From: root <root@green-clover.iinteractive.com> Date: Sun, 19 Apr 2009 15:51:39 +0000 (-0400) Subject: import moose website X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=720accfe768c0af3dfbe188975e79a925f68f995;p=gitmo%2Fmoose-htdocs.git import moose website --- 720accfe768c0af3dfbe188975e79a925f68f995 diff --git a/Moose.pdf b/Moose.pdf new file mode 100644 index 0000000..358b420 Binary files /dev/null and b/Moose.pdf differ diff --git a/Moose_YAPC_Asia_2008/.practical_moose.s5.swp b/Moose_YAPC_Asia_2008/.practical_moose.s5.swp new file mode 100644 index 0000000..a0430c8 Binary files /dev/null and b/Moose_YAPC_Asia_2008/.practical_moose.s5.swp differ diff --git a/Moose_YAPC_Asia_2008/practical_moose.html b/Moose_YAPC_Asia_2008/practical_moose.html new file mode 100644 index 0000000..cec8138 --- /dev/null +++ b/Moose_YAPC_Asia_2008/practical_moose.html @@ -0,0 +1,1275 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + +<head> +<title>Moose</title> +<!-- metadata --> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> +<meta name="generator" content="TextMate/S5" /> +<meta name="version" content="S5 1.2a2" /> +<meta name="presdate" content="2008" /> +<meta name="author" content="Yuval Kogman" /> +<meta name="company" content="" /> +<!-- configuration parameters --> +<meta name="defaultView" content="slideshow" /> +<meta name="controlVis" content="visible" /> +<!-- style sheet links --> +<link rel="stylesheet" href="./ui/moose/slides.css" type="text/css" media="projection" id="slideProj" /> +<link rel="stylesheet" href="./ui/moose/outline.css" type="text/css" media="screen" id="outlineStyle" /> +<link rel="stylesheet" href="./ui/moose/print.css" type="text/css" media="print" id="slidePrint" /> +<link rel="stylesheet" href="./ui/moose/opera.css" type="text/css" media="projection" id="operaFix" /> +<!-- embedded styles --> +<style type="text/css" media="all"> +.imgcon {width: 525px; margin: 0 auto; padding: 0; text-align: center;} +#anim {width: 270px; height: 320px; position: relative; margin-top: 0.5em;} +#anim img {position: absolute; top: 42px; left: 24px;} +img#me01 {top: 0; left: 0;} +img#me02 {left: 23px;} +img#me04 {top: 44px;} +img#me05 {top: 43px;left: 36px;} +</style> +<!-- S5 JS --> +<script src="./ui/moose/slides.js" type="text/javascript"></script> +</head> +<body> + +<div class="layout"> +<div id="controls"><!-- DO NOT EDIT --></div> +<div id="currentSlide"><!-- DO NOT EDIT --></div> +<div id="header"></div> +<div id="footer"> +<h1>YAPC::Asia::2008</h1> +<h2>Moose</h2> +</div> +<div class="topleft"></div> +<div class="topright"></div> +<div class="bottomleft"></div> +<div class="bottomright"></div> +</div> + +<div class="presentation"> + +<div class="slide"> +<h1>Moose</h1> +<h2></h2> +<h3>Yuval Kogman</h3> +<h4></h4> +</div> + + +<div class="slide"> +<h1>Moose Is Not</h1> + +<ul> +<li>Experimental</li> +<li>A toy</li> +<li>Just another accessor builder</li> +<li>A source filter</li> +<li>Perl black magic</li> +<li>Perl 6 in Perl 5</li> +</ul> + +</div> + +<div class="slide"> +<h1>Moose Is</h1> + +<ul> +<li>A complete modern object framework for Perl</li> +</ul> + +</div> + +<div class="slide"> +<h1>Moose Is</h1> + +<ul> +<li>Syntactic Sugar for <code>Class::MOP</code></li> +<li>Rich ancestry +<ul> +<li>CLOS (Common Lisp Object System)</li> +<li>Smalltalk</li> +<li>Alces latifrons</li> +<li>Perl 6</li> +<li>â¦</li> +</ul></li> +<li>Stable & Production ready</li> +<li>Polite, incremental</li> +</ul> + +</div> + +<div class="slide"> +<h1>A Simple Example</h1> + +<pre><code> +package Person; + +use strict; +use warnings; + +sub new { + my ( $class, @args ) = @_; + + @args = %{$args[0]} if @args == 1; + + return bless { + @args, + }, $class; +} + +sub name { + my ($self, @args) = @_; + $self->{name} = $args[0] if @args; + return $self->{name}; +} + +sub age { + my ($self, @args) = @_; + $self->{age} = $args[0] if @args; + return $self->{age}; +} + +1; +</code></pre> + +</div> + +<div class="slide"> +<h1>A Simple Moose Example</h1> + +<pre><code> +package Person; +use Moose; + +has name => (is => 'rw'); +has age => (is => 'rw'); + +1; +</code></pre> + +</div> + +<div class="slide"> +<h1>A Simple Moose Example (cont.)</h1> + +<ul> +<li><code>use Moose;</code> +<ul> +<li>imports keywords</li> +<li><code>use strict; use warnings;</code></li> +<li><code>@ISA = qw(Moose::Object) unless @ISA</code></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>A Simple Moose Example (cont.)</h1> + +<ul> +<li><p><code>has</code> declares attributes</p> + +<ul> +<li>generates accessors</li> +<li><code>is => 'rw'</code> â read/write accessor</li> +<li><code>is => 'ro'</code> â read only accessor</li> +<li><code>writer</code>, <code>reader</code></li> +</ul></li> +<li><p><code>new</code> inherited from <code>Moose::Object</code></p></li> +</ul> + +<div class="notes"> +<p>Now we’re going to discuss more features of the attributes</p> +</div> +</div> + +<div class="slide"> +<h1>Variations on a Moose Example</h1> + +<pre><code> +package Manager; +use Moose; + +has name => ( + is => 'rw', + isa => 'Str', + default => 'Bob' +); + +has staff => ( + is => 'ro', + isa => 'ArrayRef', + lazy => 1, + default => sub { [qw(Bob Alice Tim)] }, +); +</code></pre> + +<div class="notes"> +<p>Adds default, isa</p> +</div> +</div> + +<div class="slide"> +<h1>Variations on a Moose Example (cont.)</h1> + +<ul> +<li><p><code>default</code> is a</p> + +<ul> +<li>code reference</li> +<li>or non-reference (numbers, strings)</li> +<li>used when no parameter is given to <code>new</code></li> +</ul></li> +<li><p><code>lazy</code> delays <code>default</code></p> + +<ul> +<li>called on first usage of <code>$object->staff</code></li> +<li>not inside <code>new</code></li> +</ul></li> +</ul> + +<div class="notes"> +<p>discusses default</p> + +<p>non refs make accidental sharing hard</p> +</div> +</div> + +<div class="slide"> +<h1>Variations on a Moose Example (cont.)</h1> + +<ul> +<li><code>isa</code> specifies a type +<ul> +<li><code>Moose::Util::TypeConstraints</code> +<ul> +<li><code>Any, Item, Bool, Undef, Defined, Value, Num, Int, Str, Ref, ScalarRef, ArrayRef, HashRef, CodeRef, RegexpRef, GlobRef, FileHandle, Object and Role</code></li> +</ul></li> +<li>Types don’t need to exist</li> +</ul></li> +</ul> + +<pre><code> + has 'date' => (isa => 'DateTime'); # DWIM +</code></pre> + +<div class="notes"> +<p>isa, type constraints</p> +</div> +</div> + +<div class="slide"> +<h1>Typical Family</h1> + +<ul> +<li>Types have a hierarchy +<ul> +<li><code>Item</code> â <code>Defined</code> â <code>Ref</code> â <code>Object</code></li> +</ul></li> +</ul> + +<pre><code> + subtype 'Ref' + => as 'Defined' + => where { ref($_) }; + + subtype 'Object' + => as 'Ref' + => where { blessed($_) } +</code></pre> + +<div class="notes"> +<p>type hierarchy</p> +</div> +</div> + +<div class="slide"> +<h1>Conventional Delegates</h1> + +<pre><code> +package Employee; +use Moose; +extends qw(Person); + +has manager => ( + is => 'ro', + isa => 'Manager', + handles => { + manager_name => 'name', + coworkers => 'staff', + } +); +</code></pre> + +<ul> +<li>manager <code>handles</code> certain methods for <code>Employee</code> +<ul> +<li><code>$emp->coworkers</code> == <code>$emp->manager->staff</code></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Conventional Delegates (cont.)</h1> + +<pre><code> +has phone => ( + ... + handles => [qw(number extension)], +); +</code></pre> + +</div> + +<div class="slide"> +<h1>Conventional Delegates (cont.)</h1> + +<pre><code> +has phone => ( + ... + isa => "Phone", + handles => qr/^[a-z]w+$/, +); +</code></pre> + +</div> + +<div class="slide"> +<h1>Conventional Delegates (cont.)</h1> + +<pre><code> +has phone => ( + ... + handles => "Dialing", # a role +); +</code></pre> + +</div> + +<div class="slide"> +<h1>UnConventional Delegates</h1> + +<pre><code> +package Company; +use Moose; +use MooseX::AttributeHelpers; + +has employees => ( + metaclass => 'Collection::Array', + isa => 'ArrayRef[Employees]', + is => 'rw', + provides => { + push => 'add_employee', + pop => 'remove_employee', + count => 'number_of_employees', + empty => 'any_employees', + }, +); +</code></pre> + +</div> + +<div class="slide"> +<h1>Modified Methods</h1> + +<pre><code> +before 'employees' => sub { warn 'calling employees' }; + +after 'employees' => sub { warn 'finished calling employees' }; +</code></pre> + +<ul> +<li>Pre/Post hooks +<ul> +<li>Get a copy of <code>@_</code></li> +<li>Return value is ignored</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Modified Methods (cont.)</h1> + +<pre><code> +around 'employees' => sub { + my ($next, $self, @args) = @_; + ... + my @return = $self->$next(@args); + ... + return @return; +}; +</code></pre> + +</div> + +<div class="slide"> +<h1>Modified Methods (cont.)</h1> + +<pre><code> +package Employee; +use Moose; + +sub do_work { + my $self = shift; + + $self->punch_in; + + inner(); # call subclass here + + $self->punch_out; +} +</code></pre> + +</div> + +<div class="slide"> +<h1>Modified Methods (cont.)</h1> + +<pre><code> +package Employee::Chef; +use Moose; + +extends qw(Employee); + +augment do_work => sub { + my $self = shift; + + while ( @burgers ) { + $self->flip_burger(shift @burgers); + } +}; + +$chef->do_work; # punch in, flip burgers, punch out +</code></pre> + +</div> + +<div class="slide"> +<h1>Some Type of Coercion</h1> + +<pre><code> +package Employee; +use Moose; +use Moose::Util::TypeConstraints; +extends qw(Person); + +class_type 'Manager'; + +coerce 'Manager' => ( + from 'Str' => via { Manager->new( name => $_ ) }, +); + +has manager => ( + is => 'ro', + isa => 'Manager', + required => 1, + coerce => 1, +); +</code></pre> + +</div> + +<div class="slide"> +<h1>Some Type of Coercion (cont.)</h1> + +<pre><code> +# import type constraint keywords +use Moose::Util::TypeConstraints; + + +# define Manager, a subtype of Object +class_type "Manager"; + + +# define the conversion +... via { Manager->new( name => $_ ) } + + +# enable it per attribute +has manager => ( + ... + coerce => 1, +); +</code></pre> + +<div class="notes"> +<p>breakdown of the example</p> + +<p>class types are automatically created for all Moose classes</p> +</div> +</div> + +<div class="slide"> +<h1>Some Type of Digression</h1> + +<pre><code> +has employees => ( + is => 'rw', + isa => 'ArrayRef[Employee]', +); + +has shopping_carts => ( + is => 'rw', + isa => 'ArrayRef[ArrayRef[ShinyBead]]' +); +</code></pre> + +<div class="notes"> +<p>Going to go into features of the type system for a bit</p> + +<p>Parametrized types</p> +</div> +</div> + +<div class="slide"> +<h1>Some Type of Digression (cont.)</h1> + +<pre><code> +has language => ( + is => 'rw', + isa => 'English | Welsh | Scots | Gaelic', +); + +has member => ( + is => 'rw', + isa => 'Employee | ArrayRef[ Employee | Group ]', +); +</code></pre> + +<div class="notes"> +<p>Union types</p> +</div> +</div> + +<div class="slide"> +<h1>Some Type of Digression (cont.)</h1> + +<pre><code> +package Foo; +use Moose; +use Moose::Util::TypeConstraints; + +use Test::Deep qw(eq_deeply ...); + +type 'SomethingTricky' => where { + eq_deeply( $_, ... ); +}; + +has 'bar' => ( + is => 'rw', + isa => 'SomethingTricky', +); +</code></pre> + +<div class="notes"> +<p>Test::Deep custom validator</p> + +<p>Can use any validation from the CPAN</p> +</div> +</div> + +<div class="slide"> +<h1>Some Parametrized Type of Coercion</h1> + +<pre><code> +use Moose::Util::TypeConstraints; + +subtype 'ArrayRef[Employee]' => as 'ArrayRef'; + +coerce 'ArrayRef[Employee]' => ( + from 'ArrayRef[Str]' via { + [ map { Employee->new( name => $_ ) } @$_ ] + }, +); + +has staff => ( + isa => 'ArrayRef[Employee]', + coerce => 1, +); +</code></pre> + +<div class="notes"> +<p>coerce parametrized ArrayRef[Employee] from ArrayRef[Str]</p> +</div> +</div> + +<div class="slide"> +<h1>Role of the Moose </h1> + +<ul> +<li>A role is like a⦠+<ul> +<li>Java Interface: safe</li> +<li>mixin: useful</li> +</ul></li> +<li>A role is for small reusable behaviors +<ul> +<li>better than using a multiple inheritence</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<ul> +<li>Roles on the CPAN: +<ul> +<li><code>MooseX::Clone</code> - Flexible <code>clone</code> method</li> +<li><code>MooseX::Storage</code> - Flexible serialization</li> +<li><code>MooseX::Getopt</code> - <code>@ARGV</code> aware constructor</li> +<li><code>MooseX::LogDispatch</code> - <code>$self->logger->info("something happenned")</code></li> +<li><code>MooseX::Param</code> - <code>param</code> method like <code>CGI.pm</code>’s,</li> +</ul></li> +</ul> + +<div class="notes"> +<p>Some examples of small reusable behaviors</p> + +<p>Param is good for interacting with e.g. CGI::Expand or similar modules</p> +</div> +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<pre><code> +package Minion; +use Moose; + +extends qw(Employee); + +with qw(Salaried::Hourly); + + +package Boss; +use Moose; + +extends qw(Employee); + +with qw(Salaried::Monthly); + +</code></pre> + +<ul> +<li><code>with</code> adds roles into your class +<ul> +<li><code>Salaried::Hourly</code> was added to <code>Minion</code></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<pre><code> +package Salaried; +use Moose::Role; + +requires 'paycheck_amount'; +</code></pre> + +<ul> +<li>Just an interface</li> +</ul> + +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<pre><code> +package Salaried::Hourly; +use Moose::Role; + +with qw(Salaried); + +has hourly_rate => ( + isa => "Num", + is => "rw", + required => 1, +); + +has logged_hours => ( + isa => "Num", + is => "rw", + default => 0, +); + +# satisfy the Salaried interface: +sub paycheck_amount { + my $self = shift; + $self->logged_hours * $self->hourly_rate; +} + +</code></pre> + +<ul> +<li>More than an interface</li> +</ul> + +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<ul> +<li>More than Java Interfaces +<ul> +<li>Interfaces are behavior “contracts”</li> +<li>Roles can also have code</li> +</ul></li> +</ul> + +<div class="notes"> +<p>roles can have attributes and methods +roles provide behavior, not just interface</p> +</div> +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<ul> +<li>Role Composition +<ul> +<li>Not inheritence</li> +<li>Symmetric</li> +<li>Unordered</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<ul> +<li>Role Composition +<ul> +<li>Less ambiguity</li> +<li>Compile time errors</li> +<li>â¦And ways to fix them</li> +</ul></li> +</ul> + +<div class="notes"> +<p>symmetric composition means no precedence - if two roles try to define the same thing you get a compile time error that needs to be resolved +multiple inheritence silently assumes you want the first class</p> + +<p>roles cause errors at compile time, unlike multiple inheritence</p> + +<p>roles also provide easy ways to fix the errors</p> +</div> +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<pre><code> +package Ballet; +use Moose::Role; + +sub dance { + pirouette(); +} + +package Punk; +use Moose::Role + +sub dance { + MOSH!!!11one(); +} + +package Foo; +use Moose; + +# KABOOM: +with qw( + Punk + Ballet +); +</code></pre> + +<div class="notes"> +<p>conflicts</p> +</div> +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<pre><code> +package Ent::Puppy; +use Moose; + +with ( + Tree => { + alias => { + bark => "tree_bark", + }, + }, + Dog => { + alias => { + bark => "bark_sound", + } + }, +); + +sub bark { + my $self = shift; + + if ( $condition ) { + $self->tree_bark; + } else { + $self->bark_sound; + } +} +</code></pre> + +<ul> +<li>Not that common in practice</li> +</ul> + +<div class="notes"> +<p>Composition parameters +Easier conflict resolution +Finer grained control</p> +</div> +</div> + +<div class="slide"> +<h1>MOPs Mean Cleanliness</h1> + +<ul> +<li>Moose is based on <code>Class::MOP</code> +<ul> +<li>Metaobject Protocol for Perl 5</li> +<li>“makes an object for everything”</li> +</ul></li> +</ul> + +<pre><code> +my $class = $obj->meta; # $obj's metaclass +my $meta = MyApp->meta; # MyApp's metaclass +my $emo = $obj->meta->meta; # even more meta! + +warn $obj->meta->name; +</code></pre> + +</div> + +<div class="slide"> +<h1>Looking in From the Inside</h1> + +<pre><code> +my $metaclass = $self->meta; + +$metaclass->superclasses; + +$metaclass->linearized_isa; + +$metaclass->has_method("foo"); + +$metaclass->compute_all_applicable_attributes; + +# ⦠lots more +</code></pre> + +<div class="notes"> +<p>simple introspection</p> +</div> +</div> + +<div class="slide"> +<h1>Looking in From the Inside (cont.)</h1> + +<pre><code> +Moose::Meta::Class->create( Bar => + version => '0.01', + superclasses => [ 'Foo' ], + attributes => [ + Moose::Meta::Attribute->new( bar => ... ), + Moose::Meta::Attribute->new( baz => ... ), + ], + methods => { + calculate_bar => sub { ... }, + construct_baz => sub { ... } + }, +); + +my $anon_meta = Moose::Meta::Class->create_anon_class( ... ); +</code></pre> + +<div class="notes"> +<p>Classes can be created programmatically</p> +</div> +</div> + +<div class="slide"> +<h1>Looking in From the Inside (cont.)</h1> + +<pre><code> +has foo => ( is => "rw" ); + +__PACKAGE__->meta->add_attribute( + "foo", + is => "rw", +); +</code></pre> + +<ul> +<li>Moose is just sugar +<ul> +<li>The MOP does the hard work</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>The Metaclass Tango</h1> + +<ul> +<li>Metaclassses control class behavior</li> +</ul> + +<pre><code> +has employees => ( + metaclass => 'Collection::Array', + ... +); +</code></pre> + +<ul> +<li>custom attribute metaclasses +<ul> +<li>change how attributes work</li> +</ul></li> +<li>Many customizable parts +<ul> +<li><code>Moose::Meta::Class</code>, <code>Moose::Meta::Attribute,</code><code>Moose::Meta::Method</code>, <code>Moose::Meta::Method::Accessor</code> <code>Moose::Meta::Instance</code>, <code>Moose::Meta::Role</code>, <code>Moose::Meta::TypeConstraint</code>, â¦,</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Working in the Meta Frame</h1> + +<ul> +<li><code>$work</code> project:</li> +<li>CMS for a flash website</li> +<li>Content is in XML</li> +</ul> + +</div> + +<div class="slide"> +<h1>Working in the Meta Frame (cont.)</h1> + +<ul> +<li>Step 1. use Moose</li> +<li>Step 2. ???</li> +<li>Step 3. Profit!</li> +</ul> + +</div> + +<div class="slide"> +<h1>Working in the Meta Frame (cont.)</h1> + +<ul> +<li>Step 2.1. Client’s XML schemas â Moose classes +<ul> +<li>Automatic class definitions</li> +<li>High level objects in runtime</li> +<li>XML storage backed +<ul> +<li>SAX â Moose</li> +<li>Moose â SAX</li> +</ul></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Working in the Meta Frame (cont.)</h1> + +<ul> +<li>Step 2.2. Meta descriptions +<ul> +<li>Extend the metaclasses</li> +<li>Embed additional information +<ul> +<li>field types</li> +<li>access control</li> +</ul></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Working in the Meta Frame (cont.)</h1> + +<ul> +<li>Step 2.3 Introspection goodness +<ul> +<li>Generic web frontend</li> +<li>Object introspection based +<ul> +<li>HTML view</li> +<li>Editing widgets</li> +</ul></li> +<li>Clean, extensible</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Drawbacks of Moose</h1> + +<ul> +<li>Load time +<ul> +<li><code>MooseX::Compile</code> is in the works</li> +</ul></li> +<li>Some features are slow +<ul> +<li>but you only pay for what you use</li> +</ul></li> +<li>Extending non-Hash based classes is tricky. +<ul> +<li>but possible: <code>MooseX::GlobRef::Object</code></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Benefits of Moose</h1> + +<ul> +<li>Less boilerplate +<ul> +<li>attribute storage/access</li> +<li>construction</li> +<li>destruction</li> +<li>verification</li> +<li>â¦</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Benefits of Moose (cont.)</h1> + +<ul> +<li>Shorter +<ul> +<li>less reading</li> +<li>less writing</li> +<li>less code means fewer bugs</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Benefits of Moose (cont.)</h1> + +<ul> +<li>Less testing +<ul> +<li>Moose is very well tested +<ul> +<li>no need to check accessor behavior, etc</li> +</ul></li> +<li>focus on your code’s purpose +<ul> +<li>not that it is “assembled” correctly</li> +<li>http://c2.com/cgi/wiki?IntentionNotAlgorithm</li> +</ul></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Benefits of Moose (cont.)</h1> + +<ul> +<li>More readable +<ul> +<li>declarative style is self documenting</li> +<li>good signal to noise ratio</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Benefits of Moose (cont.)</h1> + +<ul> +<li>Meta object protocol +<ul> +<li>Cleans up Perl’s OO</li> +<li>Provides introspection</li> +<li>Enables powerful abstractions</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Benefits of Moose (cont.)</h1> + +<ul> +<li>It’s the new black +<ul> +<li>All the cool kids hang out on #moose</li> +<li>Smart sounding buzzwords</li> +<li>Chicks dig antlers</li> +<li>Ruby is so 2007</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Bonus Material</h1> + +</div> + +<div class="slide"> +<h1>Autobox</h1> + +<pre><code> +package Units::Bytes; +use Moose::Role; +use Moose::Autobox; + +sub bytes { $_[0] } +sub kilobytes { $_[0] * 1024 } +sub megabytes { $_[0] * 1024->kilobytes } +sub gigabytes { $_[0] * 1024->megabytes } +sub terabytes { $_[0] * 1024->gigabytes } + +Moose::Autobox->mixin_additional_role( + SCALAR => 'Units::Bytes', +); +</code></pre> + +</div> + +<div class="slide"> +<h1>Autobox (cont.)</h1> + +<pre><code> +use Units::Bytes; +use Moose::Autobox; # autoboxing is lexical + +is(5->bytes, 5, '... got 5 bytes'); +is(5->kilobytes, 5120, '... got 5 kilobytes'); +is(2->megabytes, 2097152, '... got 2 megabytes'); +is(1->gigabytes, 1073741824, '... got 1 gigabyte'); +is(2->terabytes, 2199023255552, '... got 2 terabytes'); +</code></pre> + +</div> + +<div class="slide"> +<h1>perl -Moose</h1> + +<ul> +<li>Moose One Liners with <code>oose.pm</code></li> +</ul> + +<pre><code> +perl -Moose -e 'has foo => ( is=> "rw" ); Class->new( foo => 1 )' +</code></pre> + +<ul> +<li>Useful for testing if something works</li> +<li>Helpful on IRC</li> +<li><code>Devel::REPL</code> is cooler though ;-)</li> +</ul> + +</div> + +<div class="slide"> +<h1>MooseX::POE</h1> + +<pre><code> +package Counter; +use MooseX::POE; +use MooseX::AttributeHelpers; + +has count => ( + traits => [qw(Counter)], + provides => { inc => "increment_count" }, +); + +sub START { + shift->yield('increment'); +} + +event increment => sub { + my $self = shift; + + warn "Count is now " . $self->count; + + $self->increment_count; + $self->yield('increment') unless $self->count > 3; +}; + +Counter->new( count => 0 ); +POE::Kernel->run(); +</code></pre> + +<ul> +<li>PoCos made easy</li> +<li>Every object has a <code>POE::Session</code></li> +<li><code>event</code> declares POE object states</li> +</ul> + +</div> + +<div class="slide"> +<h1>Fin</h1> + +<ul> +<li><p>Slides written by:</p> + +<ul> +<li>Chris Prather</li> +<li>Stevan Little</li> +<li>Robert Boone</li> +</ul></li> +<li><p>Slides deleted by:</p> + +<ul> +<li>Yuval Kogman</li> +</ul></li> +</ul> + +</div> + + +</div> + +</body> +</html> diff --git a/Moose_YAPC_Asia_2008/practical_moose.s5 b/Moose_YAPC_Asia_2008/practical_moose.s5 new file mode 100644 index 0000000..df65e4d --- /dev/null +++ b/Moose_YAPC_Asia_2008/practical_moose.s5 @@ -0,0 +1,1057 @@ +Title: Moose +Location: YAPC::Asia::2008 +Presenter: Yuval Kogman +Date: 2008 +Theme: moose + +Moose Is Not +============ + +* Experimental +* A toy +* Just another accessor builder +* A source filter +* Perl black magic +* Perl 6 in Perl 5 + +â------â------â------â------â------â------â------â------â------â------ + +Moose Is +======== + +* A complete modern object framework for Perl + +â------â------â------â------â------â------â------â------â------â------ + +Moose Is +======== + +* Syntactic Sugar for `Class::MOP` +* Rich ancestry + * CLOS (Common Lisp Object System) + * Smalltalk + * Alces latifrons + * Perl 6 + * ⦠+* Stable & Production ready +* Polite, incremental + +â------â------â------â------â------â------â------â------â------â------ + +A Simple Example +================ + +<pre><code> +package Person; + +use strict; +use warnings; + +sub new { + my ( $class, @args ) = @_; + + @args = %{$args[0]} if @args == 1; + + return bless { + @args, + }, $class; +} + +sub name { + my ($self, @args) = @_; + $self->{name} = $args[0] if @args; + return $self->{name}; +} + +sub age { + my ($self, @args) = @_; + $self->{age} = $args[0] if @args; + return $self->{age}; +} + +1; +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +A Simple Moose Example +====================== + +<pre><code> +package Person; +use Moose; + +has name => (is => 'rw'); +has age => (is => 'rw'); + +1; +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +A Simple Moose Example (cont.) +============================== + +* `use Moose;` + * imports keywords + * `use strict; use warnings;` + * `@ISA = qw(Moose::Object) unless @ISA` + +â------â------â------â------â------â------â------â------â------â------ + +A Simple Moose Example (cont.) +============================== + +* `has` declares attributes + * generates accessors + * `is => 'rw'` â read/write accessor + * `is => 'ro'` â read only accessor + * `writer`, `reader` + +* `new` inherited from `Moose::Object` + + +########## + +Now we're going to discuss more features of the attributes + +â------â------â------â------â------â------â------â------â------â------ + +Variations on a Moose Example +============================= + +<pre><code> +package Manager; +use Moose; + +has name => ( + is => 'rw', + isa => 'Str', + default => 'Bob' +); + +has staff => ( + is => 'ro', + isa => 'ArrayRef', + lazy => 1, + default => sub { [qw(Bob Alice Tim)] }, +); +</code></pre> +########## + +Adds default, isa + +â------â------â------â------â------â------â------â------â------â------ + +Variations on a Moose Example (cont.) +===================================== + +* `default` is a + * code reference + * or non-reference (numbers, strings) + * used when no parameter is given to `new` + +* `lazy` delays `default` + * called on first usage of `$object->staff` + * not inside `new` + +########## +discusses default + +non refs make accidental sharing hard + +â------â------â------â------â------â------â------â------â------â------ + +Variations on a Moose Example (cont.) +===================================== + +* `isa` specifies a type + * `Moose::Util::TypeConstraints` + * `Any, Item, Bool, Undef, Defined, Value, Num, Int, Str, Ref, ScalarRef, ArrayRef, HashRef, CodeRef, RegexpRef, GlobRef, FileHandle, Object and Role` + * Types don't need to exist +<pre><code> + has 'date' => (isa => 'DateTime'); # DWIM +</code></pre> +########## + +isa, type constraints + +â------â------â------â------â------â------â------â------â------â------ + +Typical Family +============== + +* Types have a hierarchy + * `Item` â `Defined` â `Ref` â `Object` + +<pre><code> + subtype 'Ref' + => as 'Defined' + => where { ref($_) }; + + subtype 'Object' + => as 'Ref' + => where { blessed($_) } +</code></pre> +########## + +type hierarchy + +â------â------â------â------â------â------â------â------â------â------ + +Conventional Delegates +====================== + +<pre><code> +package Employee; +use Moose; +extends qw(Person); + +has manager => ( + is => 'ro', + isa => 'Manager', + handles => { + manager_name => 'name', + coworkers => 'staff', + } +); +</code></pre> + +* manager `handles` certain methods for `Employee` + * `$emp->coworkers` == `$emp->manager->staff ` + +â------â------â------â------â------â------â------â------â------â------ + +Conventional Delegates (cont.) +============================== + +<pre><code> +has phone => ( + ... + handles => [qw(number extension)], +); +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +Conventional Delegates (cont.) +============================== + +<pre><code> +has phone => ( + ... + isa => "Phone", + handles => qr/^[a-z]\w+$/, +); +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +Conventional Delegates (cont.) +============================== + +<pre><code> +has phone => ( + ... + handles => "Dialing", # a role +); +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +UnConventional Delegates +======================== + +<pre><code> +package Company; +use Moose; +use MooseX::AttributeHelpers; + +has employees => ( + metaclass => 'Collection::Array', + isa => 'ArrayRef[Employees]', + is => 'rw', + provides => { + push => 'add_employee', + pop => 'remove_employee', + count => 'number_of_employees', + empty => 'any_employees', + }, +); +</code></pre> +â------â------â------â------â------â------â------â------â------â------ + +Modified Methods +================ + +<pre><code> +before 'employees' => sub { warn 'calling employees' }; + +after 'employees' => sub { warn 'finished calling employees' }; +</code></pre> + +* Pre/Post hooks + * Get a copy of `@_` + * Return value is ignored + +â------â------â------â------â------â------â------â------â------â------ + +Modified Methods (cont.) +======================== + +<pre><code> +around 'employees' => sub { + my ($next, $self, @args) = @_; + ... + my @return = $self->$next(@args); + ... + return @return; +}; +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +Modified Methods (cont.) +======================== + +<pre><code> +package Employee; +use Moose; + +sub do_work { + my $self = shift; + + $self->punch_in; + + inner(); # call subclass here + + $self->punch_out; +} +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +Modified Methods (cont.) +======================== + +<pre><code> +package Employee::Chef; +use Moose; + +extends qw(Employee); + +augment do_work => sub { + my $self = shift; + + while ( @burgers ) { + $self->flip_burger(shift @burgers); + } +}; + +$chef->do_work; # punch in, flip burgers, punch out +</code></pre> +â------â------â------â------â------â------â------â------â------â------ + +Some Type of Coercion +===================== + +<pre><code> +package Employee; +use Moose; +use Moose::Util::TypeConstraints; +extends qw(Person); + +class_type 'Manager'; + +coerce 'Manager' => ( + from 'Str' => via { Manager->new( name => $_ ) }, +); + +has manager => ( + is => 'ro', + isa => 'Manager', + required => 1, + coerce => 1, +); +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +Some Type of Coercion (cont.) +============================= + +<pre><code> +# import type constraint keywords +use Moose::Util::TypeConstraints; + + +# define Manager, a subtype of Object +class_type "Manager"; + + +# define the conversion +... via { Manager->new( name => $_ ) } + + +# enable it per attribute +has manager => ( + ... + coerce => 1, +); +</code></pre> + +########## + +breakdown of the example + +class types are automatically created for all Moose classes + +â------â------â------â------â------â------â------â------â------â------ + +Some Type of Digression +======================= + +<pre><code> +has employees => ( + is => 'rw', + isa => 'ArrayRef[Employee]', +); + +has shopping_carts => ( + is => 'rw', + isa => 'ArrayRef[ArrayRef[ShinyBead]]' +); +</code></pre> + +########## + +Going to go into features of the type system for a bit + +Parametrized types + +â------â------â------â------â------â------â------â------â------â------ +Some Type of Digression (cont.) +=============================== + +<pre><code> +has language => ( + is => 'rw', + isa => 'English | Welsh | Scots | Gaelic', +); + +has member => ( + is => 'rw', + isa => 'Employee | ArrayRef[ Employee | Group ]', +); +</code></pre> + +########## + +Union types + +â------â------â------â------â------â------â------â------â------â------ + +Some Type of Digression (cont.) +=============================== + +<pre><code> +package Foo; +use Moose; +use Moose::Util::TypeConstraints; + +use Test::Deep qw(eq_deeply ...); + +type 'SomethingTricky' => where { + eq_deeply( $_, ... ); +}; + +has 'bar' => ( + is => 'rw', + isa => 'SomethingTricky', +); +</code></pre> + +########## + +Test::Deep custom validator + +Can use any validation from the CPAN + +â------â------â------â------â------â------â------â------â------â------ + +Some Parametrized Type of Coercion +================================== + +<pre><code> +use Moose::Util::TypeConstraints; + +subtype 'ArrayRef[Employee]' => as 'ArrayRef'; + +coerce 'ArrayRef[Employee]' => ( + from 'ArrayRef[Str]' via { + [ map { Employee->new( name => $_ ) } @$_ ] + }, +); + +has staff => ( + isa => 'ArrayRef[Employee]', + coerce => 1, +); +</code></pre> + +########## + +coerce parametrized ArrayRef[Employee] from ArrayRef[Str] + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose +================= + +* A role is like a⦠+ * Java Interface: safe + * mixin: useful +* A role is for small reusable behaviors + * better than using a multiple inheritence + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +* Roles on the CPAN: + * `MooseX::Clone` - Flexible `clone` method + * `MooseX::Storage` - Flexible serialization + * `MooseX::Getopt` - `@ARGV` aware constructor + * `MooseX::LogDispatch` - `$self->logger->info("something happenned")` + * `MooseX::Param` - `param` method like `CGI.pm`'s, + +########## + +Some examples of small reusable behaviors + +Param is good for interacting with e.g. CGI::Expand or similar modules + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +<pre><code> +package Minion; +use Moose; + +extends qw(Employee); + +with qw(Salaried::Hourly); + + +package Boss; +use Moose; + +extends qw(Employee); + +with qw(Salaried::Monthly); + +</code></pre> + +* `with` adds roles into your class + * `Salaried::Hourly` was added to `Minion` + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +<pre><code> +package Salaried; +use Moose::Role; + +requires 'paycheck_amount'; +</code></pre> + +* Just an interface + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +<pre><code> +package Salaried::Hourly; +use Moose::Role; + +with qw(Salaried); + +has hourly_rate => ( + isa => "Num", + is => "rw", + required => 1, +); + +has logged_hours => ( + isa => "Num", + is => "rw", + default => 0, +); + +# satisfy the Salaried interface: +sub paycheck_amount { + my $self = shift; + $self->logged_hours * $self->hourly_rate; +} + +</code></pre> + +* More than an interface + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +* More than Java Interfaces + * Interfaces are behavior "contracts" + * Roles can also have code + +########## +roles can have attributes and methods +roles provide behavior, not just interface + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +* Role Composition + * Not inheritence + * Symmetric + * Unordered + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +* Role Composition + * Less ambiguity + * Compile time errors + * â¦And ways to fix them + +########## +symmetric composition means no precedence - if two roles try to define the same thing you get a compile time error that needs to be resolved +multiple inheritence silently assumes you want the first class + +roles cause errors at compile time, unlike multiple inheritence + +roles also provide easy ways to fix the errors + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +<pre><code> +package Ballet; +use Moose::Role; + +sub dance { + pirouette(); +} + +package Punk; +use Moose::Role + +sub dance { + MOSH!!!11one(); +} + +package Foo; +use Moose; + +# KABOOM: +with qw( + Punk + Ballet +); +</code></pre> + +########## + +conflicts + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +<pre><code> +package Ent::Puppy; +use Moose; + +with ( + Tree => { + alias => { + bark => "tree_bark", + }, + }, + Dog => { + alias => { + bark => "bark_sound", + } + }, +); + +sub bark { + my $self = shift; + + if ( $condition ) { + $self->tree_bark; + } else { + $self->bark_sound; + } +} +</code></pre> + +* Not that common in practice + +########## + +Composition parameters +Easier conflict resolution +Finer grained control + +â------â------â------â------â------â------â------â------â------â------ + +MOPs Mean Cleanliness +===================== + +* Moose is based on `Class::MOP` + * Metaobject Protocol for Perl 5 + * "makes an object for everything" + +<pre><code> +my $class = $obj->meta; # $obj's metaclass +my $meta = MyApp->meta; # MyApp's metaclass +my $emo = $obj->meta->meta; # even more meta! + +warn $obj->meta->name; +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +Looking in From the Inside +=========================== + +<pre><code> +my $metaclass = $self->meta; + +$metaclass->superclasses; + +$metaclass->linearized_isa; + +$metaclass->has_method("foo"); + +$metaclass->compute_all_applicable_attributes; + +# ⦠lots more +</code></pre> +########## + +simple introspection + +â------â------â------â------â------â------â------â------â------â------ + +Looking in From the Inside (cont.) +================================== + +<pre><code> +Moose::Meta::Class->create( Bar => + version => '0.01', + superclasses => [ 'Foo' ], + attributes => [ + Moose::Meta::Attribute->new( bar => ... ), + Moose::Meta::Attribute->new( baz => ... ), + ], + methods => { + calculate_bar => sub { ... }, + construct_baz => sub { ... } + }, +); + +my $anon_meta = Moose::Meta::Class->create_anon_class( ... ); +</code></pre> + +########## + +Classes can be created programmatically +â------â------â------â------â------â------â------â------â------â------ + +Looking in From the Inside (cont.) +================================== + +<pre><code> +has foo => ( is => "rw" ); + +__PACKAGE__->meta->add_attribute( + "foo", + is => "rw", +); +</code></pre> + +* Moose is just sugar + * The MOP does the hard work + +â------â------â------â------â------â------â------â------â------â------ + +The Metaclass Tango +=================== + +* Metaclassses control class behavior + +<pre><code> +has employees => ( + metaclass => 'Collection::Array', + ... +); +</code></pre> + +* custom attribute metaclasses + * change how attributes work +* Many customizable parts + * `Moose::Meta::Class`, `Moose::Meta::Attribute, ``Moose::Meta::Method`, `Moose::Meta::Method::Accessor` `Moose::Meta::Instance`, `Moose::Meta::Role`, `Moose::Meta::TypeConstraint`, â¦, + +â------â------â------â------â------â------â------â------â------â------ + +Working in the Meta Frame +========================= + +* `$work` project: +* CMS for a flash website +* Content is in XML + +â------â------â------â------â------â------â------â------â------â------ + +Working in the Meta Frame (cont.) +================================= + +* Step 1. use Moose +* Step 2. ??? +* Step 3. Profit! + +â------â------â------â------â------â------â------â------â------â------ + +Working in the Meta Frame (cont.) +================================= + +* Step 2.1. Client's XML schemas â Moose classes + * Automatic class definitions + * High level objects in runtime + * XML storage backed + * SAX â Moose + * Moose â SAX + +â------â------â------â------â------â------â------â------â------â------ + +Working in the Meta Frame (cont.) +================================= + +* Step 2.2. Meta descriptions + * Extend the metaclasses + * Embed additional information + * field types + * access control + +â------â------â------â------â------â------â------â------â------â------ + +Working in the Meta Frame (cont.) +================================= + +* Step 2.3 Introspection goodness + * Generic web frontend + * Object introspection based + * HTML view + * Editing widgets + * Clean, extensible + +â------â------â------â------â------â------â------â------â------â------ + +Drawbacks of Moose +================== + +* Load time + * `MooseX::Compile` is in the works +* Some features are slow + * but you only pay for what you use +* Extending non-Hash based classes is tricky. + * but possible: `MooseX::GlobRef::Object` + +â------â------â------â------â------â------â------â------â------â------ + +Benefits of Moose +================= + +* Less boilerplate + * attribute storage/access + * construction + * destruction + * verification + * ⦠+ +â------â------â------â------â------â------â------â------â------â------ + +Benefits of Moose (cont.) +========================= + +* Shorter + * less reading + * less writing + * less code means fewer bugs + +â------â------â------â------â------â------â------â------â------â------ + +Benefits of Moose (cont.) +========================= + +* Less testing + * Moose is very well tested + * no need to check accessor behavior, etc + * focus on your code's purpose + * not that it is "assembled" correctly + * http://c2.com/cgi/wiki?IntentionNotAlgorithm + +â------â------â------â------â------â------â------â------â------â------ + +Benefits of Moose (cont.) +========================= + +* More readable + * declarative style is self documenting + * good signal to noise ratio + +â------â------â------â------â------â------â------â------â------â------ + +Benefits of Moose (cont.) +========================= + +* Meta object protocol + * Cleans up Perl's OO + * Provides introspection + * Enables powerful abstractions + +â------â------â------â------â------â------â------â------â------â------ + +Benefits of Moose (cont.) +========================= + +* It's the new black + * All the cool kids hang out on #moose + * Smart sounding buzzwords + * Chicks dig antlers + * Ruby is so 2007 + +â------â------â------â------â------â------â------â------â------â------ + +Bonus Material +============== + +â------â------â------â------â------â------â------â------â------â------ + +Autobox +======= + +<pre><code> +package Units::Bytes; +use Moose::Role; +use Moose::Autobox; + +sub bytes { $_[0] } +sub kilobytes { $_[0] * 1024 } +sub megabytes { $_[0] * 1024->kilobytes } +sub gigabytes { $_[0] * 1024->megabytes } +sub terabytes { $_[0] * 1024->gigabytes } + +Moose::Autobox->mixin_additional_role( + SCALAR => 'Units::Bytes', +); +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +Autobox (cont.) +=============== + +<pre><code> +use Units::Bytes; +use Moose::Autobox; # autoboxing is lexical + +is(5->bytes, 5, '... got 5 bytes'); +is(5->kilobytes, 5120, '... got 5 kilobytes'); +is(2->megabytes, 2097152, '... got 2 megabytes'); +is(1->gigabytes, 1073741824, '... got 1 gigabyte'); +is(2->terabytes, 2199023255552, '... got 2 terabytes'); +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +perl -Moose +=========== + +* Moose One Liners with `oose.pm` + +<pre><code> +perl -Moose -e 'has foo => ( is=> "rw" ); Class->new( foo => 1 )' +</code></pre> + +* Useful for testing if something works +* Helpful on IRC +* `Devel::REPL` is cooler though ;-) + +â------â------â------â------â------â------â------â------â------â------ + +MooseX::POE +=========== + +<pre><code> +package Counter; +use MooseX::POE; +use MooseX::AttributeHelpers; + +has count => ( + traits => [qw(Counter)], + provides => { inc => "increment_count" }, +); + +sub START { + shift->yield('increment'); +} + +event increment => sub { + my $self = shift; + + warn "Count is now " . $self->count; + + $self->increment_count; + $self->yield('increment') unless $self->count > 3; +}; + +Counter->new( count => 0 ); +POE::Kernel->run(); +</code></pre> + +* PoCos made easy +* Every object has a `POE::Session` +* `event` declares POE object states + +â------â------â------â------â------â------â------â------â------â------ + +Fin +=== + +* Slides written by: + * Chris Prather + * Stevan Little + * Robert Boone + +* Slides deleted by: + * Yuval Kogman diff --git a/Moose_YAPC_Asia_2008/ui/default/blank.gif b/Moose_YAPC_Asia_2008/ui/default/blank.gif new file mode 100644 index 0000000..75b945d Binary files /dev/null and b/Moose_YAPC_Asia_2008/ui/default/blank.gif differ diff --git a/Moose_YAPC_Asia_2008/ui/default/bodybg.gif b/Moose_YAPC_Asia_2008/ui/default/bodybg.gif new file mode 100755 index 0000000..5f448a1 Binary files /dev/null and b/Moose_YAPC_Asia_2008/ui/default/bodybg.gif differ diff --git a/Moose_YAPC_Asia_2008/ui/default/framing.css b/Moose_YAPC_Asia_2008/ui/default/framing.css new file mode 100644 index 0000000..2a27daf --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/default/framing.css @@ -0,0 +1,22 @@ +/* The following styles size, place, and layer the slide components. + Edit these if you want to change the overall slide layout. + The commented lines can be uncommented (and modified, if necessary) + to help you with the rearrangement process. */ + +/* target = 1024x768 */ + +div#header, div#footer, .slide {width: 100%; top: 0; left: 0;} +div#header {top: 0; height: 3em; z-index: 1;} +div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;} +.slide {top: 0; width: 92%; padding: 3.5em 4% 4%; z-index: 2; list-style: none;} +div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;} +div#controls form {text-align: right; width: 100%; margin: 0;} +#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; z-index: 10;} +html>body #currentSlide {position: fixed;} + +/* +div#header {background: #FCC;} +div#footer {background: #CCF;} +div#controls {background: #BBD;} +div#currentSlide {background: #FFC;} +*/ diff --git a/Moose_YAPC_Asia_2008/ui/default/iepngfix.htc b/Moose_YAPC_Asia_2008/ui/default/iepngfix.htc new file mode 100644 index 0000000..bba2db7 --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/default/iepngfix.htc @@ -0,0 +1,42 @@ +<public:component> +<public:attach event="onpropertychange" onevent="doFix()" /> + +<script> + +// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com +// Free usage permitted as long as this notice remains intact. + +// This must be a path to a blank image. That's all the configuration you need here. +var blankImg = 'ui/default/blank.gif'; + +var f = 'DXImageTransform.Microsoft.AlphaImageLoader'; + +function filt(s, m) { + if (filters[f]) { + filters[f].enabled = s ? true : false; + if (s) with (filters[f]) { src = s; sizingMethod = m } + } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")'; +} + +function doFix() { + if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) || + (event && !/(background|src)/.test(event.propertyName))) return; + + if (tagName == 'IMG') { + if ((/\.png$/i).test(src)) { + filt(src, 'image'); // was 'scale' + src = blankImg; + } else if (src.indexOf(blankImg) < 0) filt(); + } else if (style.backgroundImage) { + if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) { + var s = RegExp.$1; + style.backgroundImage = ''; + filt(s, 'crop'); + } else filt(); + } +} + +doFix(); + +</script> +</public:component> \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008/ui/default/notes.css b/Moose_YAPC_Asia_2008/ui/default/notes.css new file mode 100644 index 0000000..5858cf2 --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/default/notes.css @@ -0,0 +1,122 @@ +/* Following are the note styles -- edit away! */ + +body { + margin: 0; + padding: 1.0em; + background: #333; + color: #FFF; + font: 2em/1.4em 'Lucida Grande', Verdana, sans-serif; +} + +div.timers { + background: #FFF; + color: #333; + border: 0.08em solid #222; + border-top-width: 1px; + border-left-width: 1px; + float: left; + padding: 0.2em; + margin: 0 0 0.5em; + position: relative; +} + +div.timers h1 { + text-align: left; + font-size: 0.6em; + line-height: 1.4em; + background-color: #FF9; + padding: 0 0.75em; + margin: 0.25em 0 0; + border: 1px solid #EE8; +} + +div.timers div.controls { + position: absolute; + right: 0.25em; + top: 0.1em; + line-height: 1em; +} + +div.timers h1 a { + text-decoration: none; + color: #000; +} + +div.timers div.controls a { + font-size: 0.5em; + padding: 0; + color: #330; +} + +div.timers a.control { + position: absolute; + text-decoration: none; + padding: 0 0.25em; + color: #AAA; + outline: 0; +} + +#minus { + left: 0.25em; +} + +#plus { + right: 0.25em; +} + +.overtime { + background: yellow; + color: red; + border: 3px solid; + padding: 0.1em 0.25em; + font-weight: bold; +} + +div.timers h2 { + font-size: 0.6em; + line-height: 1.0em; + font-weight: normal; + margin: 0 0 -0.25em; + padding-top: 0.5em; + color: #666; +} + +div.timers p {margin: 0; padding: 0 0.5em;} +div.timers form {margin: 0;} + +div.timers span.clock { + font-family: monospace; +} + +div.timers ul {margin: 0; padding: 0; list-style: none;} +div.timers li {float: left; width: 5em; margin: 0; padding: 0 0.5em; + text-align: center;} + +div#elapsed {width: 12.1em;} +div#remaining {clear: left; width: 12.1em;} +div#remaining p {text-align: center;} + +#slide, +#next, +#notes, +#nextnotes { + font-size: 0.75em; + line-height: 1.4em; + clear: left; +/* max-width: 30.0em; */ + text-shadow: 0.1em 0.1em 0.1em #111; +} + +#next {margin-top: 2.5em;} +#next, #nextnotes { + color: #999; + font-size: 0.66em; +} + +em.disclaimer { + color: #666; +} + +div.collapsed h1 {display: block; font-size: 0.33em;} +div.collapsed h1 a {display: inline;} +div.collapsed * {display: none;} diff --git a/Moose_YAPC_Asia_2008/ui/default/opera.css b/Moose_YAPC_Asia_2008/ui/default/opera.css new file mode 100644 index 0000000..9e9d2a3 --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/default/opera.css @@ -0,0 +1,7 @@ +/* DO NOT CHANGE THESE unless you really want to break Opera Show */ +.slide { + visibility: visible !important; + position: static !important; + page-break-before: always; +} +#slide0 {page-break-before: avoid;} diff --git a/Moose_YAPC_Asia_2008/ui/default/outline.css b/Moose_YAPC_Asia_2008/ui/default/outline.css new file mode 100644 index 0000000..62db519 --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/default/outline.css @@ -0,0 +1,15 @@ +/* don't change this unless you want the layout stuff to show up in the outline view! */ + +.layout div, #footer *, #controlForm * {display: none;} +#footer, #controls, #controlForm, #navLinks, #toggle { + display: block; visibility: visible; margin: 0; padding: 0;} +#toggle {float: right; padding: 0.5em;} +html>body #toggle {position: fixed; top: 0; right: 0;} + +/* making the outline look pretty-ish */ + +#slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;} +#slide0 h1 {padding-top: 1.5em;} +.slide h1 {margin: 1.5em 0 0; padding-top: 0.25em; + border-top: 1px solid #888; border-bottom: 1px solid #AAA;} +#toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;} diff --git a/Moose_YAPC_Asia_2008/ui/default/pretty.css b/Moose_YAPC_Asia_2008/ui/default/pretty.css new file mode 100644 index 0000000..838a7cf --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/default/pretty.css @@ -0,0 +1,82 @@ +/* Following are the presentation styles -- edit away! */ + +body {background: #FFF url(bodybg.gif) -16px 0 no-repeat; color: #000; font-size: 2.25em;} +:link, :visited {text-decoration: none; color: #00C;} +#controls :active {color: #88A !important;} +#controls :focus {outline: 1px dotted #227;} +h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;} +ul, pre {margin: 0; line-height: 1em;} +html, body {margin: 0; padding: 0;} + +blockquote, q {font-style: italic;} +blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;} +blockquote p {margin: 0;} +blockquote i {font-style: normal;} +blockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;} +blockquote b i {font-style: italic;} + +kbd {font-weight: bold; font-size: 1em;} +sup {font-size: smaller; line-height: 1px;} + +.slide code {padding: 2px 0.25em; font-weight: bold; color: #533;} +.slide code.bad, code del {color: red;} +.slide code.old {color: silver;} +.slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: #533; font-size: 90%;} +.slide pre code {display: block;} +.slide ul {margin-left: 5%; margin-right: 7%; list-style: disc;} +.slide li {margin-top: 0.75em; margin-right: 0;} +.slide ul ul {line-height: 1;} +.slide ul ul li {margin: .2em; font-size: 85%; list-style: square;} +.slide img.leader {display: block; margin: 0 auto;} + +div#header, div#footer {background: #005; color: #AAB; + font-family: Verdana, Helvetica, sans-serif;} +div#header {background: #005 url(bodybg.gif) -16px 0 no-repeat; + line-height: 1px;} +div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;} +#footer h1, #footer h2 {display: block; padding: 0 1em;} +#footer h2 {font-style: italic;} + +div.long {font-size: 0.75em;} +.slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1; + margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap; + font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize; + color: #DDE; background: #005;} +.slide h3 {font-size: 130%;} +h1 abbr {font-variant: small-caps;} + +div#controls {position: absolute; left: 60%; bottom: 0; + width: 40%; + text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;} +html>body div#controls {position: fixed; padding: 0; top: auto;} +#controls #navLinks a {padding: 0; margin: 0 0.5em; + background: #005; border: none; color: #779; + cursor: pointer;} +#controls #navList #jumplist {background: #DDD; color: #227;} + +#currentSlide {text-align: center; font-size: 0.5em; color: #449;} + +#slide0 {padding-top: 3.5em; font-size: 90%;} +#slide0 h1 {position: static; margin: 1em 0 0; padding: 0; + font: bold 2em Helvetica, sans-serif; white-space: normal; + color: #000; background: transparent;} +#slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;} +#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;} +#slide0 h4 {margin-top: 0; font-size: 1em;} + +ul.urls {list-style: none; display: inline; margin: 0;} +.urls li {display: inline; margin: 0;} +.note {display: none;} +.external {border-bottom: 1px dotted gray;} +html>body .external {border-bottom: none;} +.external:after {content: " \274F"; font-size: smaller; color: #77B;} + +.incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;} +img.incremental {visibility: hidden;} +.slide .current {color: #B02;} + + +/* diagnostics + +li:after {content: " [" attr(class) "]"; color: #F88;} + */ \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008/ui/default/pretty.css~ b/Moose_YAPC_Asia_2008/ui/default/pretty.css~ new file mode 100644 index 0000000..d0d1aa3 --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/default/pretty.css~ @@ -0,0 +1,86 @@ +/* Following are the presentation styles -- edit away! */ + +body {background: #FFF url(bodybg.gif) -16px 0 no-repeat; color: #000; font-size: 2.25em;} +:link, :visited {text-decoration: none; color: #00C;} +#controls :active {color: #88A !important;} +#controls :focus {outline: 1px dotted #227;} +h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;} +ul, pre {margin: 0; line-height: 1em;} +html, body {margin: 0; padding: 0;} + +blockquote, q {font-style: italic;} +blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;} +blockquote p {margin: 0;} +blockquote i {font-style: normal;} +blockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;} +blockquote b i {font-style: italic;} + +kbd {font-weight: bold; font-size: 1em;} +sup {font-size: smaller; line-height: 1px;} + +.slide code {padding: 2px 0.25em; font-weight: bold; color: #533;} +.slide code.bad, code del {color: red;} +.slide code.old {color: silver;} +.slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: #533; font-size: 90%;} +.slide pre code {display: block;} +.slide ul {margin-left: 5%; margin-right: 7%; list-style: disc;} +.slide li {margin-top: 0.75em; margin-right: 0;} +.slide ul ul {line-height: 1;} +.slide ul ul li {margin: .2em; font-size: 85%; list-style: square;} +.slide img.leader {display: block; margin: 0 auto;} + +div#header, div#footer {background: #005; color: #AAB; + font-family: Verdana, Helvetica, sans-serif;} +div#header {background: #005 url(bodybg.gif) -16px 0 no-repeat; + line-height: 1px;} +div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;} +#footer h1, #footer h2 {display: block; padding: 0 1em;} +#footer h2 {font-style: italic;} + +div.long {font-size: 0.75em;} +.slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1; + margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap; + font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize; + color: #DDE; background: #005;} +.slide h2 {position: absolute; top: 1.7em; left: 87px; z-index: 1; + margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap; + font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize; + color: #DDE; background: #005;} +.slide h3 {font-size: 130%;} +h1 abbr {font-variant: small-caps;} + +div#controls {position: absolute; left: 60%; bottom: 0; + width: 40%; + text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;} +html>body div#controls {position: fixed; padding: 0; top: auto;} +#controls #navLinks a {padding: 0; margin: 0 0.5em; + background: #005; border: none; color: #779; + cursor: pointer;} +#controls #navList #jumplist {background: #DDD; color: #227;} + +#currentSlide {text-align: center; font-size: 0.5em; color: #449;} + +#slide0 {padding-top: 3.5em; font-size: 90%;} +#slide0 h1 {position: static; margin: 1em 0 0; padding: 0; + font: bold 2em Helvetica, sans-serif; white-space: normal; + color: #000; background: transparent;} +#slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;} +#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;} +#slide0 h4 {margin-top: 0; font-size: 1em;} + +ul.urls {list-style: none; display: inline; margin: 0;} +.urls li {display: inline; margin: 0;} +.note {display: none;} +.external {border-bottom: 1px dotted gray;} +html>body .external {border-bottom: none;} +.external:after {content: " \274F"; font-size: smaller; color: #77B;} + +.incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;} +img.incremental {visibility: hidden;} +.slide .current {color: #B02;} + + +/* diagnostics + +li:after {content: " [" attr(class) "]"; color: #F88;} + */ diff --git a/Moose_YAPC_Asia_2008/ui/default/print.css b/Moose_YAPC_Asia_2008/ui/default/print.css new file mode 100644 index 0000000..e7a71d1 --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/default/print.css @@ -0,0 +1 @@ +/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */ .slide, ul {page-break-inside: avoid; visibility: visible !important;} h1 {page-break-after: avoid;} body {font-size: 12pt; background: white;} * {color: black;} #slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;} #slide0 h3 {margin: 0; padding: 0;} #slide0 h4 {margin: 0 0 0.5em; padding: 0;} #slide0 {margin-bottom: 3em;} h1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;} .extra {background: transparent !important;} div.extra, pre.extra, .example {font-size: 10pt; color: #333;} ul.extra a {font-weight: bold;} p.example {display: none;} #header {display: none;} #footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;} #footer h2, #controls {display: none;} /* The following rule keeps the layout stuff out of print. Remove at your own risk! */ .layout, .layout * {display: none !important;} \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008/ui/default/s5-core.css b/Moose_YAPC_Asia_2008/ui/default/s5-core.css new file mode 100644 index 0000000..ad1530b --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/default/s5-core.css @@ -0,0 +1,9 @@ +/* Do not edit or override these styles! The system will likely break if you do. */ + +div#header, div#footer, div#controls, .slide {position: absolute;} +html>body div#header, html>body div#footer, + html>body div#controls, html>body .slide {position: fixed;} +.handout, .notes {display: none;} +.layout {display: block;} +.slide, .hideme, .incremental {visibility: hidden;} +#slide0 {visibility: visible;} diff --git a/Moose_YAPC_Asia_2008/ui/default/slides.css b/Moose_YAPC_Asia_2008/ui/default/slides.css new file mode 100644 index 0000000..0786d7d --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/default/slides.css @@ -0,0 +1,3 @@ +@import url(s5-core.css); /* required to make the slide show run at all */ +@import url(framing.css); /* sets basic placement and size of slide components */ +@import url(pretty.css); /* stuff that makes the slides look better than blah */ \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008/ui/default/slides.js b/Moose_YAPC_Asia_2008/ui/default/slides.js new file mode 100644 index 0000000..ab2a4b2 --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/default/slides.js @@ -0,0 +1,764 @@ +// S5 v1.2a1 slides.js -- released into the Public Domain +// +// Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information +// about all the wonderful and talented contributors to this code! + +var undef; +var slideCSS = ''; +var snum = 0; +var smax = 1; +var incpos = 0; +var number = undef; +var s5mode = true; +var defaultView = 'slideshow'; +var controlVis = 'visible'; + +var s5NotesWindow; +var s5NotesWindowLoaded = false; +var previousSlide = 0; +var presentationStart = new Date(); +var slideStart = new Date(); + +var countdown = { + timer: 0, + state: 'pause', + start: new Date(), + end: 0, + remaining: 0 +}; + + +var isIE = navigator.appName == 'Microsoft Internet Explorer' && navigator.userAgent.indexOf('Opera') < 1 ? 1 : 0; +var isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0; +var isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0; + +function hasClass(object, className) { + if (!object.className) return false; + return (object.className.search('(^|\\s)' + className + '(\\s|$)') != -1); +} + +function hasValue(object, value) { + if (!object) return false; + return (object.search('(^|\\s)' + value + '(\\s|$)') != -1); +} + +function removeClass(object,className) { + if (!object || !hasClass(object,className)) return; + object.className = object.className.replace(new RegExp('(^|\\s)'+className+'(\\s|$)'), RegExp.$1+RegExp.$2); +} + +function addClass(object,className) { + if (!object || hasClass(object, className)) return; + if (object.className) { + object.className += ' '+className; + } else { + object.className = className; + } +} + +function GetElementsWithClassName(elementName,className) { + var allElements = document.getElementsByTagName(elementName); + var elemColl = new Array(); + for (var i = 0; i< allElements.length; i++) { + if (hasClass(allElements[i], className)) { + elemColl[elemColl.length] = allElements[i]; + } + } + return elemColl; +} + +function isParentOrSelf(element, id) { + if (element == null || element.nodeName=='BODY') return false; + else if (element.id == id) return true; + else return isParentOrSelf(element.parentNode, id); +} + +function nodeValue(node) { + var result = ""; + if (node.nodeType == 1) { + var children = node.childNodes; + for (var i = 0; i < children.length; ++i) { + result += nodeValue(children[i]); + } + } + else if (node.nodeType == 3) { + result = node.nodeValue; + } + return(result); +} + +function slideLabel() { + var slideColl = GetElementsWithClassName('*','slide'); + var list = document.getElementById('jumplist'); + smax = slideColl.length; + for (var n = 0; n < smax; n++) { + var obj = slideColl[n]; + + var did = 'slide' + n.toString(); + obj.setAttribute('id',did); + +// if (isOp) continue; // Opera fix (hallvord) + + var otext = ''; + var menu = obj.firstChild; + if (!menu) continue; // to cope with empty slides + while (menu && menu.nodeType == 3) { + menu = menu.nextSibling; + } + if (!menu) continue; // to cope with slides with only text nodes + + var menunodes = menu.childNodes; + for (var o = 0; o < menunodes.length; o++) { + otext += nodeValue(menunodes[o]); + } + list.options[list.length] = new Option(n + ' : ' + otext, n); + } +} + +function currentSlide() { + var cs; + if (document.getElementById) { + cs = document.getElementById('currentSlide'); + } else { + cs = document.currentSlide; + } + cs.innerHTML = '<a id="plink" href="">' + + '<span id="csHere">' + snum + '<\/span> ' + + '<span id="csSep">\/<\/span> ' + + '<span id="csTotal">' + (smax-1) + '<\/span>' + + '<\/a>' + ; + if (snum == 0) { + cs.style.visibility = 'hidden'; + } else { + cs.style.visibility = 'visible'; + } +} + +function go(step) { + if (document.getElementById('slideProj').disabled || step == 0) return; + var jl = document.getElementById('jumplist'); + var cid = 'slide' + snum; + var ce = document.getElementById(cid); + if (incrementals[snum].length > 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + removeClass(incrementals[snum][i], 'current'); + removeClass(incrementals[snum][i], 'incremental'); + } + } + if (step != 'j') { + snum += step; + lmax = smax - 1; + if (snum > lmax) snum = lmax; + if (snum < 0) snum = 0; + } else + snum = parseInt(jl.value); + var nid = 'slide' + snum; + var ne = document.getElementById(nid); + if (!ne) { + ne = document.getElementById('slide0'); + snum = 0; + } + if (step < 0) {incpos = incrementals[snum].length} else {incpos = 0;} + if (incrementals[snum].length > 0 && incpos == 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + if (hasClass(incrementals[snum][i], 'current')) + incpos = i + 1; + else + addClass(incrementals[snum][i], 'incremental'); + } + } + if (incrementals[snum].length > 0 && incpos > 0) + addClass(incrementals[snum][incpos - 1], 'current'); + if (isOp) { //hallvord + location.hash = nid; + } else { + ce.style.visibility = 'hidden'; + ne.style.visibility = 'visible'; + } // /hallvord + jl.selectedIndex = snum; + currentSlide(); + loadNote(); + permaLink(); + number = undef; +} + +function goTo(target) { + if (target >= smax || target == snum) return; + go(target - snum); +} + +function subgo(step) { + if (step > 0) { + removeClass(incrementals[snum][incpos - 1],'current'); + removeClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos],'current'); + incpos++; + } else { + incpos--; + removeClass(incrementals[snum][incpos],'current'); + addClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos - 1],'current'); + } + loadNote(); +} + +function toggle() { + var slideColl = GetElementsWithClassName('*','slide'); + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + if (!slides.disabled) { + slides.disabled = true; + outline.disabled = false; + s5mode = false; + fontSize('1em'); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'visible'; + } + } else { + slides.disabled = false; + outline.disabled = true; + s5mode = true; + fontScale(); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'hidden'; + } + slideColl[snum].style.visibility = 'visible'; + } +} + +function showHide(action) { + var obj = GetElementsWithClassName('*','hideme')[0]; + switch (action) { + case 's': obj.style.visibility = 'visible'; break; + case 'h': obj.style.visibility = 'hidden'; break; + case 'k': + if (obj.style.visibility != 'visible') { + obj.style.visibility = 'visible'; + } else { + obj.style.visibility = 'hidden'; + } + break; + } +} + +// 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/) +function keys(key) { + if (!key) { + key = event; + key.which = key.keyCode; + } + if (key.which == 84) { + toggle(); + return; + } + if (s5mode) { + switch (key.which) { + case 10: // return + case 13: // enter + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + if(number != undef) { + goTo(number); + break; + } + case 32: // spacebar + case 34: // page down + case 39: // rightkey + case 40: // downkey + if(number != undef) { + go(number); + } else if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + break; + case 33: // page up + case 37: // leftkey + case 38: // upkey + if(number != undef) { + go(-1 * number); + } else if (!incrementals[snum] || incpos <= 0) { + go(-1); + } else { + subgo(-1); + } + break; + case 36: // home + goTo(0); + break; + case 35: // end + goTo(smax-1); + break; + case 67: // c + showHide('k'); + break; + case 78: // n + createNotesWindow(); + break; + } + if (key.which < 48 || key.which > 57) { + number = undef; + } else { + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + number = (((number != undef) ? number : 0) * 10) + (key.which - 48); + } + } + return false; +} + +function clicker(e) { + number = undef; + var target; + if (window.event) { + target = window.event.srcElement; + e = window.event; + } else target = e.target; + if (target.href != null || hasValue(target.rel, 'external') || isParentOrSelf(target, 'controls') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object')) return true; + if (!e.which || e.which == 1) { + if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + } +} + +function findSlide(hash) { + var target = null; + var slides = GetElementsWithClassName('*','slide'); + for (var i = 0; i < slides.length; i++) { + var targetSlide = slides[i]; + if ( (targetSlide.name && targetSlide.name == hash) + || (targetSlide.id && targetSlide.id == hash) ) { + target = targetSlide; + break; + } + } + while(target != null && target.nodeName != 'BODY') { + if (hasClass(target, 'slide')) { + return parseInt(target.id.slice(5)); + } + target = target.parentNode; + } + return null; +} + +function slideJump() { + if (window.location.hash == null) return; + var sregex = /^#slide(\d+)$/; + var matches = sregex.exec(window.location.hash); + var dest = null; + if (matches != null) { + dest = parseInt(matches[1]); + } else { + dest = findSlide(window.location.hash.slice(1)); + } + if (dest != null) + go(dest - snum); +} + +function fixLinks() { + var thisUri = window.location.href; + thisUri = thisUri.slice(0, thisUri.length - window.location.hash.length); + var aelements = document.getElementsByTagName('A'); + for (var i = 0; i < aelements.length; i++) { + var a = aelements[i].href; + var slideID = a.match('\#slide[0-9]{1,2}'); + if ((slideID) && (slideID[0].slice(0,1) == '#')) { + var dest = findSlide(slideID[0].slice(1)); + if (dest != null) { + if (aelements[i].addEventListener) { + aelements[i].addEventListener("click", new Function("e", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "if (e.preventDefault) e.preventDefault();"), true); + } else if (aelements[i].attachEvent) { + aelements[i].attachEvent("onclick", new Function("", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "event.returnValue = false;")); + } + } + } + } +} + +function externalLinks() { + if (!document.getElementsByTagName) return; + var anchors = document.getElementsByTagName('a'); + for (var i=0; i<anchors.length; i++) { + var anchor = anchors[i]; + if (anchor.getAttribute('href') && hasValue(anchor.rel, 'external')) { + anchor.target = '_blank'; + addClass(anchor,'external'); + } + } +} + +function permaLink() { + document.getElementById('plink').href = window.location.pathname + '#slide' + snum; +} + +function createControls() { + var controlsDiv = document.getElementById("controls"); + if (!controlsDiv) return; + var hider = ' onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"'; + var hideDiv, hideList = ''; + if (controlVis == 'hidden') { + hideDiv = hider; + } else { + hideList = hider; + } + controlsDiv.innerHTML = '<form action="#" id="controlForm"' + hideDiv + '>' + + '<div id="navLinks">' + + '<a accesskey="n" id="show-notes" href="javascript:createNotesWindow();" title="Show Notes">≡<\/a>' + + '<a accesskey="t" id="toggle" href="javascript:toggle();">Ø<\/a>' + + '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' + + '<a accesskey="x" id="next" href="javascript:go(1);">»<\/a>' + + '<div id="navList"' + hideList + '><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>' + + '<\/div><\/form>'; + if (controlVis == 'hidden') { + var hidden = document.getElementById('navLinks'); + } else { + var hidden = document.getElementById('jumplist'); + } + addClass(hidden,'hideme'); +} + +function fontScale() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers + if (!s5mode) return false; + var vScale = 48; // both yield 16 (the usual browser default) at 1024x768 + var hScale = 64; // perhaps should auto-calculate based on theme's declared value? + if (window.innerHeight) { + var vSize = window.innerHeight; + var hSize = window.innerWidth; + } else if (document.documentElement.clientHeight) { + var vSize = document.documentElement.clientHeight; + var hSize = document.documentElement.clientWidth; + } else if (document.body.clientHeight) { + var vSize = document.body.clientHeight; + var hSize = document.body.clientWidth; + } else { + var vSize = 700; // assuming 1024x768, minus chrome and such + var hSize = 1024; // these do not account for kiosk mode or Opera Show + } + var newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale)); + fontSize(newSize + 'px'); + if (isGe) { // hack to counter incremental reflow bugs + var obj = document.getElementsByTagName('body')[0]; + obj.style.display = 'none'; + obj.style.display = 'block'; + } +} + +function fontSize(value) { + if (!(s5ss = document.getElementById('s5ss'))) { + if (!document.createStyleSheet) { + document.getElementsByTagName('head')[0].appendChild(s5ss = document.createElement('style')); + s5ss.setAttribute('media','screen, projection'); + s5ss.setAttribute('id','s5ss'); + } else { + document.createStyleSheet(); + document.s5ss = document.styleSheets[document.styleSheets.length - 1]; + } + } + if (!(document.s5ss && document.s5ss.addRule)) { + while (s5ss.lastChild) s5ss.removeChild(s5ss.lastChild); + s5ss.appendChild(document.createTextNode('html {font-size: ' + value + ' !important;}')); + } else { + document.s5ss.addRule('html','font-size: ' + value + ' !important;'); + } +} + +function notOperaFix() { + slideCSS = document.getElementById('slideProj').href; + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + slides.setAttribute('media','screen'); + outline.disabled = true; + if (isGe) { + slides.setAttribute('href','null'); // Gecko fix + slides.setAttribute('href',slideCSS); // Gecko fix + } + if (isIE && document.styleSheets && document.styleSheets[0]) { + document.styleSheets[0].addRule('img', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('div', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('.slide', 'behavior: url(ui/default/iepngfix.htc)'); + } +} + +function getIncrementals(obj) { + var incrementals = new Array(); + if (!obj) + return incrementals; + var children = obj.childNodes; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (hasClass(child, 'incremental')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'incremental'); + for (var j = 0; j < child.childNodes.length; j++) { + if (child.childNodes[j].nodeType == 1) { + addClass(child.childNodes[j], 'incremental'); + } + } + } else { + incrementals[incrementals.length] = child; + removeClass(child,'incremental'); + } + } + if (hasClass(child, 'show-first')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'show-first'); + if (child.childNodes[isGe].nodeType == 1) { + removeClass(child.childNodes[isGe], 'incremental'); + } + } else { + incrementals[incrementals.length] = child; + } + } + incrementals = incrementals.concat(getIncrementals(child)); + } + return incrementals; +} + +function createIncrementals() { + var incrementals = new Array(); + for (var i = 0; i < smax; i++) { + incrementals[i] = getIncrementals(document.getElementById('slide'+i)); + } + return incrementals; +} + +function defaultCheck() { + var allMetas = document.getElementsByTagName('meta'); + for (var i = 0; i< allMetas.length; i++) { + if (allMetas[i].name == 'defaultView') { + defaultView = allMetas[i].content; + } + if (allMetas[i].name == 'controlVis') { + controlVis = allMetas[i].content; + } + } +} + +// Key trap fix, new function body for trap() +function trap(e) { + if (!e) { + e = event; + e.which = e.keyCode; + } + try { + modifierKey = e.ctrlKey || e.altKey || e.metaKey; + } + catch(e) { + modifierKey = false; + } + return modifierKey || e.which == 0; +} + +function noteLabel() { // Gives notes id's to match parent slides + var notes = GetElementsWithClassName('div','notes'); + for (var i = 0; i < notes.length; i++) { + var note = notes[i]; + var id = 'note' + note.parentNode.id.substring(5); + note.setAttribute('id',id); + } + resetElapsedSlide(); + resetRemainingTime(); + window.setInterval('updateElaspedTime()', 1000); +} + +function createNotesWindow() { // creates a window for our notes + if (!s5NotesWindow || s5NotesWindow.closed) { // Create the window if it doesn't exist + s5NotesWindowLoaded = false; + // Note: Safari has a tendency to ignore window options preferring to default to the settings of the parent window, grr. + s5NotesWindow = window.open('ui/s5-notes.html', 's5NotesWindow', 'top=0,left=0'); + } + if (s5NotesWindowLoaded) { // Load the current note if the Note HTML has loaded + loadNote(); + } else { // Keep trying... + window.setTimeout('createNotesWindow()', 50); + } +} + +function loadNote() { +// Loads a note into the note window + var notes = nextNotes = '<em class="disclaimer">There are no notes for this slide.</em>'; + if (document.getElementById('note' + snum)) { + notes = document.getElementById('note' + snum).innerHTML; + } + if (document.getElementById('note' + (snum + 1))) { + nextNotes = document.getElementById('note' + (snum + 1)).innerHTML; + } + + var jl = document.getElementById('jumplist'); + var slideTitle = jl.options[jl.selectedIndex].text.replace(/^\d+\s+:\s+/, '') + ((jl.selectedIndex) ? ' (' + jl.selectedIndex + '/' + (smax - 1) + ')' : ''); + if (incrementals[snum].length > 0) { +// alert('howdy'); + slideTitle += ' <small>[' + incpos + '/' + incrementals[snum].length + ']</small>'; + } + if (jl.selectedIndex < smax - 1) { + var nextTitle = jl.options[jl.selectedIndex + 1].text.replace(/^\d+\s+:\s+/, '') + ((jl.selectedIndex + 1) ? ' (' + (jl.selectedIndex + 1) + '/' + (smax - 1) + ')' : ''); + } else { + var nextTitle = '[end of slide show]'; + } + + if (s5NotesWindow && !s5NotesWindow.closed && s5NotesWindow.document) { + s5NotesWindow.document.getElementById('slide').innerHTML = slideTitle; + s5NotesWindow.document.getElementById('notes').innerHTML = notes; + s5NotesWindow.document.getElementById('next').innerHTML = nextTitle; + s5NotesWindow.document.getElementById('nextnotes').innerHTML = nextNotes; + } + resetElapsedSlide(); +} + +function minimizeTimer(id) { + var obj = s5NotesWindow.document.getElementById(id); + if (hasClass(obj,'collapsed')) { + removeClass(obj,'collapsed'); + } else { + addClass(obj,'collapsed'); + } +} + +function resetElapsedTime() { + presentationStart = new Date(); + slideStart = new Date(); + updateElaspedTime(); +} + +function resetElapsedSlide() { + if (snum != previousSlide) { + slideStart = new Date(); + previousSlide = snum; + updateElaspedTime(); + } +} + +function updateElaspedTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var now = new Date(); + var ep = s5NotesWindow.document.getElementById('elapsed-presentation'); + var es = s5NotesWindow.document.getElementById('elapsed-slide'); + ep.innerHTML = formatTime(now.valueOf() - presentationStart.valueOf()); + es.innerHTML = formatTime(now.valueOf() - slideStart.valueOf()); +} + +function resetRemainingTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var startField = s5NotesWindow.document.getElementById('startFrom'); + startFrom = readTime(startField.value); + countdown.remaining = startFrom * 60000; // convert to msecs + countdown.start = new Date().valueOf(); + countdown.end = countdown.start + countdown.remaining; + var tl = s5NotesWindow.document.getElementById('timeLeft'); + var timeLeft = formatTime(countdown.remaining); + tl.innerHTML = timeLeft; +} + +function updateRemainingTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var tl = s5NotesWindow.document.getElementById('timeLeft'); + var now = new Date(); + if (countdown.state == 'run') { + countdown.remaining = countdown.end - now; + } + tl.style.color = ''; + tl.style.backgroundColor = ''; + if (countdown.remaining >= 0) { + var timeLeft = formatTime(countdown.remaining); + removeClass(tl,'overtime'); + if (countdown.remaining < 300000) { + tl.style.color = 'rgb(' + (255-Math.round(countdown.remaining/2000)) + ',0,0)'; + tl.style.backgroundColor = 'rgb(255,255,' + (Math.round(countdown.remaining/2000)) + ')'; + } + } else { + var timeLeft = '-' + formatTime(-countdown.remaining); + addClass(tl,'overtime'); + } + tl.innerHTML = timeLeft; +} + +function toggleRemainingTime() { + if (countdown.state == 'pause') countdown.state = 'run'; else countdown.state = 'pause'; + if (countdown.state == 'pause') { + window.clearInterval(countdown.timer); + } + if (countdown.state == 'run') { + countdown.start = new Date().valueOf(); + countdown.end = countdown.start + countdown.remaining; + countdown.timer = window.setInterval('updateRemainingTime()', 1000); + } +} + +function alterRemainingTime(amt) { + var change = amt * 60000; // convert to msecs + countdown.end += change; + countdown.remaining += change; + updateRemainingTime(); +} + +function formatTime(msecs) { + var time = new Date(msecs); + + var hrs = time.getUTCHours() + ((time.getUTCDate() -1) * 24); // I doubt anyone will spend more than 24 hours on a presentation or single slide but just in case... + hrs = (hrs < 10) ? '0'+hrs : hrs; + if (hrs == 'NaN' || isNaN(hrs)) hrs = '--'; + + var min = time.getUTCMinutes(); + min = (min < 10) ? '0'+min : min; + if (min == 'NaN' || isNaN(min)) min = '--'; + + var sec = time.getUTCSeconds(); + sec = (sec < 10) ? '0'+sec : sec; + if (sec == 'NaN' || isNaN(sec)) sec = '--'; + + return hrs + ':' + min + ':' + sec; +} + +function readTime(val) { + var sregex = /:/; + var matches = sregex.exec(val); + if (matches == null) { + return val; + } else { + var times = val.split(':'); + var hours = parseInt(times[0]); + var mins = parseInt(times[1]); + var total = (hours * 60) + mins; + return total; + } +} + +function windowChange() { + fontScale(); +} + +function startup() { + defaultCheck(); + createControls(); // hallvord + slideLabel(); + incrementals = createIncrementals(); + noteLabel(); // [SI:060104] must follow slideLabel() + loadNote(); + fixLinks(); + externalLinks(); + fontScale(); + if (!isOp) notOperaFix(); + slideJump(); + if (defaultView == 'outline') { + toggle(); + } + document.onkeyup = keys; + document.onkeypress = trap; + document.onclick = clicker; +} + +window.onload = startup; +window.onresize = function(){setTimeout('windowChange()',5);} \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008/ui/moose/blank.gif b/Moose_YAPC_Asia_2008/ui/moose/blank.gif new file mode 100644 index 0000000..75b945d Binary files /dev/null and b/Moose_YAPC_Asia_2008/ui/moose/blank.gif differ diff --git a/Moose_YAPC_Asia_2008/ui/moose/bodybg.gif b/Moose_YAPC_Asia_2008/ui/moose/bodybg.gif new file mode 100755 index 0000000..5f448a1 Binary files /dev/null and b/Moose_YAPC_Asia_2008/ui/moose/bodybg.gif differ diff --git a/Moose_YAPC_Asia_2008/ui/moose/framing.css b/Moose_YAPC_Asia_2008/ui/moose/framing.css new file mode 100644 index 0000000..2a27daf --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/moose/framing.css @@ -0,0 +1,22 @@ +/* The following styles size, place, and layer the slide components. + Edit these if you want to change the overall slide layout. + The commented lines can be uncommented (and modified, if necessary) + to help you with the rearrangement process. */ + +/* target = 1024x768 */ + +div#header, div#footer, .slide {width: 100%; top: 0; left: 0;} +div#header {top: 0; height: 3em; z-index: 1;} +div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;} +.slide {top: 0; width: 92%; padding: 3.5em 4% 4%; z-index: 2; list-style: none;} +div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;} +div#controls form {text-align: right; width: 100%; margin: 0;} +#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; z-index: 10;} +html>body #currentSlide {position: fixed;} + +/* +div#header {background: #FCC;} +div#footer {background: #CCF;} +div#controls {background: #BBD;} +div#currentSlide {background: #FFC;} +*/ diff --git a/Moose_YAPC_Asia_2008/ui/moose/iepngfix.htc b/Moose_YAPC_Asia_2008/ui/moose/iepngfix.htc new file mode 100644 index 0000000..bba2db7 --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/moose/iepngfix.htc @@ -0,0 +1,42 @@ +<public:component> +<public:attach event="onpropertychange" onevent="doFix()" /> + +<script> + +// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com +// Free usage permitted as long as this notice remains intact. + +// This must be a path to a blank image. That's all the configuration you need here. +var blankImg = 'ui/default/blank.gif'; + +var f = 'DXImageTransform.Microsoft.AlphaImageLoader'; + +function filt(s, m) { + if (filters[f]) { + filters[f].enabled = s ? true : false; + if (s) with (filters[f]) { src = s; sizingMethod = m } + } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")'; +} + +function doFix() { + if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) || + (event && !/(background|src)/.test(event.propertyName))) return; + + if (tagName == 'IMG') { + if ((/\.png$/i).test(src)) { + filt(src, 'image'); // was 'scale' + src = blankImg; + } else if (src.indexOf(blankImg) < 0) filt(); + } else if (style.backgroundImage) { + if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) { + var s = RegExp.$1; + style.backgroundImage = ''; + filt(s, 'crop'); + } else filt(); + } +} + +doFix(); + +</script> +</public:component> \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008/ui/moose/moose_watermark.gif b/Moose_YAPC_Asia_2008/ui/moose/moose_watermark.gif new file mode 100644 index 0000000..a67bafc Binary files /dev/null and b/Moose_YAPC_Asia_2008/ui/moose/moose_watermark.gif differ diff --git a/Moose_YAPC_Asia_2008/ui/moose/moose_watermark.png b/Moose_YAPC_Asia_2008/ui/moose/moose_watermark.png new file mode 100644 index 0000000..3963b59 Binary files /dev/null and b/Moose_YAPC_Asia_2008/ui/moose/moose_watermark.png differ diff --git a/Moose_YAPC_Asia_2008/ui/moose/notes.css b/Moose_YAPC_Asia_2008/ui/moose/notes.css new file mode 100644 index 0000000..5858cf2 --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/moose/notes.css @@ -0,0 +1,122 @@ +/* Following are the note styles -- edit away! */ + +body { + margin: 0; + padding: 1.0em; + background: #333; + color: #FFF; + font: 2em/1.4em 'Lucida Grande', Verdana, sans-serif; +} + +div.timers { + background: #FFF; + color: #333; + border: 0.08em solid #222; + border-top-width: 1px; + border-left-width: 1px; + float: left; + padding: 0.2em; + margin: 0 0 0.5em; + position: relative; +} + +div.timers h1 { + text-align: left; + font-size: 0.6em; + line-height: 1.4em; + background-color: #FF9; + padding: 0 0.75em; + margin: 0.25em 0 0; + border: 1px solid #EE8; +} + +div.timers div.controls { + position: absolute; + right: 0.25em; + top: 0.1em; + line-height: 1em; +} + +div.timers h1 a { + text-decoration: none; + color: #000; +} + +div.timers div.controls a { + font-size: 0.5em; + padding: 0; + color: #330; +} + +div.timers a.control { + position: absolute; + text-decoration: none; + padding: 0 0.25em; + color: #AAA; + outline: 0; +} + +#minus { + left: 0.25em; +} + +#plus { + right: 0.25em; +} + +.overtime { + background: yellow; + color: red; + border: 3px solid; + padding: 0.1em 0.25em; + font-weight: bold; +} + +div.timers h2 { + font-size: 0.6em; + line-height: 1.0em; + font-weight: normal; + margin: 0 0 -0.25em; + padding-top: 0.5em; + color: #666; +} + +div.timers p {margin: 0; padding: 0 0.5em;} +div.timers form {margin: 0;} + +div.timers span.clock { + font-family: monospace; +} + +div.timers ul {margin: 0; padding: 0; list-style: none;} +div.timers li {float: left; width: 5em; margin: 0; padding: 0 0.5em; + text-align: center;} + +div#elapsed {width: 12.1em;} +div#remaining {clear: left; width: 12.1em;} +div#remaining p {text-align: center;} + +#slide, +#next, +#notes, +#nextnotes { + font-size: 0.75em; + line-height: 1.4em; + clear: left; +/* max-width: 30.0em; */ + text-shadow: 0.1em 0.1em 0.1em #111; +} + +#next {margin-top: 2.5em;} +#next, #nextnotes { + color: #999; + font-size: 0.66em; +} + +em.disclaimer { + color: #666; +} + +div.collapsed h1 {display: block; font-size: 0.33em;} +div.collapsed h1 a {display: inline;} +div.collapsed * {display: none;} diff --git a/Moose_YAPC_Asia_2008/ui/moose/opera.css b/Moose_YAPC_Asia_2008/ui/moose/opera.css new file mode 100644 index 0000000..9e9d2a3 --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/moose/opera.css @@ -0,0 +1,7 @@ +/* DO NOT CHANGE THESE unless you really want to break Opera Show */ +.slide { + visibility: visible !important; + position: static !important; + page-break-before: always; +} +#slide0 {page-break-before: avoid;} diff --git a/Moose_YAPC_Asia_2008/ui/moose/outline.css b/Moose_YAPC_Asia_2008/ui/moose/outline.css new file mode 100644 index 0000000..62db519 --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/moose/outline.css @@ -0,0 +1,15 @@ +/* don't change this unless you want the layout stuff to show up in the outline view! */ + +.layout div, #footer *, #controlForm * {display: none;} +#footer, #controls, #controlForm, #navLinks, #toggle { + display: block; visibility: visible; margin: 0; padding: 0;} +#toggle {float: right; padding: 0.5em;} +html>body #toggle {position: fixed; top: 0; right: 0;} + +/* making the outline look pretty-ish */ + +#slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;} +#slide0 h1 {padding-top: 1.5em;} +.slide h1 {margin: 1.5em 0 0; padding-top: 0.25em; + border-top: 1px solid #888; border-bottom: 1px solid #AAA;} +#toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;} diff --git a/Moose_YAPC_Asia_2008/ui/moose/pretty.css b/Moose_YAPC_Asia_2008/ui/moose/pretty.css new file mode 100644 index 0000000..80fdf85 --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/moose/pretty.css @@ -0,0 +1,86 @@ +/* Following are the presentation styles -- edit away! */ + +body {background: #FFF url(moose_watermark.png) -16px 0 no-repeat; color: #000; font-size: 1.5em;} +:link, :visited {text-decoration: none; color: #3399cc;} +#controls :active {color: #333 !important;} +#controls :focus {outline: 1px dotted #227;} +h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;} +ul, pre {margin: 0; line-height: 1em;} +html, body {margin: 0; padding: 0;} + +blockquote, q {font-style: italic;} +blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;} +blockquote p {margin: 0;} +blockquote i {font-style: normal;} +blockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;} +blockquote b i {font-style: italic;} + +kbd {font-weight: bold; font-size: 1em;} +sup {font-size: smaller; line-height: 1px;} + +.slide code {font-size: 0.75em; padding: 2px 0.2em; font-weight: bold; color: #533;} +.slide code.bad, code del {color: red;} +.slide code.old {color: silver;} +.slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: #533; font-size: 90%;} +.slide pre code {font-size: 0.75em; margin-left: 5%; display: block; line-height: 1.25em;} +.slide ul {margin-left: 5%; margin-right: 7%; list-style: disc;} +.slide li {margin-top: 0.75em; margin-right: 0;} +.slide ul ul {line-height: 1;} +.slide ul ul li {margin: .2em; font-size: 85%; list-style: square;} +.slide img.leader {display: block; margin: 0 auto;} + +div#header, div#footer {background: #39c; color: #333; + font-family: Verdana, Helvetica, sans-serif;} +div#header {background: #3399cc url(moose_watermark.png) -16px 0 no-repeat; + line-height: 1px;} +div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;} +#footer h1, #footer h2 {display: block; padding: 0 1em;} +#footer h2 {font-style: italic;} + +div.long {font-size: 0.75em;} +.slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1; + margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap; + font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize; + color: #333;} +.slide h2 {position: absolute; top: 1.9em; left: 87px; z-index: 1; + margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap; + font: bold 120%/.7em Helvetica, sans-serif; text-transform: capitalize; + color: #333;} +.slide h3 {font-size: 130%;} +h1 abbr {font-variant: small-caps;} + +div#controls {position: absolute; left: 60%; bottom: 0; + width: 40%; + text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;} +html>body div#controls {position: fixed; padding: 0; top: auto;} +#controls #navLinks a {padding: 0; margin: 0 0.5em; + background: #3399cc; border: none; color: #333; + cursor: pointer;} +#controls #navList #jumplist {background: #DDD; color: #227;} + +#currentSlide {text-align: center; font-size: 0.5em; color: #333;} + +#slide0 {padding-top: 3.5em; font-size: 90%;} +#slide0 h1 {position: static; margin: 1em 0 0; padding: 0; + font: bold 2em Helvetica, sans-serif; white-space: normal; + color: #000; background: transparent;} +#slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;} +#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;} +#slide0 h4 {margin-top: 0; font-size: 1em;} + +ul.urls {list-style: none; display: inline; margin: 0;} +.urls li {display: inline; margin: 0;} +.note {display: none;} +.external {border-bottom: 1px dotted gray;} +html>body .external {border-bottom: none;} +.external:after {content: " \274F"; font-size: smaller; color: #77B;} + +.incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;} +img.incremental {visibility: hidden;} +.slide .current {color: #B02;} + + +/* diagnostics + +li:after {content: " [" attr(class) "]"; color: #F88;} + */ diff --git a/Moose_YAPC_Asia_2008/ui/moose/pretty.css~ b/Moose_YAPC_Asia_2008/ui/moose/pretty.css~ new file mode 100644 index 0000000..386fd00 --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/moose/pretty.css~ @@ -0,0 +1,86 @@ +/* Following are the presentation styles -- edit away! */ + +body {background: #FFF url(moose_watermark.png) -16px 0 no-repeat; color: #000; font-size: 1.5em;} +:link, :visited {text-decoration: none; color: #3399cc;} +#controls :active {color: #333 !important;} +#controls :focus {outline: 1px dotted #227;} +h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;} +ul, pre {margin: 0; line-height: 1em;} +html, body {margin: 0; padding: 0;} + +blockquote, q {font-style: italic;} +blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;} +blockquote p {margin: 0;} +blockquote i {font-style: normal;} +blockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;} +blockquote b i {font-style: italic;} + +kbd {font-weight: bold; font-size: 1em;} +sup {font-size: smaller; line-height: 1px;} + +.slide code {font-size: 0.75em; padding: 2px 0.2em; font-weight: bold; color: #533;} +.slide code.bad, code del {color: red;} +.slide code.old {color: silver;} +.slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: #533; font-size: 90%;} +.slide pre code {font-size: 0.75em; margin-left: 5%; display: block; line-height: 1.25em;} +.slide ul {margin-left: 5%; margin-right: 7%; list-style: disc;} +.slide li {margin-top: 0.75em; margin-right: 0;} +.slide ul ul {line-height: 1;} +.slide ul ul li {margin: .2em; font-size: 85%; list-style: square;} +.slide img.leader {display: block; margin: 0 auto;} + +div#header, div#footer {background: #39c; color: #333; + font-family: Verdana, Helvetica, sans-serif;} +div#header {background: #3399cc url(moose_watermark.png) -16px 0 no-repeat; + line-height: 1px;} +div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;} +#footer h1, #footer h2 {display: block; padding: 0 1em;} +#footer h2 {font-style: italic;} + +div.long {font-size: 0.75em;} +.slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1; + margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap; + font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize; + color: #333;} +.slide h1 {position: absolute; top: 1.9em; left: 87px; z-index: 1; + margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap; + font: bold 120%/.7em Helvetica, sans-serif; text-transform: capitalize; + color: #333;} +.slide h3 {font-size: 130%;} +h1 abbr {font-variant: small-caps;} + +div#controls {position: absolute; left: 60%; bottom: 0; + width: 40%; + text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;} +html>body div#controls {position: fixed; padding: 0; top: auto;} +#controls #navLinks a {padding: 0; margin: 0 0.5em; + background: #3399cc; border: none; color: #333; + cursor: pointer;} +#controls #navList #jumplist {background: #DDD; color: #227;} + +#currentSlide {text-align: center; font-size: 0.5em; color: #333;} + +#slide0 {padding-top: 3.5em; font-size: 90%;} +#slide0 h1 {position: static; margin: 1em 0 0; padding: 0; + font: bold 2em Helvetica, sans-serif; white-space: normal; + color: #000; background: transparent;} +#slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;} +#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;} +#slide0 h4 {margin-top: 0; font-size: 1em;} + +ul.urls {list-style: none; display: inline; margin: 0;} +.urls li {display: inline; margin: 0;} +.note {display: none;} +.external {border-bottom: 1px dotted gray;} +html>body .external {border-bottom: none;} +.external:after {content: " \274F"; font-size: smaller; color: #77B;} + +.incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;} +img.incremental {visibility: hidden;} +.slide .current {color: #B02;} + + +/* diagnostics + +li:after {content: " [" attr(class) "]"; color: #F88;} + */ diff --git a/Moose_YAPC_Asia_2008/ui/moose/print.css b/Moose_YAPC_Asia_2008/ui/moose/print.css new file mode 100644 index 0000000..e7a71d1 --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/moose/print.css @@ -0,0 +1 @@ +/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */ .slide, ul {page-break-inside: avoid; visibility: visible !important;} h1 {page-break-after: avoid;} body {font-size: 12pt; background: white;} * {color: black;} #slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;} #slide0 h3 {margin: 0; padding: 0;} #slide0 h4 {margin: 0 0 0.5em; padding: 0;} #slide0 {margin-bottom: 3em;} h1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;} .extra {background: transparent !important;} div.extra, pre.extra, .example {font-size: 10pt; color: #333;} ul.extra a {font-weight: bold;} p.example {display: none;} #header {display: none;} #footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;} #footer h2, #controls {display: none;} /* The following rule keeps the layout stuff out of print. Remove at your own risk! */ .layout, .layout * {display: none !important;} \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008/ui/moose/s5-core.css b/Moose_YAPC_Asia_2008/ui/moose/s5-core.css new file mode 100644 index 0000000..ad1530b --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/moose/s5-core.css @@ -0,0 +1,9 @@ +/* Do not edit or override these styles! The system will likely break if you do. */ + +div#header, div#footer, div#controls, .slide {position: absolute;} +html>body div#header, html>body div#footer, + html>body div#controls, html>body .slide {position: fixed;} +.handout, .notes {display: none;} +.layout {display: block;} +.slide, .hideme, .incremental {visibility: hidden;} +#slide0 {visibility: visible;} diff --git a/Moose_YAPC_Asia_2008/ui/moose/slides.css b/Moose_YAPC_Asia_2008/ui/moose/slides.css new file mode 100644 index 0000000..0786d7d --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/moose/slides.css @@ -0,0 +1,3 @@ +@import url(s5-core.css); /* required to make the slide show run at all */ +@import url(framing.css); /* sets basic placement and size of slide components */ +@import url(pretty.css); /* stuff that makes the slides look better than blah */ \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008/ui/moose/slides.js b/Moose_YAPC_Asia_2008/ui/moose/slides.js new file mode 100644 index 0000000..ab2a4b2 --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/moose/slides.js @@ -0,0 +1,764 @@ +// S5 v1.2a1 slides.js -- released into the Public Domain +// +// Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information +// about all the wonderful and talented contributors to this code! + +var undef; +var slideCSS = ''; +var snum = 0; +var smax = 1; +var incpos = 0; +var number = undef; +var s5mode = true; +var defaultView = 'slideshow'; +var controlVis = 'visible'; + +var s5NotesWindow; +var s5NotesWindowLoaded = false; +var previousSlide = 0; +var presentationStart = new Date(); +var slideStart = new Date(); + +var countdown = { + timer: 0, + state: 'pause', + start: new Date(), + end: 0, + remaining: 0 +}; + + +var isIE = navigator.appName == 'Microsoft Internet Explorer' && navigator.userAgent.indexOf('Opera') < 1 ? 1 : 0; +var isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0; +var isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0; + +function hasClass(object, className) { + if (!object.className) return false; + return (object.className.search('(^|\\s)' + className + '(\\s|$)') != -1); +} + +function hasValue(object, value) { + if (!object) return false; + return (object.search('(^|\\s)' + value + '(\\s|$)') != -1); +} + +function removeClass(object,className) { + if (!object || !hasClass(object,className)) return; + object.className = object.className.replace(new RegExp('(^|\\s)'+className+'(\\s|$)'), RegExp.$1+RegExp.$2); +} + +function addClass(object,className) { + if (!object || hasClass(object, className)) return; + if (object.className) { + object.className += ' '+className; + } else { + object.className = className; + } +} + +function GetElementsWithClassName(elementName,className) { + var allElements = document.getElementsByTagName(elementName); + var elemColl = new Array(); + for (var i = 0; i< allElements.length; i++) { + if (hasClass(allElements[i], className)) { + elemColl[elemColl.length] = allElements[i]; + } + } + return elemColl; +} + +function isParentOrSelf(element, id) { + if (element == null || element.nodeName=='BODY') return false; + else if (element.id == id) return true; + else return isParentOrSelf(element.parentNode, id); +} + +function nodeValue(node) { + var result = ""; + if (node.nodeType == 1) { + var children = node.childNodes; + for (var i = 0; i < children.length; ++i) { + result += nodeValue(children[i]); + } + } + else if (node.nodeType == 3) { + result = node.nodeValue; + } + return(result); +} + +function slideLabel() { + var slideColl = GetElementsWithClassName('*','slide'); + var list = document.getElementById('jumplist'); + smax = slideColl.length; + for (var n = 0; n < smax; n++) { + var obj = slideColl[n]; + + var did = 'slide' + n.toString(); + obj.setAttribute('id',did); + +// if (isOp) continue; // Opera fix (hallvord) + + var otext = ''; + var menu = obj.firstChild; + if (!menu) continue; // to cope with empty slides + while (menu && menu.nodeType == 3) { + menu = menu.nextSibling; + } + if (!menu) continue; // to cope with slides with only text nodes + + var menunodes = menu.childNodes; + for (var o = 0; o < menunodes.length; o++) { + otext += nodeValue(menunodes[o]); + } + list.options[list.length] = new Option(n + ' : ' + otext, n); + } +} + +function currentSlide() { + var cs; + if (document.getElementById) { + cs = document.getElementById('currentSlide'); + } else { + cs = document.currentSlide; + } + cs.innerHTML = '<a id="plink" href="">' + + '<span id="csHere">' + snum + '<\/span> ' + + '<span id="csSep">\/<\/span> ' + + '<span id="csTotal">' + (smax-1) + '<\/span>' + + '<\/a>' + ; + if (snum == 0) { + cs.style.visibility = 'hidden'; + } else { + cs.style.visibility = 'visible'; + } +} + +function go(step) { + if (document.getElementById('slideProj').disabled || step == 0) return; + var jl = document.getElementById('jumplist'); + var cid = 'slide' + snum; + var ce = document.getElementById(cid); + if (incrementals[snum].length > 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + removeClass(incrementals[snum][i], 'current'); + removeClass(incrementals[snum][i], 'incremental'); + } + } + if (step != 'j') { + snum += step; + lmax = smax - 1; + if (snum > lmax) snum = lmax; + if (snum < 0) snum = 0; + } else + snum = parseInt(jl.value); + var nid = 'slide' + snum; + var ne = document.getElementById(nid); + if (!ne) { + ne = document.getElementById('slide0'); + snum = 0; + } + if (step < 0) {incpos = incrementals[snum].length} else {incpos = 0;} + if (incrementals[snum].length > 0 && incpos == 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + if (hasClass(incrementals[snum][i], 'current')) + incpos = i + 1; + else + addClass(incrementals[snum][i], 'incremental'); + } + } + if (incrementals[snum].length > 0 && incpos > 0) + addClass(incrementals[snum][incpos - 1], 'current'); + if (isOp) { //hallvord + location.hash = nid; + } else { + ce.style.visibility = 'hidden'; + ne.style.visibility = 'visible'; + } // /hallvord + jl.selectedIndex = snum; + currentSlide(); + loadNote(); + permaLink(); + number = undef; +} + +function goTo(target) { + if (target >= smax || target == snum) return; + go(target - snum); +} + +function subgo(step) { + if (step > 0) { + removeClass(incrementals[snum][incpos - 1],'current'); + removeClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos],'current'); + incpos++; + } else { + incpos--; + removeClass(incrementals[snum][incpos],'current'); + addClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos - 1],'current'); + } + loadNote(); +} + +function toggle() { + var slideColl = GetElementsWithClassName('*','slide'); + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + if (!slides.disabled) { + slides.disabled = true; + outline.disabled = false; + s5mode = false; + fontSize('1em'); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'visible'; + } + } else { + slides.disabled = false; + outline.disabled = true; + s5mode = true; + fontScale(); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'hidden'; + } + slideColl[snum].style.visibility = 'visible'; + } +} + +function showHide(action) { + var obj = GetElementsWithClassName('*','hideme')[0]; + switch (action) { + case 's': obj.style.visibility = 'visible'; break; + case 'h': obj.style.visibility = 'hidden'; break; + case 'k': + if (obj.style.visibility != 'visible') { + obj.style.visibility = 'visible'; + } else { + obj.style.visibility = 'hidden'; + } + break; + } +} + +// 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/) +function keys(key) { + if (!key) { + key = event; + key.which = key.keyCode; + } + if (key.which == 84) { + toggle(); + return; + } + if (s5mode) { + switch (key.which) { + case 10: // return + case 13: // enter + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + if(number != undef) { + goTo(number); + break; + } + case 32: // spacebar + case 34: // page down + case 39: // rightkey + case 40: // downkey + if(number != undef) { + go(number); + } else if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + break; + case 33: // page up + case 37: // leftkey + case 38: // upkey + if(number != undef) { + go(-1 * number); + } else if (!incrementals[snum] || incpos <= 0) { + go(-1); + } else { + subgo(-1); + } + break; + case 36: // home + goTo(0); + break; + case 35: // end + goTo(smax-1); + break; + case 67: // c + showHide('k'); + break; + case 78: // n + createNotesWindow(); + break; + } + if (key.which < 48 || key.which > 57) { + number = undef; + } else { + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + number = (((number != undef) ? number : 0) * 10) + (key.which - 48); + } + } + return false; +} + +function clicker(e) { + number = undef; + var target; + if (window.event) { + target = window.event.srcElement; + e = window.event; + } else target = e.target; + if (target.href != null || hasValue(target.rel, 'external') || isParentOrSelf(target, 'controls') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object')) return true; + if (!e.which || e.which == 1) { + if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + } +} + +function findSlide(hash) { + var target = null; + var slides = GetElementsWithClassName('*','slide'); + for (var i = 0; i < slides.length; i++) { + var targetSlide = slides[i]; + if ( (targetSlide.name && targetSlide.name == hash) + || (targetSlide.id && targetSlide.id == hash) ) { + target = targetSlide; + break; + } + } + while(target != null && target.nodeName != 'BODY') { + if (hasClass(target, 'slide')) { + return parseInt(target.id.slice(5)); + } + target = target.parentNode; + } + return null; +} + +function slideJump() { + if (window.location.hash == null) return; + var sregex = /^#slide(\d+)$/; + var matches = sregex.exec(window.location.hash); + var dest = null; + if (matches != null) { + dest = parseInt(matches[1]); + } else { + dest = findSlide(window.location.hash.slice(1)); + } + if (dest != null) + go(dest - snum); +} + +function fixLinks() { + var thisUri = window.location.href; + thisUri = thisUri.slice(0, thisUri.length - window.location.hash.length); + var aelements = document.getElementsByTagName('A'); + for (var i = 0; i < aelements.length; i++) { + var a = aelements[i].href; + var slideID = a.match('\#slide[0-9]{1,2}'); + if ((slideID) && (slideID[0].slice(0,1) == '#')) { + var dest = findSlide(slideID[0].slice(1)); + if (dest != null) { + if (aelements[i].addEventListener) { + aelements[i].addEventListener("click", new Function("e", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "if (e.preventDefault) e.preventDefault();"), true); + } else if (aelements[i].attachEvent) { + aelements[i].attachEvent("onclick", new Function("", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "event.returnValue = false;")); + } + } + } + } +} + +function externalLinks() { + if (!document.getElementsByTagName) return; + var anchors = document.getElementsByTagName('a'); + for (var i=0; i<anchors.length; i++) { + var anchor = anchors[i]; + if (anchor.getAttribute('href') && hasValue(anchor.rel, 'external')) { + anchor.target = '_blank'; + addClass(anchor,'external'); + } + } +} + +function permaLink() { + document.getElementById('plink').href = window.location.pathname + '#slide' + snum; +} + +function createControls() { + var controlsDiv = document.getElementById("controls"); + if (!controlsDiv) return; + var hider = ' onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"'; + var hideDiv, hideList = ''; + if (controlVis == 'hidden') { + hideDiv = hider; + } else { + hideList = hider; + } + controlsDiv.innerHTML = '<form action="#" id="controlForm"' + hideDiv + '>' + + '<div id="navLinks">' + + '<a accesskey="n" id="show-notes" href="javascript:createNotesWindow();" title="Show Notes">≡<\/a>' + + '<a accesskey="t" id="toggle" href="javascript:toggle();">Ø<\/a>' + + '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' + + '<a accesskey="x" id="next" href="javascript:go(1);">»<\/a>' + + '<div id="navList"' + hideList + '><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>' + + '<\/div><\/form>'; + if (controlVis == 'hidden') { + var hidden = document.getElementById('navLinks'); + } else { + var hidden = document.getElementById('jumplist'); + } + addClass(hidden,'hideme'); +} + +function fontScale() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers + if (!s5mode) return false; + var vScale = 48; // both yield 16 (the usual browser default) at 1024x768 + var hScale = 64; // perhaps should auto-calculate based on theme's declared value? + if (window.innerHeight) { + var vSize = window.innerHeight; + var hSize = window.innerWidth; + } else if (document.documentElement.clientHeight) { + var vSize = document.documentElement.clientHeight; + var hSize = document.documentElement.clientWidth; + } else if (document.body.clientHeight) { + var vSize = document.body.clientHeight; + var hSize = document.body.clientWidth; + } else { + var vSize = 700; // assuming 1024x768, minus chrome and such + var hSize = 1024; // these do not account for kiosk mode or Opera Show + } + var newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale)); + fontSize(newSize + 'px'); + if (isGe) { // hack to counter incremental reflow bugs + var obj = document.getElementsByTagName('body')[0]; + obj.style.display = 'none'; + obj.style.display = 'block'; + } +} + +function fontSize(value) { + if (!(s5ss = document.getElementById('s5ss'))) { + if (!document.createStyleSheet) { + document.getElementsByTagName('head')[0].appendChild(s5ss = document.createElement('style')); + s5ss.setAttribute('media','screen, projection'); + s5ss.setAttribute('id','s5ss'); + } else { + document.createStyleSheet(); + document.s5ss = document.styleSheets[document.styleSheets.length - 1]; + } + } + if (!(document.s5ss && document.s5ss.addRule)) { + while (s5ss.lastChild) s5ss.removeChild(s5ss.lastChild); + s5ss.appendChild(document.createTextNode('html {font-size: ' + value + ' !important;}')); + } else { + document.s5ss.addRule('html','font-size: ' + value + ' !important;'); + } +} + +function notOperaFix() { + slideCSS = document.getElementById('slideProj').href; + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + slides.setAttribute('media','screen'); + outline.disabled = true; + if (isGe) { + slides.setAttribute('href','null'); // Gecko fix + slides.setAttribute('href',slideCSS); // Gecko fix + } + if (isIE && document.styleSheets && document.styleSheets[0]) { + document.styleSheets[0].addRule('img', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('div', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('.slide', 'behavior: url(ui/default/iepngfix.htc)'); + } +} + +function getIncrementals(obj) { + var incrementals = new Array(); + if (!obj) + return incrementals; + var children = obj.childNodes; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (hasClass(child, 'incremental')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'incremental'); + for (var j = 0; j < child.childNodes.length; j++) { + if (child.childNodes[j].nodeType == 1) { + addClass(child.childNodes[j], 'incremental'); + } + } + } else { + incrementals[incrementals.length] = child; + removeClass(child,'incremental'); + } + } + if (hasClass(child, 'show-first')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'show-first'); + if (child.childNodes[isGe].nodeType == 1) { + removeClass(child.childNodes[isGe], 'incremental'); + } + } else { + incrementals[incrementals.length] = child; + } + } + incrementals = incrementals.concat(getIncrementals(child)); + } + return incrementals; +} + +function createIncrementals() { + var incrementals = new Array(); + for (var i = 0; i < smax; i++) { + incrementals[i] = getIncrementals(document.getElementById('slide'+i)); + } + return incrementals; +} + +function defaultCheck() { + var allMetas = document.getElementsByTagName('meta'); + for (var i = 0; i< allMetas.length; i++) { + if (allMetas[i].name == 'defaultView') { + defaultView = allMetas[i].content; + } + if (allMetas[i].name == 'controlVis') { + controlVis = allMetas[i].content; + } + } +} + +// Key trap fix, new function body for trap() +function trap(e) { + if (!e) { + e = event; + e.which = e.keyCode; + } + try { + modifierKey = e.ctrlKey || e.altKey || e.metaKey; + } + catch(e) { + modifierKey = false; + } + return modifierKey || e.which == 0; +} + +function noteLabel() { // Gives notes id's to match parent slides + var notes = GetElementsWithClassName('div','notes'); + for (var i = 0; i < notes.length; i++) { + var note = notes[i]; + var id = 'note' + note.parentNode.id.substring(5); + note.setAttribute('id',id); + } + resetElapsedSlide(); + resetRemainingTime(); + window.setInterval('updateElaspedTime()', 1000); +} + +function createNotesWindow() { // creates a window for our notes + if (!s5NotesWindow || s5NotesWindow.closed) { // Create the window if it doesn't exist + s5NotesWindowLoaded = false; + // Note: Safari has a tendency to ignore window options preferring to default to the settings of the parent window, grr. + s5NotesWindow = window.open('ui/s5-notes.html', 's5NotesWindow', 'top=0,left=0'); + } + if (s5NotesWindowLoaded) { // Load the current note if the Note HTML has loaded + loadNote(); + } else { // Keep trying... + window.setTimeout('createNotesWindow()', 50); + } +} + +function loadNote() { +// Loads a note into the note window + var notes = nextNotes = '<em class="disclaimer">There are no notes for this slide.</em>'; + if (document.getElementById('note' + snum)) { + notes = document.getElementById('note' + snum).innerHTML; + } + if (document.getElementById('note' + (snum + 1))) { + nextNotes = document.getElementById('note' + (snum + 1)).innerHTML; + } + + var jl = document.getElementById('jumplist'); + var slideTitle = jl.options[jl.selectedIndex].text.replace(/^\d+\s+:\s+/, '') + ((jl.selectedIndex) ? ' (' + jl.selectedIndex + '/' + (smax - 1) + ')' : ''); + if (incrementals[snum].length > 0) { +// alert('howdy'); + slideTitle += ' <small>[' + incpos + '/' + incrementals[snum].length + ']</small>'; + } + if (jl.selectedIndex < smax - 1) { + var nextTitle = jl.options[jl.selectedIndex + 1].text.replace(/^\d+\s+:\s+/, '') + ((jl.selectedIndex + 1) ? ' (' + (jl.selectedIndex + 1) + '/' + (smax - 1) + ')' : ''); + } else { + var nextTitle = '[end of slide show]'; + } + + if (s5NotesWindow && !s5NotesWindow.closed && s5NotesWindow.document) { + s5NotesWindow.document.getElementById('slide').innerHTML = slideTitle; + s5NotesWindow.document.getElementById('notes').innerHTML = notes; + s5NotesWindow.document.getElementById('next').innerHTML = nextTitle; + s5NotesWindow.document.getElementById('nextnotes').innerHTML = nextNotes; + } + resetElapsedSlide(); +} + +function minimizeTimer(id) { + var obj = s5NotesWindow.document.getElementById(id); + if (hasClass(obj,'collapsed')) { + removeClass(obj,'collapsed'); + } else { + addClass(obj,'collapsed'); + } +} + +function resetElapsedTime() { + presentationStart = new Date(); + slideStart = new Date(); + updateElaspedTime(); +} + +function resetElapsedSlide() { + if (snum != previousSlide) { + slideStart = new Date(); + previousSlide = snum; + updateElaspedTime(); + } +} + +function updateElaspedTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var now = new Date(); + var ep = s5NotesWindow.document.getElementById('elapsed-presentation'); + var es = s5NotesWindow.document.getElementById('elapsed-slide'); + ep.innerHTML = formatTime(now.valueOf() - presentationStart.valueOf()); + es.innerHTML = formatTime(now.valueOf() - slideStart.valueOf()); +} + +function resetRemainingTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var startField = s5NotesWindow.document.getElementById('startFrom'); + startFrom = readTime(startField.value); + countdown.remaining = startFrom * 60000; // convert to msecs + countdown.start = new Date().valueOf(); + countdown.end = countdown.start + countdown.remaining; + var tl = s5NotesWindow.document.getElementById('timeLeft'); + var timeLeft = formatTime(countdown.remaining); + tl.innerHTML = timeLeft; +} + +function updateRemainingTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var tl = s5NotesWindow.document.getElementById('timeLeft'); + var now = new Date(); + if (countdown.state == 'run') { + countdown.remaining = countdown.end - now; + } + tl.style.color = ''; + tl.style.backgroundColor = ''; + if (countdown.remaining >= 0) { + var timeLeft = formatTime(countdown.remaining); + removeClass(tl,'overtime'); + if (countdown.remaining < 300000) { + tl.style.color = 'rgb(' + (255-Math.round(countdown.remaining/2000)) + ',0,0)'; + tl.style.backgroundColor = 'rgb(255,255,' + (Math.round(countdown.remaining/2000)) + ')'; + } + } else { + var timeLeft = '-' + formatTime(-countdown.remaining); + addClass(tl,'overtime'); + } + tl.innerHTML = timeLeft; +} + +function toggleRemainingTime() { + if (countdown.state == 'pause') countdown.state = 'run'; else countdown.state = 'pause'; + if (countdown.state == 'pause') { + window.clearInterval(countdown.timer); + } + if (countdown.state == 'run') { + countdown.start = new Date().valueOf(); + countdown.end = countdown.start + countdown.remaining; + countdown.timer = window.setInterval('updateRemainingTime()', 1000); + } +} + +function alterRemainingTime(amt) { + var change = amt * 60000; // convert to msecs + countdown.end += change; + countdown.remaining += change; + updateRemainingTime(); +} + +function formatTime(msecs) { + var time = new Date(msecs); + + var hrs = time.getUTCHours() + ((time.getUTCDate() -1) * 24); // I doubt anyone will spend more than 24 hours on a presentation or single slide but just in case... + hrs = (hrs < 10) ? '0'+hrs : hrs; + if (hrs == 'NaN' || isNaN(hrs)) hrs = '--'; + + var min = time.getUTCMinutes(); + min = (min < 10) ? '0'+min : min; + if (min == 'NaN' || isNaN(min)) min = '--'; + + var sec = time.getUTCSeconds(); + sec = (sec < 10) ? '0'+sec : sec; + if (sec == 'NaN' || isNaN(sec)) sec = '--'; + + return hrs + ':' + min + ':' + sec; +} + +function readTime(val) { + var sregex = /:/; + var matches = sregex.exec(val); + if (matches == null) { + return val; + } else { + var times = val.split(':'); + var hours = parseInt(times[0]); + var mins = parseInt(times[1]); + var total = (hours * 60) + mins; + return total; + } +} + +function windowChange() { + fontScale(); +} + +function startup() { + defaultCheck(); + createControls(); // hallvord + slideLabel(); + incrementals = createIncrementals(); + noteLabel(); // [SI:060104] must follow slideLabel() + loadNote(); + fixLinks(); + externalLinks(); + fontScale(); + if (!isOp) notOperaFix(); + slideJump(); + if (defaultView == 'outline') { + toggle(); + } + document.onkeyup = keys; + document.onkeypress = trap; + document.onclick = clicker; +} + +window.onload = startup; +window.onresize = function(){setTimeout('windowChange()',5);} \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008/ui/s5-notes.html b/Moose_YAPC_Asia_2008/ui/s5-notes.html new file mode 100644 index 0000000..5c6c4ca --- /dev/null +++ b/Moose_YAPC_Asia_2008/ui/s5-notes.html @@ -0,0 +1,64 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<!-- Do not edit this document! The system will likely break if you do. --> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Notes</title> +<link rel="stylesheet" href="default/notes.css" type="text/css" /> +<script type="text/javascript"> +// <![CDATA[ + document.onkeyup = opener.keys; + document.onkeypress = opener.trap; + document.onclick = opener.clicker; +// ]]> +</script> +</head> + +<body onload="opener.s5NotesWindowLoaded=true;" onunload="opener.s5NotesWindowLoaded=false;"> + + +<div class="timers" id="elapsed"> +<h1> +<a href="#" onclick="opener.minimizeTimer('elapsed'); return false;">Elapsed Time</a> +</h1> +<ul> +<li> +<h2>Presentation</h2> +<span class="clock" id="elapsed-presentation">00:00:00</span> +</li> +<li> +<h2>Current Slide</h2> +<span class="clock" id="elapsed-slide">00:00:00</span> +</li> +</ul> +<div class="controls"> +<a href="#reset-elapsed" onclick="opener.resetElapsedTime(); return false;" title="Reset Elapsed Time">|←</a> +</div> +</div> + +<div class="timers" id="remaining"> +<h1> +<a href="#" onclick="opener.minimizeTimer('remaining'); return false;">Remaining Time</a> +</h1> +<p> +<a href="#subtract-remaining" class="control" id="minus" onclick="opener.alterRemainingTime('-5'); return false;" title="Subtract 5 Minutes">-</a> +<span class="clock" id="timeLeft">00:00:00</span> +<a href="#add-remaining" class="control" id="plus" onclick="opener.alterRemainingTime('5'); return false;" title="Add 5 Minutes">+</a> +</p> +<div class="controls"> +<form action="#" onsubmit="opener.resetRemainingTime(); return false;"> +<input type="text" class="text" id="startFrom" value="0" size="4" maxlength="4" /> +<a href="#toggle-remaining" onclick="opener.toggleRemainingTime(); return false;" title="Pause/Run Remaining Time">||</a> +<a href="#reset-remaining" onclick="opener.resetRemainingTime(); return false;" title="Reset Remaining Time">|←</a> +</form> +</div> +</div> + +<h2 id="slide">...</h2> +<div id="notes"></div> + +<h2 id="next">...</h2> +<div id="nextnotes"></div> + +</body> +</html> diff --git a/Moose_YAPC_Asia_2008_ja/practical_moose.html b/Moose_YAPC_Asia_2008_ja/practical_moose.html new file mode 100644 index 0000000..365b112 --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/practical_moose.html @@ -0,0 +1,1453 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + +<head> +<title>Moose</title> +<!-- metadata --> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> +<meta name="generator" content="TextMate/S5" /> +<meta name="version" content="S5 1.2a2" /> +<meta name="presdate" content="2008" /> +<meta name="author" content="Yuval Kogman" /> +<meta name="company" content="" /> +<!-- configuration parameters --> +<meta name="defaultView" content="slideshow" /> +<meta name="controlVis" content="visible" /> +<!-- style sheet links --> +<link rel="stylesheet" href="./ui/moose/slides.css" type="text/css" media="projection" id="slideProj" /> +<link rel="stylesheet" href="./ui/moose/outline.css" type="text/css" media="screen" id="outlineStyle" /> +<link rel="stylesheet" href="./ui/moose/print.css" type="text/css" media="print" id="slidePrint" /> +<link rel="stylesheet" href="./ui/moose/opera.css" type="text/css" media="projection" id="operaFix" /> +<!-- embedded styles --> +<style type="text/css" media="all"> +.imgcon {width: 525px; margin: 0 auto; padding: 0; text-align: center;} +#anim {width: 270px; height: 320px; position: relative; margin-top: 0.5em;} +#anim img {position: absolute; top: 42px; left: 24px;} +img#me01 {top: 0; left: 0;} +img#me02 {left: 23px;} +img#me04 {top: 44px;} +img#me05 {top: 43px;left: 36px;} +</style> +<!-- S5 JS --> +<script src="./ui/moose/slides.js" type="text/javascript"></script> +</head> +<body> + +<div class="layout"> +<div id="controls"><!-- DO NOT EDIT --></div> +<div id="currentSlide"><!-- DO NOT EDIT --></div> +<div id="header"></div> +<div id="footer"> +<h1>YAPC::Asia::2008</h1> +<h2>Moose</h2> +</div> +<div class="topleft"></div> +<div class="topright"></div> +<div class="bottomleft"></div> +<div class="bottomright"></div> +</div> + +<div class="presentation"> + +<div class="slide"> +<h1>Moose</h1> +<h2></h2> +<h3>Yuval Kogman</h3> +<h4></h4> +</div> + + +<div class="slide"> +<h1>Moose ã¯ãªã«ã§ã¯ãªãã</h1> + +<h2>Moose Is Not</h2> + +<ul> +<li>å®é¨ããããã¿ã¤ã (experimental)</li> +<li>ããã¡ã (toy)</li> +<li>ããä¸ã¤ã®ã¢ã¯ã»ãµãã«ãã¼ (accessor builder)</li> +<li>ã½ã¼ã¹ãã£ã«ã¿ (source filter)</li> +<li>é»éè¡ (black magic)</li> +<li>Perl 6 in Perl 5</li> +</ul> + +</div> + +<div class="slide"> +<h1>Mooseã¨ã¯ãªã«ã</h1> + +<h2>Moose Is</h2> + +<ul> +<li><p>Perlã®ããã®å®å ¨ã«ã¢ãã³ãªãªãã¸ã§ã¯ããã¬ã¼ã ã¯ã¼ã¯</p></li> +<li><p>A complete modern object framework for Perl</p></li> +</ul> + +</div> + +<div class="slide"> +<h1>Mooseã¨ã¯ãªã«ã</h1> + +<h2>Moose Is</h2> + +<ul> +<li>Class::MOPã®ããã®ã·ã³ã¿ãã¯ã¹ã·ã¥ã¬ã¼ (Syntactic sugar)</li> +<li>ç¥å ãã¡ (ancestry) +<ul> +<li>CLOS (Common Lisp Object System)</li> +<li>Smalltalk</li> +<li>Alces latifrons</li> +<li>Perl 6</li> +<li>â¦</li> +</ul></li> +<li>å®å®ãã¦ãã¦ããä»äºã«ãã¤ããã¾ã (Stable & Production ready)</li> +</ul> + +</div> + +<div class="slide"> +<h1>ã·ã³ãã«ãªä¾</h1> + +<h2>A Simple Example</h2> + +<pre><code> +package Person; + +use strict; +use warnings; + +sub new { + my ($class) = @_; + + return bless { + name => '', + age => undef, + }, $class; +} + +sub name { + my ($self, $name) = @_; + $self->{'name'} = $name if $name; + return $self->{'name'}; +} + +sub age { + my ($self, $age) = @_; + $self->{'age'} = $age if $age; + return $self->{'age'}; +} + +1; +</code></pre> + +</div> + +<div class="slide"> +<h1>ã·ã³ãã«ãªMooseã®ä¾</h1> + +<h2>A Simple Moose Example</h2> + +<pre><code> +package Person; +use Moose; + +has name => (is => 'rw'); +has age => (is => 'rw'); + +1; +</code></pre> + +</div> + +<div class="slide"> +<h1>ã·ã³ãã«ãªMooseã®ä¾(ã¤ã¥ã)</h1> + +<h2>A Simple Moose Example (cont.)</h2> + +<ul> +<li><code>use Moose;</code> +<ul> +<li>ãã¼ã¯ã¼ããã¤ã³ãã¼ã (imports keywords)</li> +<li><code>use strict; use warnings;</code></li> +<li><code>@ISA = qw(Moose::Object) unless @ISA</code></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>ã·ã³ãã«ãªMooseã®ä¾(ã¤ã¥ã)</h1> + +<h2>A Simple Moose Example (cont.)</h2> + +<ul> +<li><p><code>has</code> ã¯ã¢ããªãã¥ã¼ããå®ç¾©ãã (declares attibutes)</p> + +<ul> +<li>ã¢ã¯ã»ãµãçæ (generates accessors)</li> +<li><code>is => 'rw'</code> â èªã¿æ¸ã両ç¨ã¢ã¯ã»ãµ</li> +<li><code>is => 'ro'</code> â èªã¿è¾¼ã¿å°ç¨ã¢ã¯ã»ãµ</li> +<li><code>writer</code>, <code>reader</code></li> +</ul></li> +<li><p><code>new</code> 㯠<code>Moose::Object</code> ããç¶æ¿ãã</p></li> +</ul> + +<div class="notes"> +<p>ä»åº¦ã¯ã¢ããªãã¥ã¼ãã®æ©è½ã説æãã¦ããã +Now we’re going to discuss more features of the attributes</p> +</div> +</div> + +<div class="slide"> +<h1>Mooseã®ä¾ã®ããªã¨ã¼ã·ã§ã³</h1> + +<h2>Variations on a Moose Example</h2> + +<pre><code> +package Person; +use Moose; + +has name => ( + is => 'rw', + isa => 'Str' + default => 'Bob' +); + +has staff => ( + is => 'ro', + isa => 'ArrayRef', + lazy => 1, + default => sub { [qw(Bob Alice Tim)] }, +); +</code></pre> + +<div class="notes"> +<p>default 㨠isa ã追å ããã¦ã¾ã +Adds default, isa</p> +</div> +</div> + +<div class="slide"> +<h1>Mooseã®ä¾ã®ããªã¨ã¼ã·ã§ã³(ã¤ã¥ã)</h1> + +<h2>Variations on a Moose Example (cont.)</h2> + +<ul> +<li><p><code>default</code> ã¯</p> + +<ul> +<li>ã³ã¼ããªãã¡ã¬ã³ã¹ (coderef)</li> +<li>ã¾ãã¯ãªãã¡ã¬ã³ã¹ä»¥å¤ (æ°å¤, æåå) (nonref)</li> +<li><code>new</code> ã«ãã©ã¡ã¼ã¿ããããããªãã£ãã¨ãã«ä½¿ããã</li> +</ul></li> +<li><p><code>lazy</code> 㯠<code>default</code> ãé å»¶ããã</p> + +<ul> +<li>æåã« <code>$object->staff</code> ã使ãããã¨ãã«å¼ã°ãã (generates)</li> +<li><code>new</code> ã®ä¸ã§ã¯ãªã (no param)</li> +</ul></li> +</ul> + +<div class="notes"> +<p>ããã©ã«ãã®è©± +discusses default</p> + +<p>ãªãã¡ã¬ã³ã¹ã§ãªãã¨æ³å®å¤ã®å ±æãããããããªã +non refs make accidental sharing hard</p> +</div> +</div> + +<div class="slide"> +<h1>Mooseã®ä¾ã®ããªã¨ã¼ã·ã§ã³(ã¤ã¥ã)</h1> + +<h2>Variations on a Moose Example (cont.)</h2> + +<ul> +<li><code>isa</code> ã¯åãè¦å®ãã (specifies type) +<ul> +<li><code>Moose::Util::TypeConstraints</code> +<ul> +<li><code>Any, Item, Bool, Undef, Defined, Value, Num, Int, Str, Ref, ScalarRef, ArrayRef, HashRef, CodeRef, RegexpRef, GlobRef, FileHandle, Object, and Role</code></li> +</ul></li> +<li>åã¯åå¨ããå¿ è¦ã¯ããã¾ãã (don’t need to exist)</li> +</ul></li> +</ul> + +<pre><code> + has 'date' => (isa => 'DateTime'); # DWIM +</code></pre> + +<div class="notes"> +<p>isa, åã®å¶ç´ +isa, type constraints</p> +</div> +</div> + +<div class="slide"> +<h1>å</h1> + +<h2>Typical Family</h2> + +<ul> +<li>åã¯é層æ§é ããã£ã¦ãã (types have a hierarchy) +<ul> +<li><code>Item</code> â <code>Defined</code> â <code>Ref</code> â <code>Object</code></li> +</ul></li> +</ul> + +<pre><code> + subtype 'Ref' + => as 'Defined' + => where { ref($_) }; + + subtype 'Object' + => as 'Ref' + => where { blessed($_) } +</code></pre> + +<div class="notes"> +<p>åã®é層æ§é +type hierarchy</p> +</div> +</div> + +<div class="slide"> +<h1>åã®å¼·å¶å¤æ</h1> + +<h2>Some Type of Coercion</h2> + +<pre><code> +package Employee; +use Moose; +use Moose::Util::TypeConstraints; +extends qw(Person); + +class_type 'Manager'; + +coerce 'Manager' + => from 'Str' + => via { Manager->new( name => $_) }; + +has manager => ( + is => 'ro', + isa => 'Manager', + required => 1, + coerce => 1, +); +</code></pre> + +</div> + +<div class="slide"> +<h1>åã®å¼·å¶å¤æ(ã¤ã¥ã)</h1> + +<h2>Some Type of Coercion (cont.)</h2> + +<pre><code> +# åå¶ç´ã®ãã¼ã¯ã¼ããã¤ã³ãã¼ã(import type constraint keywords) +use Moose::Util::TypeConstraints; + + +# ãªãã¸ã§ã¯ãã®ãµãã¿ã¤ãã§ããããã¼ã¸ã£ã¼ãå®ç¾©(define Manager, a subtype of Object) +class_type "Manager"; + + +# 夿ãå®ç¾©ãã(define the conversion) +coerce 'Manager' + => from 'Str' + => via { Manager->new( name => $_) }; + + +# ã¢ããªãã¥ã¼ããã¨ã«æå¹ã«ãã(enable it per attribute) +has manager => ( + ⦠+ coerce => 1, +); +</code></pre> + +<div class="notes"> +<p>ä¾ãç´°ããè¦ã¦ããã +breakdown of the example</p> + +<p>ã¯ã©ã¹ã®åã¯Mooseã®ã¯ã©ã¹ãã¹ã¦ã«èªåçã«ç¨æããã¾ã +class types are automatically created for all Moose classes</p> +</div> +</div> + +<div class="slide"> +<h1>ä¼çµ±çãªå§è²</h1> + +<h2>Conventional Delegates</h2> + +<pre><code> +package Employee; +use Moose; +extends qw(Person); + +has manager => ( + is => 'ro', + isa => 'Manager', + handles => { + manager_name => 'name', + coworkers => 'staff', + } +); +</code></pre> + +<ul> +<li>ããã¼ã¸ã£ã¼ã¯ <code>Employee</code> ã®ããã¤ãã®ã¡ã½ãããå¦çãã¾ã</li> +<li>manager <code>handles</code> certain methods for <code>Employee</code> +<ul> +<li><code>$emp->coworkers</code> == <code>$emp->manager->staff</code></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>ä¼çµ±çãªå§è²(ã¤ã¥ã)</h1> + +<h2>Conventional Delegates (cont.)</h2> + +<pre><code> +has phone => ( + ... + handles => [qw(number extension)], +); +</code></pre> + +</div> + +<div class="slide"> +<h1>ä¼çµ±çãªå§è²(ã¤ã¥ã)</h1> + +<h2>Conventional Delegates (cont.)</h2> + +<pre><code> +has phone => ( + isa => "Phone" + handles => qr/$method_regex/, +); +</code></pre> + +<ul> +<li><code>Phone->meta->compute_all_applicable_methods</code>ã«ãã£ã«ã¿ã¼ãããã</li> +<li>Filters <code>Phone->meta->compute_all_applicable_methods</code></li> +</ul> + +</div> + +<div class="slide"> +<h1>ä¼çµ±çãªå§è²(ã¤ã¥ã)</h1> + +<h2>Conventional Delegates (cont.)</h2> + +<pre><code> +has phone => ( + ... + handles => "Dialing", # a role +); +</code></pre> + +</div> + +<div class="slide"> +<h1>ä¼çµ±çãããªãå§è²</h1> + +<h2>UnConventional Delegates</h2> + +<pre><code> +package Company; +use Moose; +use MooseX::AttributeHelpers; + +has employees => ( + metaclass => 'Collection::Array', + isa => 'ArrayRef[Employees]', + is => 'rw', + provides => { + push => 'add_employee', + pop => 'remove_employee', + count => 'number_of_employees', + empty => 'any_employees', + } +); +</code></pre> + +</div> + +<div class="slide"> +<h1>ã¡ã½ãã夿´ã®ã»ã«ã¤</h1> + +<h2>Modified Methods</h2> + +<pre><code> +before 'employees' => sub { warn 'calling employees' }; + +after 'employees' => sub { warn 'finished calling employees' }; +</code></pre> + +<ul> +<li>ç¾å¨ã®ã¡ã½ãããå®è¡ãããåï¼ãããå¾ã«å®è¡ããã¾ã</li> +<li>Pre/Post hooks +<ul> +<li><code>@_</code>ã®ã³ãã¼ãå¾ã¾ã(Get a copy of <code>@_</code>)</li> +<li>è¿ãå¤ã¯ç¡è¦ããã¾ã(Return value is ignored)</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>ã¡ã½ãã夿´ã®ã»ã«ã¤(ã¤ã¥ã)</h1> + +<h2>Modified Methods (cont.)</h2> + +<pre><code> +around 'employees' => sub { + my ($next, $self, @args) = @_; + ... + my @return = $self->$next(@args); + ... + return @return; +}; +</code></pre> + +</div> + +<div class="slide"> +<h1>ã¡ã½ãã夿´ã®ã»ã«ã¤(ã¤ã¥ã)</h1> + +<h2>Modified Methods (cont.)</h2> + +<pre><code> +package Employee; +use Moose; + +sub do_work { + my $self = shift; + + $self->punch_in; + + inner(); # call subclass here + + $self->punch_out; +} +</code></pre> + +</div> + +<div class="slide"> +<h1>ã¡ã½ãã夿´ã®ã»ã«ã¤(ã¤ã¥ã)</h1> + +<h2>Modified Methods (cont.)</h2> + +<pre><code> +package Employee::Chef; +use Moose; + +extends qw(Employee); + +augment do_work => sub { + my $self = shift; + + while ( @burgers ) { + $self->flip_burger(shift @burgers); + } +} + +$chef->do_work; # punch in, flip burgers, punch out +</code></pre> + +</div> + +<div class="slide"> +<h1>åã«ã¤ãã¦ã®ä½è«</h1> + +<h2>Some Type of Digression</h2> + +<pre><code> +has employees => ( + is => 'rw', + isa => 'ArrayRef[Employee]', +); + +has shopping_carts => ( + is => 'rw', + isa => 'ArrayRef[ArrayRef[ShinyBead]]' +); +</code></pre> + +<div class="notes"> +<p>åã·ã¹ãã ã®æ©è½ã«ã¤ãã¦ã¡ãã£ã¨èª¬æãã¦ããã +Going to go into features of the type system for a bit</p> + +<p>ãã©ã¡ã¼ã¿ä»ãã®å +Parametrized types</p> +</div> +</div> + +<div class="slide"> +<h1>åã«ã¤ãã¦ã®ä½è«(ã¤ã¥ã)</h1> + +<h2>Some Type of Digression (cont.)</h2> + +<pre><code> +has language => ( + is => 'rw', + isa => 'English | Welsh | Scots | Gaelic', +); + +has member => ( + is => 'rw', + isa => 'Employee | ArrayRef[Employee|Group]', +); +</code></pre> + +<div class="notes"> +<p>åã®çµå +Union types</p> +</div> +</div> + +<div class="slide"> +<h1>åã«ã¤ãã¦ã®ä½è«(ã¤ã¥ã)</h1> + +<h2>Some Type of Digression (cont.)</h2> + +<pre><code> +package Foo; +use Moose; +use Moose::Util::TypeConstraints; +use Test::Deep qw(eq_deeply ...); + +type 'SomethingTricky' + => where { + eq_deeply( $_, ... ); + }; + +has 'bar' => ( + is => 'rw', + isa => 'SomethingTricky', +); +</code></pre> + +<div class="notes"> +<p>Test::Deppã®ã«ã¹ã¿ã ããªãã¼ã¿ +Test::Deep custom validator</p> + +<p>CPANããã©ããªããªãã¼ã¿ã§ãæã£ã¦ãããã +Can use any validation from the CPAN</p> +</div> +</div> + +<div class="slide"> +<h1>ãã©ã¡ã¼ã¿ä»ãã®åã®å¼·å¶å¤æ</h1> + +<h2>Some Parametrized Type of Coercion</h2> + +<pre><code> +use Moose::Util::TypeConstraints; +subtype 'ArrayRef[Employee]' => as 'ArrayRef'; + +coerce 'ArrayRef[Employee]' + => from 'ArrayRef[Str]' + => via { [ map { Employee->new( name => $_ ) } @$_ ] }; + +has staff => ( + is => 'ro', + isa => 'ArrayRef[Employee]', + lazy => 1, + default => sub { [qw(Bob Alice Tim)] }, + coerce => 1, +); +</code></pre> + +<div class="notes"> +<p>ArrayRef[Str] ãã ArrayRef[Employee] ã«å¼·å¶å¤æ +coerce parametrized ArrayRef[Employee] from ArrayRef[Str]</p> + +<p>å¼·å¶å¤æã¯ ‘default’ ã®è¿ãå¤ã«ãé©ç¨ããã¾ã +coercions can be applied to ‘default’ return values</p> +</div> +</div> + +<div class="slide"> +<h1>Mooseã®Role </h1> + +<h2>Role of the Moose</h2> + +<ul> +<li>Role ã¯â¦(A role is like a) +<ul> +<li>Javaã®Interfaceã¿ãã</li> +<li>mixinã¿ãã</li> +<li>â¦ããã§ãã¦å®å ¨ã§ãã¯ãã«(safe, powerful)</li> +</ul></li> +<li>Role ã¯å°ããã¦åå©ç¨å¯è½ãªåä½åã(A role is for small reusable behaviors) +<ul> +<li>å¤éç¶æ¿ãããã(better than using a multiple inheritence)</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Mooseã®Role(ã¤ã¥ã)</h1> + +<h2>Role of the Moose (cont.)</h2> + +<ul> +<li>CPAN ã«ãã Role ãã¡(Roles on the CPAN): +<ul> +<li><code>MooseX::Storage</code> - æè»ãªã·ãªã¢ã©ã¤ãº(Flexible serialization)</li> +<li><code>MooseX::LogDispatch</code> - <code>$self->logger->info("something happenned")</code></li> +<li><code>MooseX::Getopt</code> - ã³ãã³ãã©ã¤ã³å¼æ°ã®å¦ç(<code>@ARGV</code> aware constructor)</li> +<li><code>MooseX::Param</code> - <code>CGI.pm</code> ã® <code>param()</code> ã¡ã½ããã¿ãããªã®(<code>param</code> method like <code>CGI.pm</code>’s)</li> +<li><code>MooseX::Clone</code> - æè»ãª<code>clone</code>ã¡ã½ãã(Flexible <code>clone</code> method)</li> +</ul></li> +</ul> + +<div class="notes"> +<p>åå©ç¨å¯è½ãªå°ããªåä½ã®ä¾ +Some examples of small reusable behaviors</p> + +<p>Paramã¯é£æºã«ä¾¿å© +Param is good for interacting with e.g. CGI::Expand or similar modules</p> +</div> +</div> + +<div class="slide"> +<h1>Mooseã®Role(ã¤ã¥ã)</h1> + +<h2>Role of the Moose (cont.)</h2> + +<pre><code> +package Minion; +use Moose; + +extends qw(Employee); + +with qw(Salaried::Hourly); + +package Boss; +use Moose; + +extends qw(Employee); + +with qw(Salaried::Monthly); + +</code></pre> + +<ul> +<li><code>with</code> ã¯ã¯ã©ã¹ã« Role ã追å ãã¾ã</li> +<li><code>with</code> adds roles into your class +<ul> +<li><code>Salaried::Hourly</code>ã<code>Minion</code>ã«è¿½å ããã</li> +<li><code>Salaried::Hourly</code> was added to <code>Minion</code></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Mooseã®Role(ã¤ã¥ã)</h1> + +<h2>Role of the Moose (cont.)</h2> + +<pre><code> +package Salaried; +use Moose::Role; + +requires qw('paycheck_amount'); +</code></pre> + +<ul> +<li>åãªãã¤ã³ã¿ã¼ãã§ã¼ã¹</li> +<li>Just an interface</li> +</ul> + +</div> + +<div class="slide"> +<h1>Mooseã®Role(ã¤ã¥ã)</h1> + +<h2>Role of the Moose (cont.)</h2> + +<pre><code> +package Salaried::Hourly; +use Moose::Role; + +with qw(Salaried); + +has hourly_rate => ( + isa => "Num", + is => "rw", + required => 1, +); + +has logged_hours => ( + isa => "Num", + is => "rw", + default => 0, +); + +sub paycheck_amount { + my $self = shift; + + $self->logged_hours * $self->hourly_rate; +} + +</code></pre> + +<ul> +<li>ã¤ã³ã¿ã¼ãã§ã¼ã¹ããã¤ã¤ã!</li> +<li>More than an interface</li> +</ul> + +</div> + +<div class="slide"> +<h1>Mooseã®Role(ã¤ã¥ã)</h1> + +<h2>Role of the Moose (cont.)</h2> + +<ul> +<li>Javaã®ã¤ã³ã¿ã¼ãã§ã¼ã¹ããã¤ã¤ã!</li> +<li>More than Java Interfaces +<ul> +<li>ã¤ã³ã¿ã¼ãã§ã¼ã¹ã¯æåã®’è¦å®’ãæä¾ãã</li> +<li>Interfaces are behavior “contracts”</li> +<li>Role ã¯æåã®’å®è£ ’ãæä¾ã§ãã</li> +<li>Roles can also have code</li> +</ul></li> +</ul> + +<div class="notes"> +<p>Roleã¯ã¢ããªãã¥ã¼ãã¨ã¡ã½ãããæã¦ã +roles can have attributes and methods +Roleã¯ã¤ã³ã¿ã¼ãã§ã¼ã¹ã ãã§ãªãåä½ãæä¾ãããã® +roles provide behavior, not just interface</p> +</div> +</div> + +<div class="slide"> +<h1>Mooseã®Role(ã¤ã¥ã)</h1> + +<h2>Role of the Moose (cont.)</h2> + +<ul> +<li>Roleã®çµã¿è¾¼ã¿(Role Composition) +<ul> +<li>ç¶æ¿ã§ã¯ãªã(Not inheritence)</li> +<li>å§å©ä¸¡ææ(Symmetric)</li> +<li>é åºã¯é¢ä¿ãªã(Unordered)</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Mooseã®Role(ã¤ã¥ã)</h1> + +<h2>Role of the Moose (cont.)</h2> + +<ul> +<li>Roleã®çµã¿è¾¼ã¿(Role Composition) +<ul> +<li>ããã¾ãããå°ãªã(Less ambiguity)</li> +<li>ã³ã³ãã¤ã«æã¨ã©ã¼(Compile time errors)</li> +<li>â¦ä¿®æ£ããæ¹æ³ããã(And ways to fix them)</li> +</ul></li> +</ul> + +<div class="notes"> +<p>å§å©ä¸¡ææã¨ããã®ã¯åªå é ä½ããªãã¨ãããã¨ããµãã¤ã®Roleãåããã®ãå®ç¾©ãããã¨ããå ´åã¯ã³ã³ãã¤ã«æã«ã¨ã©ã¼ã«ãªãï¼ç´ããªãã¨ãããªãï¼ +symmetric composition means no precedence - if two roles try to define the same thing you get a compile time error that needs to be resolved +å¤éç¶æ¿ã®å ´åã¯ã ã¾ã£ã¦æåã®ã¯ã©ã¹ã使ãããã ã¨æ³å®ãã¦ãã¾ã +multiple inheritence silently assumes you want the first class</p> + +<p>Roleã¯å¤éç¶æ¿ã¨éã£ã¦ã³ã³ãã¤ã«æã«ã¨ã©ã¼ãåã +roles cause errors at compile time, unlike multiple inheritence</p> + +<p>Roleã¯ç°¡åã«ã¨ã©ã¼ãä¿®æ£ããæ¹æ³ãç¨æãã¦ãã +roles also provide easy ways to fix the errors</p> +</div> +</div> + +<div class="slide"> +<h1>Mooseã®Role(ã¤ã¥ã)</h1> + +<h2>Role of the Moose (cont.)</h2> + +<pre><code> +package First; +use Moose::Role; + +sub dancing { ... } + +package Second; +use Moose::Role + +sub dancing { ... } + +package Foo; +use Moose; + +# KABOOM +with qw( + First + Second +); +</code></pre> + +<div class="notes"> +<p>è¡çª +conflicts</p> +</div> +</div> + +<div class="slide"> +<h1>Mooseã®Role(ã¤ã¥ã)</h1> + +<h2>Role of the Moose (cont.)</h2> + +<pre><code> +package Ent::Puppy; +use Moose; + +with ( + Tree => { + alias => { + bark => "tree_bark", + }, + }, + Dog => { + alias => { + bark => "bark_sound", + } + }, +); + +sub bark { + my $self = shift; + + if ( $condition ) { + $self->tree_bark; + } else { + $self->bark_sound; + } +} +</code></pre> + +<div class="notes"> +<p>çµã¿è¾¼ãã¨ãã«ãã©ã¡ã¼ã¿ãã¤ãã +Composition parameters +è¡çªã解決ããã®ãç°¡åã ã +Easier conflict resolution +ããããç´°ããã³ã³ããã¼ã«ãã§ããããã«ãªã +Finer grained control</p> +</div> +</div> + +<div class="slide"> +<h1>MOPã¯ãã¬ã¤</h1> + +<h2>MOPs Mean Cleanliness</h2> + +<ul> +<li>Moose 㯠Class::MOP ã§ã¤ãããã¦ã</li> +<li>Moose is based on <code>Class::MOP</code> +<ul> +<li>Perl5ã®ããã®ã¡ã¿ãªãã¸ã§ã¯ããããã³ã«(Metaobject Protocol for Perl 5)</li> +<li>ãã¹ã¦ã«ãªãã¸ã§ã¯ããã¤ãããã(“makes an object for everything”)</li> +</ul></li> +</ul> + +<pre><code> +my $class = $obj->meta; # $objã®ã¡ã¿ã¯ã©ã¹($obj's metaclass) +my $meta = MyApp->meta; # MyAppã®ã¡ã¿ã¯ã©ã¹(MyApp's metaclass) +my $emo = $obj->meta->meta # ã¡ã¿ã¡ã¿(even more meta)! + +warn $obj->meta->name; +</code></pre> + +</div> + +<div class="slide"> +<h1>å å´ããã¿ã¦ã¿ã</h1> + +<h2>Looking in From the Inside</h2> + +<pre><code> +my $metaclass = $self->meta; + +$metaclass->superclasses; + +$metaclass->linearized_isa; # ãã¹ã¦ã®å ç¥ã¯ã©ã¹ãå¾ã¾ã(returns all ancestors) + +$metaclass->has_method("foo"); + +$metaclass->compute_all_applicable_methods; # ãã¹ã¦ã®ã¡ã½ãã(ç¶æ¿ããããã®ããµããã¦)(returns all methods (inherited too)) + +$metaclass->has_attribute("bar"); + +# ⦠lots more +</code></pre> + +<div class="notes"> +<p>simple introspection</p> +</div> +</div> + +<div class="slide"> +<h1>å å´ããã¿ã¦ã¿ã(ã¤ã¥ã)</h1> + +<h2>Looking in From the Inside (cont.)</h2> + +<pre><code> +Moose::Meta::Class->create( Bar => + version => '0.01', + superclasses => [ 'Foo' ], + attributes => [ + Moose::Meta::Attribute->new( bar => ... ), + Moose::Meta::Attribute->new( baz => ... ), + ], + methods => { + calculate_bar => sub { ... }, + construct_baz => sub { ... } + } +); +</code></pre> + +<div class="notes"> +<p>ã¯ã©ã¹ã¯ããã°ã©ã çã«ã¤ãããã¨ãã§ãã +Classes can be created programmatically</p> + +<p>ç¡åã¯ã©ã¹ãå¯ +Anonymous classes also possible</p> +</div> +</div> + +<div class="slide"> +<h1>å å´ããã¿ã¦ã¿ã(ã¤ã¥ã)</h1> + +<h2>Looking in From the Inside (cont.)</h2> + +<pre><code> +has foo => ( is => "rw" ); + +__PACKAGE__->meta->add_attribute( foo => is => "rw" ); +</code></pre> + +<ul> +<li>Mooseã¯åãªãã·ã¥ã¬ã¼(Moose is just sugar) +<ul> +<li>大å¤ãªé¨åã¯MOPããã¦ããã(The MOP does the hard work)</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>ã¡ã¿ã¯ã©ã¹ã®ã¿ã³ã´</h1> + +<h2>The Metaclass Tango</h2> + +<ul> +<li>ã¡ã¿ã¯ã©ã¹ã¯ã¯ã©ã¹ã®æåãã³ã³ããã¼ã«ãã</li> +<li>Metaclassses control class behavior</li> +</ul> + +<pre><code> +has employees => ( + metaclass => 'Collection::Array', + ... +); +</code></pre> + +<ul> +<li>ã«ã¹ã¿ã ã¢ããªãã¥ã¼ãã¡ã¿ã¯ã©ã¹ã¯</li> +<li>custom attribute metaclasses +<ul> +<li>ã¢ããªãã¥ã¼ããã©ããã風ã«åãããå¤ãã</li> +<li>change how attributes work</li> +</ul></li> +<li>ã«ã¹ã¿ãã¤ãºå¯è½ãªãã¼ããã¡</li> +<li>Many customizable parts +<ul> +<li><code>Moose::Meta::Class</code>, <code>Moose::Meta::Attribute,</code><code>Moose::Meta::Method</code>, <code>Moose::Meta::Method::Accessor</code> <code>Moose::Meta::Instance</code>, <code>Moose::Meta::Role</code>, <code>Moose::Meta::TypeConstraint</code>, â¦,</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>ã¡ã¿ãã¬ã¼ã ã使ã</h1> + +<h2>Working in the Meta Frame</h2> + +<ul> +<li>ä»äºã§ãã£ããããã話(An interesting <code>$work</code> story)</li> +<li>flashã使ã£ããµã¤ãç¨ã®CMS(CMS for a flash website)</li> +<li>ã³ã³ãã³ãã¯XML(Content is in XML)</li> +</ul> + +</div> + +<div class="slide"> +<h1>ã¡ã¿ãã¬ã¼ã ã使ã(ã¤ã¥ã)</h1> + +<h2>Working in the Meta Frame (cont.)</h2> + +<ul> +<li>Step 1. use Moose</li> +<li>Step 2. ???</li> +<li>Step 3. é(Profit)!</li> +</ul> + +</div> + +<div class="slide"> +<h1>ã¡ã¿ãã¬ã¼ã ã使ã(ã¤ã¥ã)</h1> + +<h2>Working in the Meta Frame (cont.)</h2> + +<ul> +<li>Step 2.1. XMLã¹ãã¼ã(schemas) â ã¯ã©ã¹(classes) +<ul> +<li>èªå夿(Automatic conversion) +<ul> +<li>MOPã®ãããã§æ¥½å(MOP makes it easy)</li> +</ul></li> +<li>å®è¡æã«ã¯é«ã¬ãã«ãªãã¸ã§ã¯ã(High level objects in runtime)</li> +<li>è£ã§ã¯XML(XML backed) +<ul> +<li>ã¯ã©ã¤ã¢ã³ãã®ã¹ãã¼ã(With client’s schemas)</li> +<li>SAX â Moose</li> +<li>Moose â SAX</li> +</ul></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>ã¡ã¿ãã¬ã¼ã ã使ã(ã¤ã¥ã)</h1> + +<h2>Working in the Meta Frame (cont.)</h2> + +<ul> +<li>Step 2.2. ã¡ã¿è¨è¿°(Meta descriptions) +<ul> +<li>ã¡ã¿ã¯ã©ã¹ãæ¡å¼µ(Extend the metaclasses)</li> +<li>追å ã®æ å ±ãåãè¾¼ã(Embed additional information) +<ul> +<li>ãã£ã¼ã«ãå(field types)</li> +<li>ã¢ã¯ã»ã¹ã³ã³ããã¼ã«(access control)</li> +</ul></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>ã¡ã¿ãã¬ã¼ã ã使ã(ã¤ã¥ã)</h1> + +<h2>Working in the Meta Frame (cont.)</h2> + +<ul> +<li>Step 2.3 ã¤ã³ããã¹ãã¯ã·ã§ã³ãããã(Introspection goodness) +<ul> +<li>æ±ç¨Webããã³ãã¨ã³ã(Generic web frontend)</li> +<li>ãªãã¸ã§ã¯ãã¤ã³ããã¹ãã¯ã·ã§ã³ãã¼ã¹(Object introspection based) +<ul> +<li>HTMLãã¥ã¼(view)</li> +<li>ç·¨éç¨ã®ã¦ã£ã¸ã§ãã(Editing widgets)</li> +</ul></li> +<li>ã¯ãªã¼ã³ã§æ¡å¼µæ§ãé«ã(Clean, extensible)</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Moose ã®æ¬ ç¹</h1> + +<h2>Drawbacks of Moose</h2> + +<ul> +<li>ãã¼ãæé(Load time) +<ul> +<li><code>MooseX::Compile</code> ãã¢ã«ã§ã(<code>MooseX::Compile</code> is in the works)</li> +</ul></li> +<li>ããã¤ãã®æ©è½ãé ã(Some features are slow) +<ul> +<li>ã§ããããªããã¤ãã£ãã¶ãã ãã ãã(but you only pay for what you use)</li> +</ul></li> +<li>hashref ãããªãã¯ã©ã¹ã®æ¡å¼µã¯ããªããã¼(Extending non-Hash based classes is tricky). +<ul> +<li>ã§ãå¯è½(but possible): <code>MooseX::GlobRef::Object</code></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Mooseã®ã¤ã¤!ã¨ã</h1> + +<h2>Benefits of Moose</h2> + +<ul> +<li>éå±ãªãã¨ãæ¸ããã(Less tedious) +<ul> +<li>決ã¾ãæå¥ãæ¸ããªãã¦ãã(ditch that boilerplate): +<ul> +<li>ã¢ããªãã¥ã¼ãã®ã¹ãã¬ã¼ã¸/ã¢ã¯ã»ãµ(attribute storage/access)</li> +<li>ã³ã³ã¹ãã©ã¯ã¿(construction)</li> +<li>ãã¹ãã©ã¯ã¿(destruction)</li> +<li>弿°æ¤æ»(verification)</li> +<li>â¦</li> +</ul></li> +<li>ç¹°ãè¿ããæ¸ããã(less repetition)</li> +<li>typo ãæ¸ããã(fewer typos)</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Mooseã®ã¤ã¤!ã¨ã(ã¤ã¥ã)</h1> + +<h2>Benefits of Moose (cont.)</h2> + +<ul> +<li>ã¿ããã(Shorter) +<ul> +<li>declarative == æ å ±ãããããã¿ã¤ãæ°ããããªã(more info, less typing)</li> +<li>no RSI ;-)</li> +<li>ã³ã¼ãããããªãããã°ããããªããã(less code means fewer bugs)</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Mooseã®ã¤ã¤!ã¨ã(ã¤ã¥ã)</h1> + +<h2>Benefits of Moose (cont.)</h2> + +<ul> +<li>ãã¹ãããããªãã¦ãã(Less testing) +<ul> +<li>Moose ã¯ãããã¹ãããã¦ãã</li> +<li>Moose is well tested +<ul> +<li>ã¢ã¯ã»ãµããæåããããã§ãã¯ããã§ãããã</li> +<li>no need to check accessor behavior, etc</li> +</ul></li> +<li>ããªãã®ã³ã¼ãã®ç®çã«ãã©ã¼ã«ã¹ã§ãã¾ã!</li> +<li>focus on your code’s purpose +<ul> +<li>ãã¡ãã¨ãã¾ã¨ãã¦ããããªãã¦ãããã</li> +<li>not that it is “assembled” correctly</li> +<li>http://c2.com/cgi/wiki?IntentionNotAlgorithm</li> +</ul></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Mooseã®ã¤ã¤!ã¨ã(ã¤ã¥ã)</h1> + +<h2>Benefits of Moose (cont.)</h2> + +<ul> +<li>èªã¿ããã(More readable) +<ul> +<li>宣è¨çãªã¹ã¿ã¤ã«ã ãããã®ã¾ã¾ææ¸ã«ãªã£ã¦ãã</li> +<li>declarative style is self documenting</li> +<li>ãããããã¨ãæ¸ããé¢ä¿ãªãOOã®ãããã¨ãã¯ãã¾ãæ¸ããªãã¦ããã</li> +<li>Code your intentions, not and OO mechanics less</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Mooseã®ã¤ã¤!ã¨ã(ã¤ã¥ã)</h1> + +<h2>Benefits of Moose (cont.)</h2> + +<ul> +<li>Meta object protocol +<ul> +<li>Perl ã® OO ã綺éºã«ãã¤ããã¾ã</li> +<li>Cleans up all levels of Perl’s OO</li> +<li>ã¤ã³ããã¹ãã¯ã·ã§ã³ã§ãã¾ã</li> +<li>Provides introspection</li> +<li>ãã¯ãã«ãªæ½è±¡å</li> +<li>Enables powerful abstractions</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Mooseã®ã¤ã¤!ã¨ã(ã¤ã¥ã)</h1> + +<h2>Benefits of Moose (cont.)</h2> + +<ul> +<li>ä»å¹´ã®æµè¡ã ã</li> +<li>It’s the new black +<ul> +<li>ã¤ã«ããé£ä¸ã¯ã¿ããª#mooseã«ãã¦ãã</li> +<li>All the cool kids hang out on #moose</li> +<li>ãã£ãããããªããºã¯ã¼ã</li> +<li>Smart sounding buzzwords</li> +<li>2007å¹´ã«ã¯Rubyãããã ã£ãã</li> +<li>Ruby is so 2007</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>ãã¾ã</h1> + +<h2>Bonus Material</h2> + +</div> + +<div class="slide"> +<h1>Autobox</h1> + +<pre><code> +package Units::Bytes; +use Moose::Role; +use Moose::Autobox; + +sub bytes { $_[0] } +sub kilobytes { $_[0] * 1024 } +sub megabytes { $_[0] * 1024->kilobytes } +sub gigabytes { $_[0] * 1024->megabytes } +sub terabytes { $_[0] * 1024->gigabytes } + +Moose::Autobox->mixin_additional_role(SCALAR => 'Units::Bytes'); +</code></pre> + +</div> + +<div class="slide"> +<h1>Autobox (ã¤ã¥ã)</h1> + +<h2>Autobox (cont.)</h2> + +<pre><code> +use Units::Bytes; +use Moose::Autobox; + +is(5->bytes, 5, '... got 5 bytes'); +is(5->kilobytes, 5120, '... got 5 kilobytes'); +is(2->megabytes, 2097152, '... got 2 megabytes'); +is(1->gigabytes, 1073741824, '... got 1 gigabyte'); +is(2->terabytes, 2199023255552, '... got 2 terabyte'); +</code></pre> + +</div> + +<div class="slide"> +<h1>perl -Moose</h1> + +<ul> +<li>Moose ãªã¯ã³ã©ã¤ãã¼ã«ã¯ <code>oose.pm</code> ãããã§ã</li> +<li>Moose One Liners with <code>oose.pm</code></li> +</ul> + +<pre><code> +perl -Moose -e'has foo => (is=>q[rw]); Class->new(foo=>1)' +</code></pre> + +<ul> +<li>ãªãããããããã¨ããªã©ã«</li> +<li>Useful for testing if something works</li> +<li>IRC ã§ã®ä¼è©±ã«ã¯æ¬ ããã¾ãããª!</li> +<li>Nice for IRC</li> +</ul> + +</div> + +<div class="slide"> +<h1>MooseX::POE</h1> + +<pre><code> +package Counter; +use MooseX::POE; + +has count => ( + isa => 'Int', + is => 'rw', +); + +sub START { + my ($self) = @_; + $self->yield('increment'); +} + +event increment => sub { + my ($self) = @_; + warn "Count is now " . $self->count; + $self->count( $self->count + 1 ); + $self->yield('increment') unless $self->count > 3; +}; + +Counter->new( count => 0 ); +POE::Kernel->run(); +</code></pre> + +<ul> +<li>POE ã®ã³ã³ãã¼ãã³ããç°¡åã«ããã¾ã</li> +<li>POE components made easy</li> +<li>ããããã®ãªãã¸ã§ã¯ãã POE::Session ããã£ã¦ã¾ã</li> +<li>Every object has a POE::Session</li> +<li><code>event</code> ããªãã¸ã§ã¯ãã®ã¹ãã¼ãã宣è¨ãã¾ã</li> +<li><code>event</code> declares object states</li> +</ul> + +</div> + +<div class="slide"> +<h1>Fin</h1> + +<ul> +<li><p>Slides written by:</p> + +<ul> +<li>Chris Prather</li> +<li>Stevan Little</li> +<li>Robert Boone</li> +</ul></li> +<li><p>Slides deleted by:</p> + +<ul> +<li>Yuval Kogman</li> +</ul></li> +<li><p>Slides translated by:</p> + +<ul> +<li>tokuhirom</li> +</ul></li> +</ul> + +</div> + + +</div> + +</body> +</html> diff --git a/Moose_YAPC_Asia_2008_ja/practical_moose.s5 b/Moose_YAPC_Asia_2008_ja/practical_moose.s5 new file mode 100644 index 0000000..2d60d32 --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/practical_moose.s5 @@ -0,0 +1,1233 @@ +Title: Moose +Location: YAPC::Asia::2008 +Presenter: Yuval Kogman +Date: 2008 +Theme: moose + +Moose ã¯ãªã«ã§ã¯ãªãã +====================== +Moose Is Not +------------ + +* å®é¨ããããã¿ã¤ã (experimental) +* ããã¡ã (toy) +* ããä¸ã¤ã®ã¢ã¯ã»ãµãã«ãã¼ (accessor builder) +* ã½ã¼ã¹ãã£ã«ã¿ (source filter) +* é»éè¡ (black magic) +* Perl 6 in Perl 5 + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã¨ã¯ãªã«ã +=============== +Moose Is +-------- + +* Perlã®ããã®å®å ¨ã«ã¢ãã³ãªãªãã¸ã§ã¯ããã¬ã¼ã ã¯ã¼ã¯ + +* A complete modern object framework for Perl + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã¨ã¯ãªã«ã +=============== +Moose Is +-------- + +* Class::MOPã®ããã®ã·ã³ã¿ãã¯ã¹ã·ã¥ã¬ã¼ (Syntactic sugar) +* ç¥å ãã¡ (ancestry) + * CLOS (Common Lisp Object System) + * Smalltalk + * Alces latifrons + * Perl 6 + * ⦠+* å®å®ãã¦ãã¦ããä»äºã«ãã¤ããã¾ã (Stable & Production ready) + + +â------â------â------â------â------â------â------â------â------â------ + +ã·ã³ãã«ãªä¾ +============ +A Simple Example +---------------- + +<pre><code> +package Person; + +use strict; +use warnings; + +sub new { + my ($class) = @_; + + return bless { + name => '', + age => undef, + }, $class; +} + +sub name { + my ($self, $name) = @_; + $self->{'name'} = $name if $name; + return $self->{'name'}; +} + +sub age { + my ($self, $age) = @_; + $self->{'age'} = $age if $age; + return $self->{'age'}; +} + +1; +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +ã·ã³ãã«ãªMooseã®ä¾ +=================== +A Simple Moose Example +---------------------- + +<pre><code> +package Person; +use Moose; + +has name => (is => 'rw'); +has age => (is => 'rw'); + +1; +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +ã·ã³ãã«ãªMooseã®ä¾(ã¤ã¥ã) +=========================== +A Simple Moose Example (cont.) +------------------------------ + +* `use Moose;` + * ãã¼ã¯ã¼ããã¤ã³ãã¼ã (imports keywords) + * `use strict; use warnings;` + * `@ISA = qw(Moose::Object) unless @ISA` + +â------â------â------â------â------â------â------â------â------â------ + +ã·ã³ãã«ãªMooseã®ä¾(ã¤ã¥ã) +=========================== +A Simple Moose Example (cont.) +------------------------------ + +* `has` ã¯ã¢ããªãã¥ã¼ããå®ç¾©ãã (declares attibutes) + * ã¢ã¯ã»ãµãçæ (generates accessors) + * `is => 'rw'` â èªã¿æ¸ã両ç¨ã¢ã¯ã»ãµ + * `is => 'ro'` â èªã¿è¾¼ã¿å°ç¨ã¢ã¯ã»ãµ + * `writer`, `reader` + +* `new` 㯠`Moose::Object` ããç¶æ¿ãã + + +########## + +ä»åº¦ã¯ã¢ããªãã¥ã¼ãã®æ©è½ã説æãã¦ããã +Now we're going to discuss more features of the attributes + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®ä¾ã®ããªã¨ã¼ã·ã§ã³ +========================= +Variations on a Moose Example +----------------------------- + +<pre><code> +package Person; +use Moose; + +has name => ( + is => 'rw', + isa => 'Str' + default => 'Bob' +); + +has staff => ( + is => 'ro', + isa => 'ArrayRef', + lazy => 1, + default => sub { [qw(Bob Alice Tim)] }, +); +</code></pre> + +########## + +default 㨠isa ã追å ããã¦ã¾ã +Adds default, isa + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®ä¾ã®ããªã¨ã¼ã·ã§ã³(ã¤ã¥ã) +================================= +Variations on a Moose Example (cont.) +------------------------------------- + +* `default` 㯠+ * ã³ã¼ããªãã¡ã¬ã³ã¹ (coderef) + * ã¾ãã¯ãªãã¡ã¬ã³ã¹ä»¥å¤ (æ°å¤, æåå) (nonref) + * `new` ã«ãã©ã¡ã¼ã¿ããããããªãã£ãã¨ãã«ä½¿ããã + +* `lazy` 㯠`default` ãé å»¶ããã + * æåã« `$object->staff` ã使ãããã¨ãã«å¼ã°ãã (generates) + * `new` ã®ä¸ã§ã¯ãªã (no param) + +########## +ããã©ã«ãã®è©± +discusses default + +ãªãã¡ã¬ã³ã¹ã§ãªãã¨æ³å®å¤ã®å ±æãããããããªã +non refs make accidental sharing hard + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®ä¾ã®ããªã¨ã¼ã·ã§ã³(ã¤ã¥ã) +================================= +Variations on a Moose Example (cont.) +------------------------------------- + +* `isa` ã¯åãè¦å®ãã (specifies type) + * `Moose::Util::TypeConstraints` + * `Any, Item, Bool, Undef, Defined, Value, Num, Int, Str, Ref, ScalarRef, ArrayRef, HashRef, CodeRef, RegexpRef, GlobRef, FileHandle, Object, and Role` + * åã¯åå¨ããå¿ è¦ã¯ããã¾ãã (don't need to exist) +<pre><code> + has 'date' => (isa => 'DateTime'); # DWIM +</code></pre> +########## + +isa, åã®å¶ç´ +isa, type constraints + +â------â------â------â------â------â------â------â------â------â------ + +å +== +Typical Family +-------------- + +* åã¯é層æ§é ããã£ã¦ãã (types have a hierarchy) + * `Item` â `Defined` â `Ref` â `Object` + +<pre><code> + subtype 'Ref' + => as 'Defined' + => where { ref($_) }; + + subtype 'Object' + => as 'Ref' + => where { blessed($_) } +</code></pre> +########## + +åã®é層æ§é +type hierarchy + +â------â------â------â------â------â------â------â------â------â------ + +åã®å¼·å¶å¤æ +============ +Some Type of Coercion +--------------------- + +<pre><code> +package Employee; +use Moose; +use Moose::Util::TypeConstraints; +extends qw(Person); + +class_type 'Manager'; + +coerce 'Manager' + => from 'Str' + => via { Manager->new( name => $_) }; + +has manager => ( + is => 'ro', + isa => 'Manager', + required => 1, + coerce => 1, +); +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +åã®å¼·å¶å¤æ(ã¤ã¥ã) +==================== +Some Type of Coercion (cont.) +----------------------------- + +<pre><code> +# åå¶ç´ã®ãã¼ã¯ã¼ããã¤ã³ãã¼ã(import type constraint keywords) +use Moose::Util::TypeConstraints; + + +# ãªãã¸ã§ã¯ãã®ãµãã¿ã¤ãã§ããããã¼ã¸ã£ã¼ãå®ç¾©(define Manager, a subtype of Object) +class_type "Manager"; + + +# 夿ãå®ç¾©ãã(define the conversion) +coerce 'Manager' + => from 'Str' + => via { Manager->new( name => $_) }; + + +# ã¢ããªãã¥ã¼ããã¨ã«æå¹ã«ãã(enable it per attribute) +has manager => ( + ⦠+ coerce => 1, +); +</code></pre> + +########## + +ä¾ãç´°ããè¦ã¦ããã +breakdown of the example + +ã¯ã©ã¹ã®åã¯Mooseã®ã¯ã©ã¹ãã¹ã¦ã«èªåçã«ç¨æããã¾ã +class types are automatically created for all Moose classes + +â------â------â------â------â------â------â------â------â------â------ + +ä¼çµ±çãªå§è² +============ +Conventional Delegates +---------------------- + +<pre><code> +package Employee; +use Moose; +extends qw(Person); + +has manager => ( + is => 'ro', + isa => 'Manager', + handles => { + manager_name => 'name', + coworkers => 'staff', + } +); +</code></pre> + +* ããã¼ã¸ã£ã¼ã¯ `Employee` ã®ããã¤ãã®ã¡ã½ãããå¦çãã¾ã +* manager `handles` certain methods for `Employee` + * `$emp->coworkers` == `$emp->manager->staff ` + +â------â------â------â------â------â------â------â------â------â------ + +ä¼çµ±çãªå§è²(ã¤ã¥ã) +==================== +Conventional Delegates (cont.) +------------------------------ + +<pre><code> +has phone => ( + ... + handles => [qw(number extension)], +); +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +ä¼çµ±çãªå§è²(ã¤ã¥ã) +==================== +Conventional Delegates (cont.) +------------------------------ + +<pre><code> +has phone => ( + isa => "Phone" + handles => qr/$method_regex/, +); +</code></pre> + +* `Phone->meta->compute_all_applicable_methods`ã«ãã£ã«ã¿ã¼ãããã +* Filters `Phone->meta->compute_all_applicable_methods` + +â------â------â------â------â------â------â------â------â------â------ + +ä¼çµ±çãªå§è²(ã¤ã¥ã) +==================== +Conventional Delegates (cont.) +------------------------------ + +<pre><code> +has phone => ( + ... + handles => "Dialing", # a role +); +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +ä¼çµ±çãããªãå§è² +================ +UnConventional Delegates +------------------------ + +<pre><code> +package Company; +use Moose; +use MooseX::AttributeHelpers; + +has employees => ( + metaclass => 'Collection::Array', + isa => 'ArrayRef[Employees]', + is => 'rw', + provides => { + push => 'add_employee', + pop => 'remove_employee', + count => 'number_of_employees', + empty => 'any_employees', + } +); +</code></pre> +â------â------â------â------â------â------â------â------â------â------ + +ã¡ã½ãã夿´ã®ã»ã«ã¤ +==================== +Modified Methods +---------------- + +<pre><code> +before 'employees' => sub { warn 'calling employees' }; + +after 'employees' => sub { warn 'finished calling employees' }; +</code></pre> + +* ç¾å¨ã®ã¡ã½ãããå®è¡ãããåï¼ãããå¾ã«å®è¡ããã¾ã +* Pre/Post hooks + * `@_`ã®ã³ãã¼ãå¾ã¾ã(Get a copy of `@_`) + * è¿ãå¤ã¯ç¡è¦ããã¾ã(Return value is ignored) + +â------â------â------â------â------â------â------â------â------â------ + +ã¡ã½ãã夿´ã®ã»ã«ã¤(ã¤ã¥ã) +============================ +Modified Methods (cont.) +------------------------ + +<pre><code> +around 'employees' => sub { + my ($next, $self, @args) = @_; + ... + my @return = $self->$next(@args); + ... + return @return; +}; +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +ã¡ã½ãã夿´ã®ã»ã«ã¤(ã¤ã¥ã) +============================ +Modified Methods (cont.) +------------------------ + +<pre><code> +package Employee; +use Moose; + +sub do_work { + my $self = shift; + + $self->punch_in; + + inner(); # call subclass here + + $self->punch_out; +} +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +ã¡ã½ãã夿´ã®ã»ã«ã¤(ã¤ã¥ã) +============================ +Modified Methods (cont.) +------------------------ + +<pre><code> +package Employee::Chef; +use Moose; + +extends qw(Employee); + +augment do_work => sub { + my $self = shift; + + while ( @burgers ) { + $self->flip_burger(shift @burgers); + } +} + +$chef->do_work; # punch in, flip burgers, punch out +</code></pre> +â------â------â------â------â------â------â------â------â------â------ + +åã«ã¤ãã¦ã®ä½è« +================ +Some Type of Digression +----------------------- + +<pre><code> +has employees => ( + is => 'rw', + isa => 'ArrayRef[Employee]', +); + +has shopping_carts => ( + is => 'rw', + isa => 'ArrayRef[ArrayRef[ShinyBead]]' +); +</code></pre> + +########## + +åã·ã¹ãã ã®æ©è½ã«ã¤ãã¦ã¡ãã£ã¨èª¬æãã¦ããã +Going to go into features of the type system for a bit + +ãã©ã¡ã¼ã¿ä»ãã®å +Parametrized types + +â------â------â------â------â------â------â------â------â------â------ + +åã«ã¤ãã¦ã®ä½è«(ã¤ã¥ã) +======================== +Some Type of Digression (cont.) +------------------------------- + +<pre><code> +has language => ( + is => 'rw', + isa => 'English | Welsh | Scots | Gaelic', +); + +has member => ( + is => 'rw', + isa => 'Employee | ArrayRef[Employee|Group]', +); +</code></pre> + +########## + +åã®çµå +Union types + +â------â------â------â------â------â------â------â------â------â------ + +åã«ã¤ãã¦ã®ä½è«(ã¤ã¥ã) +======================== +Some Type of Digression (cont.) +------------------------------- + +<pre><code> +package Foo; +use Moose; +use Moose::Util::TypeConstraints; +use Test::Deep qw(eq_deeply ...); + +type 'SomethingTricky' + => where { + eq_deeply( $_, ... ); + }; + +has 'bar' => ( + is => 'rw', + isa => 'SomethingTricky', +); +</code></pre> + +########## + +Test::Deppã®ã«ã¹ã¿ã ããªãã¼ã¿ +Test::Deep custom validator + +CPANããã©ããªããªãã¼ã¿ã§ãæã£ã¦ãããã +Can use any validation from the CPAN + +â------â------â------â------â------â------â------â------â------â------ + +ãã©ã¡ã¼ã¿ä»ãã®åã®å¼·å¶å¤æ +============================ +Some Parametrized Type of Coercion +---------------------------------- + +<pre><code> +use Moose::Util::TypeConstraints; +subtype 'ArrayRef[Employee]' => as 'ArrayRef'; + +coerce 'ArrayRef[Employee]' + => from 'ArrayRef[Str]' + => via { [ map { Employee->new( name => $_ ) } @$_ ] }; + +has staff => ( + is => 'ro', + isa => 'ArrayRef[Employee]', + lazy => 1, + default => sub { [qw(Bob Alice Tim)] }, + coerce => 1, +); +</code></pre> + +########## + +ArrayRef[Str] ãã ArrayRef[Employee] ã«å¼·å¶å¤æ +coerce parametrized ArrayRef[Employee] from ArrayRef[Str] + +å¼·å¶å¤æã¯ 'default' ã®è¿ãå¤ã«ãé©ç¨ããã¾ã +coercions can be applied to 'default' return values + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®Role +=========== +Role of the Moose +----------------- + +* Role ã¯â¦(A role is like a) + * Javaã®Interfaceã¿ãã + * mixinã¿ãã + * â¦ããã§ãã¦å®å ¨ã§ãã¯ãã«(safe, powerful) +* Role ã¯å°ããã¦åå©ç¨å¯è½ãªåä½åã(A role is for small reusable behaviors) + * å¤éç¶æ¿ãããã(better than using a multiple inheritence) + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®Role(ã¤ã¥ã) +=================== +Role of the Moose (cont.) +------------------------- + +* CPAN ã«ãã Role ãã¡(Roles on the CPAN): + * `MooseX::Storage` - æè»ãªã·ãªã¢ã©ã¤ãº(Flexible serialization) + * `MooseX::LogDispatch` - `$self->logger->info("something happenned")` + * `MooseX::Getopt` - ã³ãã³ãã©ã¤ã³å¼æ°ã®å¦ç(`@ARGV` aware constructor) + * `MooseX::Param` - `CGI.pm` ã® `param()` ã¡ã½ããã¿ãããªã®(`param` method like `CGI.pm`'s) + * `MooseX::Clone` - æè»ãª`clone`ã¡ã½ãã(Flexible `clone` method) + +########## + +åå©ç¨å¯è½ãªå°ããªåä½ã®ä¾ +Some examples of small reusable behaviors + +Paramã¯é£æºã«ä¾¿å© +Param is good for interacting with e.g. CGI::Expand or similar modules + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®Role(ã¤ã¥ã) +=================== +Role of the Moose (cont.) +------------------------- + +<pre><code> +package Minion; +use Moose; + +extends qw(Employee); + +with qw(Salaried::Hourly); + +package Boss; +use Moose; + +extends qw(Employee); + +with qw(Salaried::Monthly); + +</code></pre> + +* `with` ã¯ã¯ã©ã¹ã« Role ã追å ãã¾ã +* `with` adds roles into your class + * `Salaried::Hourly`ã`Minion`ã«è¿½å ããã + * `Salaried::Hourly` was added to `Minion` + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®Role(ã¤ã¥ã) +=================== +Role of the Moose (cont.) +------------------------- + +<pre><code> +package Salaried; +use Moose::Role; + +requires qw('paycheck_amount'); +</code></pre> + +* åãªãã¤ã³ã¿ã¼ãã§ã¼ã¹ +* Just an interface + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®Role(ã¤ã¥ã) +=================== +Role of the Moose (cont.) +------------------------- + +<pre><code> +package Salaried::Hourly; +use Moose::Role; + +with qw(Salaried); + +has hourly_rate => ( + isa => "Num", + is => "rw", + required => 1, +); + +has logged_hours => ( + isa => "Num", + is => "rw", + default => 0, +); + +sub paycheck_amount { + my $self = shift; + + $self->logged_hours * $self->hourly_rate; +} + +</code></pre> + +* ã¤ã³ã¿ã¼ãã§ã¼ã¹ããã¤ã¤ã! +* More than an interface + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®Role(ã¤ã¥ã) +=================== +Role of the Moose (cont.) +------------------------- + +* Javaã®ã¤ã³ã¿ã¼ãã§ã¼ã¹ããã¤ã¤ã! +* More than Java Interfaces + * ã¤ã³ã¿ã¼ãã§ã¼ã¹ã¯æåã®'è¦å®'ãæä¾ãã + * Interfaces are behavior "contracts" + * Role ã¯æåã®'å®è£ 'ãæä¾ã§ãã + * Roles can also have code + +########## +Roleã¯ã¢ããªãã¥ã¼ãã¨ã¡ã½ãããæã¦ã +roles can have attributes and methods +Roleã¯ã¤ã³ã¿ã¼ãã§ã¼ã¹ã ãã§ãªãåä½ãæä¾ãããã® +roles provide behavior, not just interface + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®Role(ã¤ã¥ã) +=================== +Role of the Moose (cont.) +------------------------- + +* Roleã®çµã¿è¾¼ã¿(Role Composition) + * ç¶æ¿ã§ã¯ãªã(Not inheritence) + * å§å©ä¸¡ææ(Symmetric) + * é åºã¯é¢ä¿ãªã(Unordered) + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®Role(ã¤ã¥ã) +=================== +Role of the Moose (cont.) +------------------------- + +* Roleã®çµã¿è¾¼ã¿(Role Composition) + * ããã¾ãããå°ãªã(Less ambiguity) + * ã³ã³ãã¤ã«æã¨ã©ã¼(Compile time errors) + * â¦ä¿®æ£ããæ¹æ³ããã(And ways to fix them) + +########## +å§å©ä¸¡ææã¨ããã®ã¯åªå é ä½ããªãã¨ãããã¨ããµãã¤ã®Roleãåããã®ãå®ç¾©ãããã¨ããå ´åã¯ã³ã³ãã¤ã«æã«ã¨ã©ã¼ã«ãªãï¼ç´ããªãã¨ãããªãï¼ +symmetric composition means no precedence - if two roles try to define the same thing you get a compile time error that needs to be resolved +å¤éç¶æ¿ã®å ´åã¯ã ã¾ã£ã¦æåã®ã¯ã©ã¹ã使ãããã ã¨æ³å®ãã¦ãã¾ã +multiple inheritence silently assumes you want the first class + +Roleã¯å¤éç¶æ¿ã¨éã£ã¦ã³ã³ãã¤ã«æã«ã¨ã©ã¼ãåã +roles cause errors at compile time, unlike multiple inheritence + +Roleã¯ç°¡åã«ã¨ã©ã¼ãä¿®æ£ããæ¹æ³ãç¨æãã¦ãã +roles also provide easy ways to fix the errors + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®Role(ã¤ã¥ã) +=================== +Role of the Moose (cont.) +------------------------- + +<pre><code> +package First; +use Moose::Role; + +sub dancing { ... } + +package Second; +use Moose::Role + +sub dancing { ... } + +package Foo; +use Moose; + +# KABOOM +with qw( + First + Second +); +</code></pre> + +########## + +è¡çª +conflicts + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®Role(ã¤ã¥ã) +=================== +Role of the Moose (cont.) +------------------------- + +<pre><code> +package Ent::Puppy; +use Moose; + +with ( + Tree => { + alias => { + bark => "tree_bark", + }, + }, + Dog => { + alias => { + bark => "bark_sound", + } + }, +); + +sub bark { + my $self = shift; + + if ( $condition ) { + $self->tree_bark; + } else { + $self->bark_sound; + } +} +</code></pre> + +########## + +çµã¿è¾¼ãã¨ãã«ãã©ã¡ã¼ã¿ãã¤ãã +Composition parameters +è¡çªã解決ããã®ãç°¡åã ã +Easier conflict resolution +ããããç´°ããã³ã³ããã¼ã«ãã§ããããã«ãªã +Finer grained control + +â------â------â------â------â------â------â------â------â------â------ + +MOPã¯ãã¬ã¤ +=========== +MOPs Mean Cleanliness +--------------------- + +* Moose 㯠Class::MOP ã§ã¤ãããã¦ã +* Moose is based on `Class::MOP` + * Perl5ã®ããã®ã¡ã¿ãªãã¸ã§ã¯ããããã³ã«(Metaobject Protocol for Perl 5) + * ãã¹ã¦ã«ãªãã¸ã§ã¯ããã¤ãããã("makes an object for everything") + +<pre><code> +my $class = $obj->meta; # $objã®ã¡ã¿ã¯ã©ã¹($obj's metaclass) +my $meta = MyApp->meta; # MyAppã®ã¡ã¿ã¯ã©ã¹(MyApp's metaclass) +my $emo = $obj->meta->meta # ã¡ã¿ã¡ã¿(even more meta)! + +warn $obj->meta->name; +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +å å´ããã¿ã¦ã¿ã +================ +Looking in From the Inside +-------------------------- + +<pre><code> +my $metaclass = $self->meta; + +$metaclass->superclasses; + +$metaclass->linearized_isa; # ãã¹ã¦ã®å ç¥ã¯ã©ã¹ãå¾ã¾ã(returns all ancestors) + +$metaclass->has_method("foo"); + +$metaclass->compute_all_applicable_methods; # ãã¹ã¦ã®ã¡ã½ãã(ç¶æ¿ããããã®ããµããã¦)(returns all methods (inherited too)) + +$metaclass->has_attribute("bar"); + +# ⦠lots more +</code></pre> +########## + +simple introspection + +â------â------â------â------â------â------â------â------â------â------ + +å å´ããã¿ã¦ã¿ã(ã¤ã¥ã) +======================== +Looking in From the Inside (cont.) +---------------------------------- + +<pre><code> +Moose::Meta::Class->create( Bar => + version => '0.01', + superclasses => [ 'Foo' ], + attributes => [ + Moose::Meta::Attribute->new( bar => ... ), + Moose::Meta::Attribute->new( baz => ... ), + ], + methods => { + calculate_bar => sub { ... }, + construct_baz => sub { ... } + } +); +</code></pre> + +########## + +ã¯ã©ã¹ã¯ããã°ã©ã çã«ã¤ãããã¨ãã§ãã +Classes can be created programmatically + +ç¡åã¯ã©ã¹ãå¯ +Anonymous classes also possible +â------â------â------â------â------â------â------â------â------â------ + +å å´ããã¿ã¦ã¿ã(ã¤ã¥ã) +======================== +Looking in From the Inside (cont.) +---------------------------------- + +<pre><code> +has foo => ( is => "rw" ); + +__PACKAGE__->meta->add_attribute( foo => is => "rw" ); +</code></pre> + +* Mooseã¯åãªãã·ã¥ã¬ã¼(Moose is just sugar) + * 大å¤ãªé¨åã¯MOPããã¦ããã(The MOP does the hard work) + +â------â------â------â------â------â------â------â------â------â------ + +ã¡ã¿ã¯ã©ã¹ã®ã¿ã³ã´ +================== +The Metaclass Tango +------------------- + +* ã¡ã¿ã¯ã©ã¹ã¯ã¯ã©ã¹ã®æåãã³ã³ããã¼ã«ãã +* Metaclassses control class behavior + +<pre><code> +has employees => ( + metaclass => 'Collection::Array', + ... +); +</code></pre> + +* ã«ã¹ã¿ã ã¢ããªãã¥ã¼ãã¡ã¿ã¯ã©ã¹ã¯ +* custom attribute metaclasses + * ã¢ããªãã¥ã¼ããã©ããã風ã«åãããå¤ãã + * change how attributes work +* ã«ã¹ã¿ãã¤ãºå¯è½ãªãã¼ããã¡ +* Many customizable parts + * `Moose::Meta::Class`, `Moose::Meta::Attribute, ``Moose::Meta::Method`, `Moose::Meta::Method::Accessor` `Moose::Meta::Instance`, `Moose::Meta::Role`, `Moose::Meta::TypeConstraint`, â¦, + +â------â------â------â------â------â------â------â------â------â------ + +ã¡ã¿ãã¬ã¼ã ã使ã +================== +Working in the Meta Frame +------------------------- + +* ä»äºã§ãã£ããããã話(An interesting `$work` story) +* flashã使ã£ããµã¤ãç¨ã®CMS(CMS for a flash website) +* ã³ã³ãã³ãã¯XML(Content is in XML) + +â------â------â------â------â------â------â------â------â------â------ + +ã¡ã¿ãã¬ã¼ã ã使ã(ã¤ã¥ã) +========================== +Working in the Meta Frame (cont.) +--------------------------------- + +* Step 1. use Moose +* Step 2. ??? +* Step 3. é(Profit)! + +â------â------â------â------â------â------â------â------â------â------ + +ã¡ã¿ãã¬ã¼ã ã使ã(ã¤ã¥ã) +========================== +Working in the Meta Frame (cont.) +--------------------------------- + +* Step 2.1. XMLã¹ãã¼ã(schemas) â ã¯ã©ã¹(classes) + * èªå夿(Automatic conversion) + * MOPã®ãããã§æ¥½å(MOP makes it easy) + * å®è¡æã«ã¯é«ã¬ãã«ãªãã¸ã§ã¯ã(High level objects in runtime) + * è£ã§ã¯XML(XML backed) + * ã¯ã©ã¤ã¢ã³ãã®ã¹ãã¼ã(With client's schemas) + * SAX â Moose + * Moose â SAX + +â------â------â------â------â------â------â------â------â------â------ + +ã¡ã¿ãã¬ã¼ã ã使ã(ã¤ã¥ã) +========================== +Working in the Meta Frame (cont.) +--------------------------------- + +* Step 2.2. ã¡ã¿è¨è¿°(Meta descriptions) + * ã¡ã¿ã¯ã©ã¹ãæ¡å¼µ(Extend the metaclasses) + * 追å ã®æ å ±ãåãè¾¼ã(Embed additional information) + * ãã£ã¼ã«ãå(field types) + * ã¢ã¯ã»ã¹ã³ã³ããã¼ã«(access control) + +â------â------â------â------â------â------â------â------â------â------ + +ã¡ã¿ãã¬ã¼ã ã使ã(ã¤ã¥ã) +========================== +Working in the Meta Frame (cont.) +--------------------------------- + +* Step 2.3 ã¤ã³ããã¹ãã¯ã·ã§ã³ãããã(Introspection goodness) + * æ±ç¨Webããã³ãã¨ã³ã(Generic web frontend) + * ãªãã¸ã§ã¯ãã¤ã³ããã¹ãã¯ã·ã§ã³ãã¼ã¹(Object introspection based) + * HTMLãã¥ã¼(view) + * ç·¨éç¨ã®ã¦ã£ã¸ã§ãã(Editing widgets) + * ã¯ãªã¼ã³ã§æ¡å¼µæ§ãé«ã(Clean, extensible) + +â------â------â------â------â------â------â------â------â------â------ + +Moose ã®æ¬ ç¹ +============ +Drawbacks of Moose +------------------ + +* ãã¼ãæé(Load time) + * `MooseX::Compile` ãã¢ã«ã§ã(`MooseX::Compile` is in the works) +* ããã¤ãã®æ©è½ãé ã(Some features are slow) + * ã§ããããªããã¤ãã£ãã¶ãã ãã ãã(but you only pay for what you use) +* hashref ãããªãã¯ã©ã¹ã®æ¡å¼µã¯ããªããã¼(Extending non-Hash based classes is tricky). + * ã§ãå¯è½(but possible): `MooseX::GlobRef::Object` + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®ã¤ã¤!ã¨ã +================ +Benefits of Moose +----------------- + +* éå±ãªãã¨ãæ¸ããã(Less tedious) + * 決ã¾ãæå¥ãæ¸ããªãã¦ãã(ditch that boilerplate): + * ã¢ããªãã¥ã¼ãã®ã¹ãã¬ã¼ã¸/ã¢ã¯ã»ãµ(attribute storage/access) + * ã³ã³ã¹ãã©ã¯ã¿(construction) + * ãã¹ãã©ã¯ã¿(destruction) + * 弿°æ¤æ»(verification) + * ⦠+ * ç¹°ãè¿ããæ¸ããã(less repetition) + * typo ãæ¸ããã(fewer typos) + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®ã¤ã¤!ã¨ã(ã¤ã¥ã) +======================== +Benefits of Moose (cont.) +------------------------- + +* ã¿ããã(Shorter) + * declarative == æ å ±ãããããã¿ã¤ãæ°ããããªã(more info, less typing) + * no RSI ;-) + * ã³ã¼ãããããªãããã°ããããªããã(less code means fewer bugs) + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®ã¤ã¤!ã¨ã(ã¤ã¥ã) +======================== +Benefits of Moose (cont.) +------------------------- + +* ãã¹ãããããªãã¦ãã(Less testing) + * Moose ã¯ãããã¹ãããã¦ãã + * Moose is well tested + * ã¢ã¯ã»ãµããæåããããã§ãã¯ããã§ãããã + * no need to check accessor behavior, etc + * ããªãã®ã³ã¼ãã®ç®çã«ãã©ã¼ã«ã¹ã§ãã¾ã! + * focus on your code's purpose + * ãã¡ãã¨ãã¾ã¨ãã¦ããããªãã¦ãããã + * not that it is "assembled" correctly + * http://c2.com/cgi/wiki?IntentionNotAlgorithm + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®ã¤ã¤!ã¨ã(ã¤ã¥ã) +======================== +Benefits of Moose (cont.) +------------------------- + +* èªã¿ããã(More readable) + * 宣è¨çãªã¹ã¿ã¤ã«ã ãããã®ã¾ã¾ææ¸ã«ãªã£ã¦ãã + * declarative style is self documenting + * ãããããã¨ãæ¸ããé¢ä¿ãªãOOã®ãããã¨ãã¯ãã¾ãæ¸ããªãã¦ããã + * Code your intentions, not and OO mechanics less + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®ã¤ã¤!ã¨ã(ã¤ã¥ã) +======================== +Benefits of Moose (cont.) +------------------------- + +* Meta object protocol + * Perl ã® OO ã綺éºã«ãã¤ããã¾ã + * Cleans up all levels of Perl's OO + * ã¤ã³ããã¹ãã¯ã·ã§ã³ã§ãã¾ã + * Provides introspection + * ãã¯ãã«ãªæ½è±¡å + * Enables powerful abstractions + +â------â------â------â------â------â------â------â------â------â------ + +Mooseã®ã¤ã¤!ã¨ã(ã¤ã¥ã) +======================== +Benefits of Moose (cont.) +------------------------- + +* ä»å¹´ã®æµè¡ã ã +* It's the new black + * ã¤ã«ããé£ä¸ã¯ã¿ããª#mooseã«ãã¦ãã + * All the cool kids hang out on #moose + * ãã£ãããããªããºã¯ã¼ã + * Smart sounding buzzwords + * 2007å¹´ã«ã¯Rubyãããã ã£ãã + * Ruby is so 2007 + +â------â------â------â------â------â------â------â------â------â------ + +ãã¾ã +====== +Bonus Material +-------------- + +â------â------â------â------â------â------â------â------â------â------ + +Autobox +======= + +<pre><code> +package Units::Bytes; +use Moose::Role; +use Moose::Autobox; + +sub bytes { $_[0] } +sub kilobytes { $_[0] * 1024 } +sub megabytes { $_[0] * 1024->kilobytes } +sub gigabytes { $_[0] * 1024->megabytes } +sub terabytes { $_[0] * 1024->gigabytes } + +Moose::Autobox->mixin_additional_role(SCALAR => 'Units::Bytes'); +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +Autobox (ã¤ã¥ã) +================ +Autobox (cont.) +--------------- + +<pre><code> +use Units::Bytes; +use Moose::Autobox; + +is(5->bytes, 5, '... got 5 bytes'); +is(5->kilobytes, 5120, '... got 5 kilobytes'); +is(2->megabytes, 2097152, '... got 2 megabytes'); +is(1->gigabytes, 1073741824, '... got 1 gigabyte'); +is(2->terabytes, 2199023255552, '... got 2 terabyte'); +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +perl -Moose +=========== + +* Moose ãªã¯ã³ã©ã¤ãã¼ã«ã¯ `oose.pm` ãããã§ã +* Moose One Liners with `oose.pm` + +<pre><code> +perl -Moose -e'has foo => (is=>q[rw]); Class->new(foo=>1)' +</code></pre> + +* ãªãããããããã¨ããªã©ã« +* Useful for testing if something works +* IRC ã§ã®ä¼è©±ã«ã¯æ¬ ããã¾ãããª! +* Nice for IRC + +â------â------â------â------â------â------â------â------â------â------ + +MooseX::POE +=========== + +<pre><code> +package Counter; +use MooseX::POE; + +has count => ( + isa => 'Int', + is => 'rw', +); + +sub START { + my ($self) = @_; + $self->yield('increment'); +} + +event increment => sub { + my ($self) = @_; + warn "Count is now " . $self->count; + $self->count( $self->count + 1 ); + $self->yield('increment') unless $self->count > 3; +}; + +Counter->new( count => 0 ); +POE::Kernel->run(); +</code></pre> + +* POE ã®ã³ã³ãã¼ãã³ããç°¡åã«ããã¾ã +* POE components made easy +* ããããã®ãªãã¸ã§ã¯ãã POE::Session ããã£ã¦ã¾ã +* Every object has a POE::Session +* `event` ããªãã¸ã§ã¯ãã®ã¹ãã¼ãã宣è¨ãã¾ã +* `event` declares object states + +â------â------â------â------â------â------â------â------â------â------ + +Fin +=== + +* Slides written by: + * Chris Prather + * Stevan Little + * Robert Boone + +* Slides deleted by: + * Yuval Kogman + +* Slides translated by: + * tokuhirom diff --git a/Moose_YAPC_Asia_2008_ja/ui/default/blank.gif b/Moose_YAPC_Asia_2008_ja/ui/default/blank.gif new file mode 100644 index 0000000..75b945d Binary files /dev/null and b/Moose_YAPC_Asia_2008_ja/ui/default/blank.gif differ diff --git a/Moose_YAPC_Asia_2008_ja/ui/default/bodybg.gif b/Moose_YAPC_Asia_2008_ja/ui/default/bodybg.gif new file mode 100755 index 0000000..5f448a1 Binary files /dev/null and b/Moose_YAPC_Asia_2008_ja/ui/default/bodybg.gif differ diff --git a/Moose_YAPC_Asia_2008_ja/ui/default/framing.css b/Moose_YAPC_Asia_2008_ja/ui/default/framing.css new file mode 100644 index 0000000..2a27daf --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/default/framing.css @@ -0,0 +1,22 @@ +/* The following styles size, place, and layer the slide components. + Edit these if you want to change the overall slide layout. + The commented lines can be uncommented (and modified, if necessary) + to help you with the rearrangement process. */ + +/* target = 1024x768 */ + +div#header, div#footer, .slide {width: 100%; top: 0; left: 0;} +div#header {top: 0; height: 3em; z-index: 1;} +div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;} +.slide {top: 0; width: 92%; padding: 3.5em 4% 4%; z-index: 2; list-style: none;} +div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;} +div#controls form {text-align: right; width: 100%; margin: 0;} +#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; z-index: 10;} +html>body #currentSlide {position: fixed;} + +/* +div#header {background: #FCC;} +div#footer {background: #CCF;} +div#controls {background: #BBD;} +div#currentSlide {background: #FFC;} +*/ diff --git a/Moose_YAPC_Asia_2008_ja/ui/default/iepngfix.htc b/Moose_YAPC_Asia_2008_ja/ui/default/iepngfix.htc new file mode 100644 index 0000000..bba2db7 --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/default/iepngfix.htc @@ -0,0 +1,42 @@ +<public:component> +<public:attach event="onpropertychange" onevent="doFix()" /> + +<script> + +// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com +// Free usage permitted as long as this notice remains intact. + +// This must be a path to a blank image. That's all the configuration you need here. +var blankImg = 'ui/default/blank.gif'; + +var f = 'DXImageTransform.Microsoft.AlphaImageLoader'; + +function filt(s, m) { + if (filters[f]) { + filters[f].enabled = s ? true : false; + if (s) with (filters[f]) { src = s; sizingMethod = m } + } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")'; +} + +function doFix() { + if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) || + (event && !/(background|src)/.test(event.propertyName))) return; + + if (tagName == 'IMG') { + if ((/\.png$/i).test(src)) { + filt(src, 'image'); // was 'scale' + src = blankImg; + } else if (src.indexOf(blankImg) < 0) filt(); + } else if (style.backgroundImage) { + if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) { + var s = RegExp.$1; + style.backgroundImage = ''; + filt(s, 'crop'); + } else filt(); + } +} + +doFix(); + +</script> +</public:component> \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008_ja/ui/default/notes.css b/Moose_YAPC_Asia_2008_ja/ui/default/notes.css new file mode 100644 index 0000000..5858cf2 --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/default/notes.css @@ -0,0 +1,122 @@ +/* Following are the note styles -- edit away! */ + +body { + margin: 0; + padding: 1.0em; + background: #333; + color: #FFF; + font: 2em/1.4em 'Lucida Grande', Verdana, sans-serif; +} + +div.timers { + background: #FFF; + color: #333; + border: 0.08em solid #222; + border-top-width: 1px; + border-left-width: 1px; + float: left; + padding: 0.2em; + margin: 0 0 0.5em; + position: relative; +} + +div.timers h1 { + text-align: left; + font-size: 0.6em; + line-height: 1.4em; + background-color: #FF9; + padding: 0 0.75em; + margin: 0.25em 0 0; + border: 1px solid #EE8; +} + +div.timers div.controls { + position: absolute; + right: 0.25em; + top: 0.1em; + line-height: 1em; +} + +div.timers h1 a { + text-decoration: none; + color: #000; +} + +div.timers div.controls a { + font-size: 0.5em; + padding: 0; + color: #330; +} + +div.timers a.control { + position: absolute; + text-decoration: none; + padding: 0 0.25em; + color: #AAA; + outline: 0; +} + +#minus { + left: 0.25em; +} + +#plus { + right: 0.25em; +} + +.overtime { + background: yellow; + color: red; + border: 3px solid; + padding: 0.1em 0.25em; + font-weight: bold; +} + +div.timers h2 { + font-size: 0.6em; + line-height: 1.0em; + font-weight: normal; + margin: 0 0 -0.25em; + padding-top: 0.5em; + color: #666; +} + +div.timers p {margin: 0; padding: 0 0.5em;} +div.timers form {margin: 0;} + +div.timers span.clock { + font-family: monospace; +} + +div.timers ul {margin: 0; padding: 0; list-style: none;} +div.timers li {float: left; width: 5em; margin: 0; padding: 0 0.5em; + text-align: center;} + +div#elapsed {width: 12.1em;} +div#remaining {clear: left; width: 12.1em;} +div#remaining p {text-align: center;} + +#slide, +#next, +#notes, +#nextnotes { + font-size: 0.75em; + line-height: 1.4em; + clear: left; +/* max-width: 30.0em; */ + text-shadow: 0.1em 0.1em 0.1em #111; +} + +#next {margin-top: 2.5em;} +#next, #nextnotes { + color: #999; + font-size: 0.66em; +} + +em.disclaimer { + color: #666; +} + +div.collapsed h1 {display: block; font-size: 0.33em;} +div.collapsed h1 a {display: inline;} +div.collapsed * {display: none;} diff --git a/Moose_YAPC_Asia_2008_ja/ui/default/opera.css b/Moose_YAPC_Asia_2008_ja/ui/default/opera.css new file mode 100644 index 0000000..9e9d2a3 --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/default/opera.css @@ -0,0 +1,7 @@ +/* DO NOT CHANGE THESE unless you really want to break Opera Show */ +.slide { + visibility: visible !important; + position: static !important; + page-break-before: always; +} +#slide0 {page-break-before: avoid;} diff --git a/Moose_YAPC_Asia_2008_ja/ui/default/outline.css b/Moose_YAPC_Asia_2008_ja/ui/default/outline.css new file mode 100644 index 0000000..62db519 --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/default/outline.css @@ -0,0 +1,15 @@ +/* don't change this unless you want the layout stuff to show up in the outline view! */ + +.layout div, #footer *, #controlForm * {display: none;} +#footer, #controls, #controlForm, #navLinks, #toggle { + display: block; visibility: visible; margin: 0; padding: 0;} +#toggle {float: right; padding: 0.5em;} +html>body #toggle {position: fixed; top: 0; right: 0;} + +/* making the outline look pretty-ish */ + +#slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;} +#slide0 h1 {padding-top: 1.5em;} +.slide h1 {margin: 1.5em 0 0; padding-top: 0.25em; + border-top: 1px solid #888; border-bottom: 1px solid #AAA;} +#toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;} diff --git a/Moose_YAPC_Asia_2008_ja/ui/default/pretty.css b/Moose_YAPC_Asia_2008_ja/ui/default/pretty.css new file mode 100644 index 0000000..838a7cf --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/default/pretty.css @@ -0,0 +1,82 @@ +/* Following are the presentation styles -- edit away! */ + +body {background: #FFF url(bodybg.gif) -16px 0 no-repeat; color: #000; font-size: 2.25em;} +:link, :visited {text-decoration: none; color: #00C;} +#controls :active {color: #88A !important;} +#controls :focus {outline: 1px dotted #227;} +h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;} +ul, pre {margin: 0; line-height: 1em;} +html, body {margin: 0; padding: 0;} + +blockquote, q {font-style: italic;} +blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;} +blockquote p {margin: 0;} +blockquote i {font-style: normal;} +blockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;} +blockquote b i {font-style: italic;} + +kbd {font-weight: bold; font-size: 1em;} +sup {font-size: smaller; line-height: 1px;} + +.slide code {padding: 2px 0.25em; font-weight: bold; color: #533;} +.slide code.bad, code del {color: red;} +.slide code.old {color: silver;} +.slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: #533; font-size: 90%;} +.slide pre code {display: block;} +.slide ul {margin-left: 5%; margin-right: 7%; list-style: disc;} +.slide li {margin-top: 0.75em; margin-right: 0;} +.slide ul ul {line-height: 1;} +.slide ul ul li {margin: .2em; font-size: 85%; list-style: square;} +.slide img.leader {display: block; margin: 0 auto;} + +div#header, div#footer {background: #005; color: #AAB; + font-family: Verdana, Helvetica, sans-serif;} +div#header {background: #005 url(bodybg.gif) -16px 0 no-repeat; + line-height: 1px;} +div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;} +#footer h1, #footer h2 {display: block; padding: 0 1em;} +#footer h2 {font-style: italic;} + +div.long {font-size: 0.75em;} +.slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1; + margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap; + font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize; + color: #DDE; background: #005;} +.slide h3 {font-size: 130%;} +h1 abbr {font-variant: small-caps;} + +div#controls {position: absolute; left: 60%; bottom: 0; + width: 40%; + text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;} +html>body div#controls {position: fixed; padding: 0; top: auto;} +#controls #navLinks a {padding: 0; margin: 0 0.5em; + background: #005; border: none; color: #779; + cursor: pointer;} +#controls #navList #jumplist {background: #DDD; color: #227;} + +#currentSlide {text-align: center; font-size: 0.5em; color: #449;} + +#slide0 {padding-top: 3.5em; font-size: 90%;} +#slide0 h1 {position: static; margin: 1em 0 0; padding: 0; + font: bold 2em Helvetica, sans-serif; white-space: normal; + color: #000; background: transparent;} +#slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;} +#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;} +#slide0 h4 {margin-top: 0; font-size: 1em;} + +ul.urls {list-style: none; display: inline; margin: 0;} +.urls li {display: inline; margin: 0;} +.note {display: none;} +.external {border-bottom: 1px dotted gray;} +html>body .external {border-bottom: none;} +.external:after {content: " \274F"; font-size: smaller; color: #77B;} + +.incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;} +img.incremental {visibility: hidden;} +.slide .current {color: #B02;} + + +/* diagnostics + +li:after {content: " [" attr(class) "]"; color: #F88;} + */ \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008_ja/ui/default/print.css b/Moose_YAPC_Asia_2008_ja/ui/default/print.css new file mode 100644 index 0000000..e7a71d1 --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/default/print.css @@ -0,0 +1 @@ +/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */ .slide, ul {page-break-inside: avoid; visibility: visible !important;} h1 {page-break-after: avoid;} body {font-size: 12pt; background: white;} * {color: black;} #slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;} #slide0 h3 {margin: 0; padding: 0;} #slide0 h4 {margin: 0 0 0.5em; padding: 0;} #slide0 {margin-bottom: 3em;} h1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;} .extra {background: transparent !important;} div.extra, pre.extra, .example {font-size: 10pt; color: #333;} ul.extra a {font-weight: bold;} p.example {display: none;} #header {display: none;} #footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;} #footer h2, #controls {display: none;} /* The following rule keeps the layout stuff out of print. Remove at your own risk! */ .layout, .layout * {display: none !important;} \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008_ja/ui/default/s5-core.css b/Moose_YAPC_Asia_2008_ja/ui/default/s5-core.css new file mode 100644 index 0000000..ad1530b --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/default/s5-core.css @@ -0,0 +1,9 @@ +/* Do not edit or override these styles! The system will likely break if you do. */ + +div#header, div#footer, div#controls, .slide {position: absolute;} +html>body div#header, html>body div#footer, + html>body div#controls, html>body .slide {position: fixed;} +.handout, .notes {display: none;} +.layout {display: block;} +.slide, .hideme, .incremental {visibility: hidden;} +#slide0 {visibility: visible;} diff --git a/Moose_YAPC_Asia_2008_ja/ui/default/slides.css b/Moose_YAPC_Asia_2008_ja/ui/default/slides.css new file mode 100644 index 0000000..0786d7d --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/default/slides.css @@ -0,0 +1,3 @@ +@import url(s5-core.css); /* required to make the slide show run at all */ +@import url(framing.css); /* sets basic placement and size of slide components */ +@import url(pretty.css); /* stuff that makes the slides look better than blah */ \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008_ja/ui/default/slides.js b/Moose_YAPC_Asia_2008_ja/ui/default/slides.js new file mode 100644 index 0000000..ab2a4b2 --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/default/slides.js @@ -0,0 +1,764 @@ +// S5 v1.2a1 slides.js -- released into the Public Domain +// +// Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information +// about all the wonderful and talented contributors to this code! + +var undef; +var slideCSS = ''; +var snum = 0; +var smax = 1; +var incpos = 0; +var number = undef; +var s5mode = true; +var defaultView = 'slideshow'; +var controlVis = 'visible'; + +var s5NotesWindow; +var s5NotesWindowLoaded = false; +var previousSlide = 0; +var presentationStart = new Date(); +var slideStart = new Date(); + +var countdown = { + timer: 0, + state: 'pause', + start: new Date(), + end: 0, + remaining: 0 +}; + + +var isIE = navigator.appName == 'Microsoft Internet Explorer' && navigator.userAgent.indexOf('Opera') < 1 ? 1 : 0; +var isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0; +var isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0; + +function hasClass(object, className) { + if (!object.className) return false; + return (object.className.search('(^|\\s)' + className + '(\\s|$)') != -1); +} + +function hasValue(object, value) { + if (!object) return false; + return (object.search('(^|\\s)' + value + '(\\s|$)') != -1); +} + +function removeClass(object,className) { + if (!object || !hasClass(object,className)) return; + object.className = object.className.replace(new RegExp('(^|\\s)'+className+'(\\s|$)'), RegExp.$1+RegExp.$2); +} + +function addClass(object,className) { + if (!object || hasClass(object, className)) return; + if (object.className) { + object.className += ' '+className; + } else { + object.className = className; + } +} + +function GetElementsWithClassName(elementName,className) { + var allElements = document.getElementsByTagName(elementName); + var elemColl = new Array(); + for (var i = 0; i< allElements.length; i++) { + if (hasClass(allElements[i], className)) { + elemColl[elemColl.length] = allElements[i]; + } + } + return elemColl; +} + +function isParentOrSelf(element, id) { + if (element == null || element.nodeName=='BODY') return false; + else if (element.id == id) return true; + else return isParentOrSelf(element.parentNode, id); +} + +function nodeValue(node) { + var result = ""; + if (node.nodeType == 1) { + var children = node.childNodes; + for (var i = 0; i < children.length; ++i) { + result += nodeValue(children[i]); + } + } + else if (node.nodeType == 3) { + result = node.nodeValue; + } + return(result); +} + +function slideLabel() { + var slideColl = GetElementsWithClassName('*','slide'); + var list = document.getElementById('jumplist'); + smax = slideColl.length; + for (var n = 0; n < smax; n++) { + var obj = slideColl[n]; + + var did = 'slide' + n.toString(); + obj.setAttribute('id',did); + +// if (isOp) continue; // Opera fix (hallvord) + + var otext = ''; + var menu = obj.firstChild; + if (!menu) continue; // to cope with empty slides + while (menu && menu.nodeType == 3) { + menu = menu.nextSibling; + } + if (!menu) continue; // to cope with slides with only text nodes + + var menunodes = menu.childNodes; + for (var o = 0; o < menunodes.length; o++) { + otext += nodeValue(menunodes[o]); + } + list.options[list.length] = new Option(n + ' : ' + otext, n); + } +} + +function currentSlide() { + var cs; + if (document.getElementById) { + cs = document.getElementById('currentSlide'); + } else { + cs = document.currentSlide; + } + cs.innerHTML = '<a id="plink" href="">' + + '<span id="csHere">' + snum + '<\/span> ' + + '<span id="csSep">\/<\/span> ' + + '<span id="csTotal">' + (smax-1) + '<\/span>' + + '<\/a>' + ; + if (snum == 0) { + cs.style.visibility = 'hidden'; + } else { + cs.style.visibility = 'visible'; + } +} + +function go(step) { + if (document.getElementById('slideProj').disabled || step == 0) return; + var jl = document.getElementById('jumplist'); + var cid = 'slide' + snum; + var ce = document.getElementById(cid); + if (incrementals[snum].length > 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + removeClass(incrementals[snum][i], 'current'); + removeClass(incrementals[snum][i], 'incremental'); + } + } + if (step != 'j') { + snum += step; + lmax = smax - 1; + if (snum > lmax) snum = lmax; + if (snum < 0) snum = 0; + } else + snum = parseInt(jl.value); + var nid = 'slide' + snum; + var ne = document.getElementById(nid); + if (!ne) { + ne = document.getElementById('slide0'); + snum = 0; + } + if (step < 0) {incpos = incrementals[snum].length} else {incpos = 0;} + if (incrementals[snum].length > 0 && incpos == 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + if (hasClass(incrementals[snum][i], 'current')) + incpos = i + 1; + else + addClass(incrementals[snum][i], 'incremental'); + } + } + if (incrementals[snum].length > 0 && incpos > 0) + addClass(incrementals[snum][incpos - 1], 'current'); + if (isOp) { //hallvord + location.hash = nid; + } else { + ce.style.visibility = 'hidden'; + ne.style.visibility = 'visible'; + } // /hallvord + jl.selectedIndex = snum; + currentSlide(); + loadNote(); + permaLink(); + number = undef; +} + +function goTo(target) { + if (target >= smax || target == snum) return; + go(target - snum); +} + +function subgo(step) { + if (step > 0) { + removeClass(incrementals[snum][incpos - 1],'current'); + removeClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos],'current'); + incpos++; + } else { + incpos--; + removeClass(incrementals[snum][incpos],'current'); + addClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos - 1],'current'); + } + loadNote(); +} + +function toggle() { + var slideColl = GetElementsWithClassName('*','slide'); + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + if (!slides.disabled) { + slides.disabled = true; + outline.disabled = false; + s5mode = false; + fontSize('1em'); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'visible'; + } + } else { + slides.disabled = false; + outline.disabled = true; + s5mode = true; + fontScale(); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'hidden'; + } + slideColl[snum].style.visibility = 'visible'; + } +} + +function showHide(action) { + var obj = GetElementsWithClassName('*','hideme')[0]; + switch (action) { + case 's': obj.style.visibility = 'visible'; break; + case 'h': obj.style.visibility = 'hidden'; break; + case 'k': + if (obj.style.visibility != 'visible') { + obj.style.visibility = 'visible'; + } else { + obj.style.visibility = 'hidden'; + } + break; + } +} + +// 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/) +function keys(key) { + if (!key) { + key = event; + key.which = key.keyCode; + } + if (key.which == 84) { + toggle(); + return; + } + if (s5mode) { + switch (key.which) { + case 10: // return + case 13: // enter + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + if(number != undef) { + goTo(number); + break; + } + case 32: // spacebar + case 34: // page down + case 39: // rightkey + case 40: // downkey + if(number != undef) { + go(number); + } else if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + break; + case 33: // page up + case 37: // leftkey + case 38: // upkey + if(number != undef) { + go(-1 * number); + } else if (!incrementals[snum] || incpos <= 0) { + go(-1); + } else { + subgo(-1); + } + break; + case 36: // home + goTo(0); + break; + case 35: // end + goTo(smax-1); + break; + case 67: // c + showHide('k'); + break; + case 78: // n + createNotesWindow(); + break; + } + if (key.which < 48 || key.which > 57) { + number = undef; + } else { + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + number = (((number != undef) ? number : 0) * 10) + (key.which - 48); + } + } + return false; +} + +function clicker(e) { + number = undef; + var target; + if (window.event) { + target = window.event.srcElement; + e = window.event; + } else target = e.target; + if (target.href != null || hasValue(target.rel, 'external') || isParentOrSelf(target, 'controls') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object')) return true; + if (!e.which || e.which == 1) { + if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + } +} + +function findSlide(hash) { + var target = null; + var slides = GetElementsWithClassName('*','slide'); + for (var i = 0; i < slides.length; i++) { + var targetSlide = slides[i]; + if ( (targetSlide.name && targetSlide.name == hash) + || (targetSlide.id && targetSlide.id == hash) ) { + target = targetSlide; + break; + } + } + while(target != null && target.nodeName != 'BODY') { + if (hasClass(target, 'slide')) { + return parseInt(target.id.slice(5)); + } + target = target.parentNode; + } + return null; +} + +function slideJump() { + if (window.location.hash == null) return; + var sregex = /^#slide(\d+)$/; + var matches = sregex.exec(window.location.hash); + var dest = null; + if (matches != null) { + dest = parseInt(matches[1]); + } else { + dest = findSlide(window.location.hash.slice(1)); + } + if (dest != null) + go(dest - snum); +} + +function fixLinks() { + var thisUri = window.location.href; + thisUri = thisUri.slice(0, thisUri.length - window.location.hash.length); + var aelements = document.getElementsByTagName('A'); + for (var i = 0; i < aelements.length; i++) { + var a = aelements[i].href; + var slideID = a.match('\#slide[0-9]{1,2}'); + if ((slideID) && (slideID[0].slice(0,1) == '#')) { + var dest = findSlide(slideID[0].slice(1)); + if (dest != null) { + if (aelements[i].addEventListener) { + aelements[i].addEventListener("click", new Function("e", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "if (e.preventDefault) e.preventDefault();"), true); + } else if (aelements[i].attachEvent) { + aelements[i].attachEvent("onclick", new Function("", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "event.returnValue = false;")); + } + } + } + } +} + +function externalLinks() { + if (!document.getElementsByTagName) return; + var anchors = document.getElementsByTagName('a'); + for (var i=0; i<anchors.length; i++) { + var anchor = anchors[i]; + if (anchor.getAttribute('href') && hasValue(anchor.rel, 'external')) { + anchor.target = '_blank'; + addClass(anchor,'external'); + } + } +} + +function permaLink() { + document.getElementById('plink').href = window.location.pathname + '#slide' + snum; +} + +function createControls() { + var controlsDiv = document.getElementById("controls"); + if (!controlsDiv) return; + var hider = ' onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"'; + var hideDiv, hideList = ''; + if (controlVis == 'hidden') { + hideDiv = hider; + } else { + hideList = hider; + } + controlsDiv.innerHTML = '<form action="#" id="controlForm"' + hideDiv + '>' + + '<div id="navLinks">' + + '<a accesskey="n" id="show-notes" href="javascript:createNotesWindow();" title="Show Notes">≡<\/a>' + + '<a accesskey="t" id="toggle" href="javascript:toggle();">Ø<\/a>' + + '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' + + '<a accesskey="x" id="next" href="javascript:go(1);">»<\/a>' + + '<div id="navList"' + hideList + '><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>' + + '<\/div><\/form>'; + if (controlVis == 'hidden') { + var hidden = document.getElementById('navLinks'); + } else { + var hidden = document.getElementById('jumplist'); + } + addClass(hidden,'hideme'); +} + +function fontScale() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers + if (!s5mode) return false; + var vScale = 48; // both yield 16 (the usual browser default) at 1024x768 + var hScale = 64; // perhaps should auto-calculate based on theme's declared value? + if (window.innerHeight) { + var vSize = window.innerHeight; + var hSize = window.innerWidth; + } else if (document.documentElement.clientHeight) { + var vSize = document.documentElement.clientHeight; + var hSize = document.documentElement.clientWidth; + } else if (document.body.clientHeight) { + var vSize = document.body.clientHeight; + var hSize = document.body.clientWidth; + } else { + var vSize = 700; // assuming 1024x768, minus chrome and such + var hSize = 1024; // these do not account for kiosk mode or Opera Show + } + var newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale)); + fontSize(newSize + 'px'); + if (isGe) { // hack to counter incremental reflow bugs + var obj = document.getElementsByTagName('body')[0]; + obj.style.display = 'none'; + obj.style.display = 'block'; + } +} + +function fontSize(value) { + if (!(s5ss = document.getElementById('s5ss'))) { + if (!document.createStyleSheet) { + document.getElementsByTagName('head')[0].appendChild(s5ss = document.createElement('style')); + s5ss.setAttribute('media','screen, projection'); + s5ss.setAttribute('id','s5ss'); + } else { + document.createStyleSheet(); + document.s5ss = document.styleSheets[document.styleSheets.length - 1]; + } + } + if (!(document.s5ss && document.s5ss.addRule)) { + while (s5ss.lastChild) s5ss.removeChild(s5ss.lastChild); + s5ss.appendChild(document.createTextNode('html {font-size: ' + value + ' !important;}')); + } else { + document.s5ss.addRule('html','font-size: ' + value + ' !important;'); + } +} + +function notOperaFix() { + slideCSS = document.getElementById('slideProj').href; + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + slides.setAttribute('media','screen'); + outline.disabled = true; + if (isGe) { + slides.setAttribute('href','null'); // Gecko fix + slides.setAttribute('href',slideCSS); // Gecko fix + } + if (isIE && document.styleSheets && document.styleSheets[0]) { + document.styleSheets[0].addRule('img', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('div', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('.slide', 'behavior: url(ui/default/iepngfix.htc)'); + } +} + +function getIncrementals(obj) { + var incrementals = new Array(); + if (!obj) + return incrementals; + var children = obj.childNodes; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (hasClass(child, 'incremental')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'incremental'); + for (var j = 0; j < child.childNodes.length; j++) { + if (child.childNodes[j].nodeType == 1) { + addClass(child.childNodes[j], 'incremental'); + } + } + } else { + incrementals[incrementals.length] = child; + removeClass(child,'incremental'); + } + } + if (hasClass(child, 'show-first')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'show-first'); + if (child.childNodes[isGe].nodeType == 1) { + removeClass(child.childNodes[isGe], 'incremental'); + } + } else { + incrementals[incrementals.length] = child; + } + } + incrementals = incrementals.concat(getIncrementals(child)); + } + return incrementals; +} + +function createIncrementals() { + var incrementals = new Array(); + for (var i = 0; i < smax; i++) { + incrementals[i] = getIncrementals(document.getElementById('slide'+i)); + } + return incrementals; +} + +function defaultCheck() { + var allMetas = document.getElementsByTagName('meta'); + for (var i = 0; i< allMetas.length; i++) { + if (allMetas[i].name == 'defaultView') { + defaultView = allMetas[i].content; + } + if (allMetas[i].name == 'controlVis') { + controlVis = allMetas[i].content; + } + } +} + +// Key trap fix, new function body for trap() +function trap(e) { + if (!e) { + e = event; + e.which = e.keyCode; + } + try { + modifierKey = e.ctrlKey || e.altKey || e.metaKey; + } + catch(e) { + modifierKey = false; + } + return modifierKey || e.which == 0; +} + +function noteLabel() { // Gives notes id's to match parent slides + var notes = GetElementsWithClassName('div','notes'); + for (var i = 0; i < notes.length; i++) { + var note = notes[i]; + var id = 'note' + note.parentNode.id.substring(5); + note.setAttribute('id',id); + } + resetElapsedSlide(); + resetRemainingTime(); + window.setInterval('updateElaspedTime()', 1000); +} + +function createNotesWindow() { // creates a window for our notes + if (!s5NotesWindow || s5NotesWindow.closed) { // Create the window if it doesn't exist + s5NotesWindowLoaded = false; + // Note: Safari has a tendency to ignore window options preferring to default to the settings of the parent window, grr. + s5NotesWindow = window.open('ui/s5-notes.html', 's5NotesWindow', 'top=0,left=0'); + } + if (s5NotesWindowLoaded) { // Load the current note if the Note HTML has loaded + loadNote(); + } else { // Keep trying... + window.setTimeout('createNotesWindow()', 50); + } +} + +function loadNote() { +// Loads a note into the note window + var notes = nextNotes = '<em class="disclaimer">There are no notes for this slide.</em>'; + if (document.getElementById('note' + snum)) { + notes = document.getElementById('note' + snum).innerHTML; + } + if (document.getElementById('note' + (snum + 1))) { + nextNotes = document.getElementById('note' + (snum + 1)).innerHTML; + } + + var jl = document.getElementById('jumplist'); + var slideTitle = jl.options[jl.selectedIndex].text.replace(/^\d+\s+:\s+/, '') + ((jl.selectedIndex) ? ' (' + jl.selectedIndex + '/' + (smax - 1) + ')' : ''); + if (incrementals[snum].length > 0) { +// alert('howdy'); + slideTitle += ' <small>[' + incpos + '/' + incrementals[snum].length + ']</small>'; + } + if (jl.selectedIndex < smax - 1) { + var nextTitle = jl.options[jl.selectedIndex + 1].text.replace(/^\d+\s+:\s+/, '') + ((jl.selectedIndex + 1) ? ' (' + (jl.selectedIndex + 1) + '/' + (smax - 1) + ')' : ''); + } else { + var nextTitle = '[end of slide show]'; + } + + if (s5NotesWindow && !s5NotesWindow.closed && s5NotesWindow.document) { + s5NotesWindow.document.getElementById('slide').innerHTML = slideTitle; + s5NotesWindow.document.getElementById('notes').innerHTML = notes; + s5NotesWindow.document.getElementById('next').innerHTML = nextTitle; + s5NotesWindow.document.getElementById('nextnotes').innerHTML = nextNotes; + } + resetElapsedSlide(); +} + +function minimizeTimer(id) { + var obj = s5NotesWindow.document.getElementById(id); + if (hasClass(obj,'collapsed')) { + removeClass(obj,'collapsed'); + } else { + addClass(obj,'collapsed'); + } +} + +function resetElapsedTime() { + presentationStart = new Date(); + slideStart = new Date(); + updateElaspedTime(); +} + +function resetElapsedSlide() { + if (snum != previousSlide) { + slideStart = new Date(); + previousSlide = snum; + updateElaspedTime(); + } +} + +function updateElaspedTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var now = new Date(); + var ep = s5NotesWindow.document.getElementById('elapsed-presentation'); + var es = s5NotesWindow.document.getElementById('elapsed-slide'); + ep.innerHTML = formatTime(now.valueOf() - presentationStart.valueOf()); + es.innerHTML = formatTime(now.valueOf() - slideStart.valueOf()); +} + +function resetRemainingTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var startField = s5NotesWindow.document.getElementById('startFrom'); + startFrom = readTime(startField.value); + countdown.remaining = startFrom * 60000; // convert to msecs + countdown.start = new Date().valueOf(); + countdown.end = countdown.start + countdown.remaining; + var tl = s5NotesWindow.document.getElementById('timeLeft'); + var timeLeft = formatTime(countdown.remaining); + tl.innerHTML = timeLeft; +} + +function updateRemainingTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var tl = s5NotesWindow.document.getElementById('timeLeft'); + var now = new Date(); + if (countdown.state == 'run') { + countdown.remaining = countdown.end - now; + } + tl.style.color = ''; + tl.style.backgroundColor = ''; + if (countdown.remaining >= 0) { + var timeLeft = formatTime(countdown.remaining); + removeClass(tl,'overtime'); + if (countdown.remaining < 300000) { + tl.style.color = 'rgb(' + (255-Math.round(countdown.remaining/2000)) + ',0,0)'; + tl.style.backgroundColor = 'rgb(255,255,' + (Math.round(countdown.remaining/2000)) + ')'; + } + } else { + var timeLeft = '-' + formatTime(-countdown.remaining); + addClass(tl,'overtime'); + } + tl.innerHTML = timeLeft; +} + +function toggleRemainingTime() { + if (countdown.state == 'pause') countdown.state = 'run'; else countdown.state = 'pause'; + if (countdown.state == 'pause') { + window.clearInterval(countdown.timer); + } + if (countdown.state == 'run') { + countdown.start = new Date().valueOf(); + countdown.end = countdown.start + countdown.remaining; + countdown.timer = window.setInterval('updateRemainingTime()', 1000); + } +} + +function alterRemainingTime(amt) { + var change = amt * 60000; // convert to msecs + countdown.end += change; + countdown.remaining += change; + updateRemainingTime(); +} + +function formatTime(msecs) { + var time = new Date(msecs); + + var hrs = time.getUTCHours() + ((time.getUTCDate() -1) * 24); // I doubt anyone will spend more than 24 hours on a presentation or single slide but just in case... + hrs = (hrs < 10) ? '0'+hrs : hrs; + if (hrs == 'NaN' || isNaN(hrs)) hrs = '--'; + + var min = time.getUTCMinutes(); + min = (min < 10) ? '0'+min : min; + if (min == 'NaN' || isNaN(min)) min = '--'; + + var sec = time.getUTCSeconds(); + sec = (sec < 10) ? '0'+sec : sec; + if (sec == 'NaN' || isNaN(sec)) sec = '--'; + + return hrs + ':' + min + ':' + sec; +} + +function readTime(val) { + var sregex = /:/; + var matches = sregex.exec(val); + if (matches == null) { + return val; + } else { + var times = val.split(':'); + var hours = parseInt(times[0]); + var mins = parseInt(times[1]); + var total = (hours * 60) + mins; + return total; + } +} + +function windowChange() { + fontScale(); +} + +function startup() { + defaultCheck(); + createControls(); // hallvord + slideLabel(); + incrementals = createIncrementals(); + noteLabel(); // [SI:060104] must follow slideLabel() + loadNote(); + fixLinks(); + externalLinks(); + fontScale(); + if (!isOp) notOperaFix(); + slideJump(); + if (defaultView == 'outline') { + toggle(); + } + document.onkeyup = keys; + document.onkeypress = trap; + document.onclick = clicker; +} + +window.onload = startup; +window.onresize = function(){setTimeout('windowChange()',5);} \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008_ja/ui/moose/blank.gif b/Moose_YAPC_Asia_2008_ja/ui/moose/blank.gif new file mode 100644 index 0000000..75b945d Binary files /dev/null and b/Moose_YAPC_Asia_2008_ja/ui/moose/blank.gif differ diff --git a/Moose_YAPC_Asia_2008_ja/ui/moose/bodybg.gif b/Moose_YAPC_Asia_2008_ja/ui/moose/bodybg.gif new file mode 100755 index 0000000..5f448a1 Binary files /dev/null and b/Moose_YAPC_Asia_2008_ja/ui/moose/bodybg.gif differ diff --git a/Moose_YAPC_Asia_2008_ja/ui/moose/framing.css b/Moose_YAPC_Asia_2008_ja/ui/moose/framing.css new file mode 100644 index 0000000..2a27daf --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/moose/framing.css @@ -0,0 +1,22 @@ +/* The following styles size, place, and layer the slide components. + Edit these if you want to change the overall slide layout. + The commented lines can be uncommented (and modified, if necessary) + to help you with the rearrangement process. */ + +/* target = 1024x768 */ + +div#header, div#footer, .slide {width: 100%; top: 0; left: 0;} +div#header {top: 0; height: 3em; z-index: 1;} +div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;} +.slide {top: 0; width: 92%; padding: 3.5em 4% 4%; z-index: 2; list-style: none;} +div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;} +div#controls form {text-align: right; width: 100%; margin: 0;} +#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; z-index: 10;} +html>body #currentSlide {position: fixed;} + +/* +div#header {background: #FCC;} +div#footer {background: #CCF;} +div#controls {background: #BBD;} +div#currentSlide {background: #FFC;} +*/ diff --git a/Moose_YAPC_Asia_2008_ja/ui/moose/iepngfix.htc b/Moose_YAPC_Asia_2008_ja/ui/moose/iepngfix.htc new file mode 100644 index 0000000..bba2db7 --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/moose/iepngfix.htc @@ -0,0 +1,42 @@ +<public:component> +<public:attach event="onpropertychange" onevent="doFix()" /> + +<script> + +// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com +// Free usage permitted as long as this notice remains intact. + +// This must be a path to a blank image. That's all the configuration you need here. +var blankImg = 'ui/default/blank.gif'; + +var f = 'DXImageTransform.Microsoft.AlphaImageLoader'; + +function filt(s, m) { + if (filters[f]) { + filters[f].enabled = s ? true : false; + if (s) with (filters[f]) { src = s; sizingMethod = m } + } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")'; +} + +function doFix() { + if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) || + (event && !/(background|src)/.test(event.propertyName))) return; + + if (tagName == 'IMG') { + if ((/\.png$/i).test(src)) { + filt(src, 'image'); // was 'scale' + src = blankImg; + } else if (src.indexOf(blankImg) < 0) filt(); + } else if (style.backgroundImage) { + if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) { + var s = RegExp.$1; + style.backgroundImage = ''; + filt(s, 'crop'); + } else filt(); + } +} + +doFix(); + +</script> +</public:component> \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008_ja/ui/moose/moose_watermark.gif b/Moose_YAPC_Asia_2008_ja/ui/moose/moose_watermark.gif new file mode 100644 index 0000000..a67bafc Binary files /dev/null and b/Moose_YAPC_Asia_2008_ja/ui/moose/moose_watermark.gif differ diff --git a/Moose_YAPC_Asia_2008_ja/ui/moose/moose_watermark.png b/Moose_YAPC_Asia_2008_ja/ui/moose/moose_watermark.png new file mode 100644 index 0000000..3963b59 Binary files /dev/null and b/Moose_YAPC_Asia_2008_ja/ui/moose/moose_watermark.png differ diff --git a/Moose_YAPC_Asia_2008_ja/ui/moose/notes.css b/Moose_YAPC_Asia_2008_ja/ui/moose/notes.css new file mode 100644 index 0000000..5858cf2 --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/moose/notes.css @@ -0,0 +1,122 @@ +/* Following are the note styles -- edit away! */ + +body { + margin: 0; + padding: 1.0em; + background: #333; + color: #FFF; + font: 2em/1.4em 'Lucida Grande', Verdana, sans-serif; +} + +div.timers { + background: #FFF; + color: #333; + border: 0.08em solid #222; + border-top-width: 1px; + border-left-width: 1px; + float: left; + padding: 0.2em; + margin: 0 0 0.5em; + position: relative; +} + +div.timers h1 { + text-align: left; + font-size: 0.6em; + line-height: 1.4em; + background-color: #FF9; + padding: 0 0.75em; + margin: 0.25em 0 0; + border: 1px solid #EE8; +} + +div.timers div.controls { + position: absolute; + right: 0.25em; + top: 0.1em; + line-height: 1em; +} + +div.timers h1 a { + text-decoration: none; + color: #000; +} + +div.timers div.controls a { + font-size: 0.5em; + padding: 0; + color: #330; +} + +div.timers a.control { + position: absolute; + text-decoration: none; + padding: 0 0.25em; + color: #AAA; + outline: 0; +} + +#minus { + left: 0.25em; +} + +#plus { + right: 0.25em; +} + +.overtime { + background: yellow; + color: red; + border: 3px solid; + padding: 0.1em 0.25em; + font-weight: bold; +} + +div.timers h2 { + font-size: 0.6em; + line-height: 1.0em; + font-weight: normal; + margin: 0 0 -0.25em; + padding-top: 0.5em; + color: #666; +} + +div.timers p {margin: 0; padding: 0 0.5em;} +div.timers form {margin: 0;} + +div.timers span.clock { + font-family: monospace; +} + +div.timers ul {margin: 0; padding: 0; list-style: none;} +div.timers li {float: left; width: 5em; margin: 0; padding: 0 0.5em; + text-align: center;} + +div#elapsed {width: 12.1em;} +div#remaining {clear: left; width: 12.1em;} +div#remaining p {text-align: center;} + +#slide, +#next, +#notes, +#nextnotes { + font-size: 0.75em; + line-height: 1.4em; + clear: left; +/* max-width: 30.0em; */ + text-shadow: 0.1em 0.1em 0.1em #111; +} + +#next {margin-top: 2.5em;} +#next, #nextnotes { + color: #999; + font-size: 0.66em; +} + +em.disclaimer { + color: #666; +} + +div.collapsed h1 {display: block; font-size: 0.33em;} +div.collapsed h1 a {display: inline;} +div.collapsed * {display: none;} diff --git a/Moose_YAPC_Asia_2008_ja/ui/moose/opera.css b/Moose_YAPC_Asia_2008_ja/ui/moose/opera.css new file mode 100644 index 0000000..9e9d2a3 --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/moose/opera.css @@ -0,0 +1,7 @@ +/* DO NOT CHANGE THESE unless you really want to break Opera Show */ +.slide { + visibility: visible !important; + position: static !important; + page-break-before: always; +} +#slide0 {page-break-before: avoid;} diff --git a/Moose_YAPC_Asia_2008_ja/ui/moose/outline.css b/Moose_YAPC_Asia_2008_ja/ui/moose/outline.css new file mode 100644 index 0000000..62db519 --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/moose/outline.css @@ -0,0 +1,15 @@ +/* don't change this unless you want the layout stuff to show up in the outline view! */ + +.layout div, #footer *, #controlForm * {display: none;} +#footer, #controls, #controlForm, #navLinks, #toggle { + display: block; visibility: visible; margin: 0; padding: 0;} +#toggle {float: right; padding: 0.5em;} +html>body #toggle {position: fixed; top: 0; right: 0;} + +/* making the outline look pretty-ish */ + +#slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;} +#slide0 h1 {padding-top: 1.5em;} +.slide h1 {margin: 1.5em 0 0; padding-top: 0.25em; + border-top: 1px solid #888; border-bottom: 1px solid #AAA;} +#toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;} diff --git a/Moose_YAPC_Asia_2008_ja/ui/moose/pretty.css b/Moose_YAPC_Asia_2008_ja/ui/moose/pretty.css new file mode 100644 index 0000000..47bd4c5 --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/moose/pretty.css @@ -0,0 +1,91 @@ +/* Following are the presentation styles -- edit away! */ + +body {background: #FFF url(moose_watermark.png) -16px 0 no-repeat; color: #000; font-size: 1.5em;} +:link, :visited {text-decoration: none; color: #3399cc;} +#controls :active {color: #333 !important;} +#controls :focus {outline: 1px dotted #227;} +h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;} +ul, pre {margin: 0; line-height: 1em;} +html, body {margin: 0; padding: 0;} + +blockquote, q {font-style: italic;} +blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;} +blockquote p {margin: 0;} +blockquote i {font-style: normal;} +blockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;} +blockquote b i {font-style: italic;} + +kbd {font-weight: bold; font-size: 1em;} +sup {font-size: smaller; line-height: 1px;} + +.slide code {font-size: 0.75em; padding: 2px 0.2em; font-weight: bold; color: #533;} +.slide code.bad, code del {color: red;} +.slide code.old {color: silver;} +.slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: #533; font-size: 90%;} +.slide pre code {font-size: 0.75em; margin-left: 5%; display: block; line-height: 1.25em;} +.slide ul {margin-left: 5%; margin-right: 7%; list-style: disc;} +.slide li {margin-top: 0.75em; margin-right: 0;} +.slide ul ul {line-height: 1;} +.slide ul ul li {margin: .2em; font-size: 85%; list-style: square;} +.slide img.leader {display: block; margin: 0 auto;} + +div#header, div#footer {background: #39c; color: #333; + font-family: Verdana, Helvetica, sans-serif;} +div#header {background: #3399cc url(moose_watermark.png) -16px 0 no-repeat; + line-height: 1px;} +div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;} +#footer h1, #footer h2 {display: block; padding: 0 1em;} +#footer h2 {font-style: italic;} + +div.long {font-size: 0.75em;} +.slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1; + margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap; + font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize; + color: #333;} +.slide h2 {position: absolute; top: 3.5em; left: 100px; z-index: 1; + margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap; + font: bold 95%/0.7em Helvetica, sans-serif; text-transform: capitalize; + color: #333;} +.slide h3 {font-size: 130%;} +h1 abbr {font-variant: small-caps;} + +div#header { height: 4.5em } +.slide { padding-top: 5em } + +div#controls {position: absolute; left: 60%; bottom: 0; + width: 40%; + text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;} +html>body div#controls {position: fixed; padding: 0; top: auto;} +#controls #navLinks a {padding: 0; margin: 0 0.5em; + background: #3399cc; border: none; color: #333; + cursor: pointer;} +#controls #navList #jumplist {background: #DDD; color: #227;} + +#currentSlide {text-align: center; font-size: 0.5em; color: #333;} + +#slide0 {padding-top: 3.5em; font-size: 90%;} +#slide0 h1 {position: static; margin: 1em 0 0; padding: 0; + font: bold 2em Helvetica, sans-serif; white-space: normal; + color: #000; background: transparent;} +#slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;} +#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;} +#slide0 h4 {margin-top: 0; font-size: 1em;} + +ul.urls {list-style: none; display: inline; margin: 0;} +.urls li {display: inline; margin: 0;} +.note {display: none;} +.external {border-bottom: 1px dotted gray;} +html>body .external {border-bottom: none;} +.external:after {content: " \274F"; font-size: smaller; color: #77B;} + +.incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;} +img.incremental {visibility: hidden;} +.slide .current {color: #B02;} + + +/* diagnostics + +li:after {content: " [" attr(class) "]"; color: #F88;} + */ + + diff --git a/Moose_YAPC_Asia_2008_ja/ui/moose/print.css b/Moose_YAPC_Asia_2008_ja/ui/moose/print.css new file mode 100644 index 0000000..e7a71d1 --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/moose/print.css @@ -0,0 +1 @@ +/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */ .slide, ul {page-break-inside: avoid; visibility: visible !important;} h1 {page-break-after: avoid;} body {font-size: 12pt; background: white;} * {color: black;} #slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;} #slide0 h3 {margin: 0; padding: 0;} #slide0 h4 {margin: 0 0 0.5em; padding: 0;} #slide0 {margin-bottom: 3em;} h1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;} .extra {background: transparent !important;} div.extra, pre.extra, .example {font-size: 10pt; color: #333;} ul.extra a {font-weight: bold;} p.example {display: none;} #header {display: none;} #footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;} #footer h2, #controls {display: none;} /* The following rule keeps the layout stuff out of print. Remove at your own risk! */ .layout, .layout * {display: none !important;} \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008_ja/ui/moose/s5-core.css b/Moose_YAPC_Asia_2008_ja/ui/moose/s5-core.css new file mode 100644 index 0000000..ad1530b --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/moose/s5-core.css @@ -0,0 +1,9 @@ +/* Do not edit or override these styles! The system will likely break if you do. */ + +div#header, div#footer, div#controls, .slide {position: absolute;} +html>body div#header, html>body div#footer, + html>body div#controls, html>body .slide {position: fixed;} +.handout, .notes {display: none;} +.layout {display: block;} +.slide, .hideme, .incremental {visibility: hidden;} +#slide0 {visibility: visible;} diff --git a/Moose_YAPC_Asia_2008_ja/ui/moose/slides.css b/Moose_YAPC_Asia_2008_ja/ui/moose/slides.css new file mode 100644 index 0000000..0786d7d --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/moose/slides.css @@ -0,0 +1,3 @@ +@import url(s5-core.css); /* required to make the slide show run at all */ +@import url(framing.css); /* sets basic placement and size of slide components */ +@import url(pretty.css); /* stuff that makes the slides look better than blah */ \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008_ja/ui/moose/slides.js b/Moose_YAPC_Asia_2008_ja/ui/moose/slides.js new file mode 100644 index 0000000..ab2a4b2 --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/moose/slides.js @@ -0,0 +1,764 @@ +// S5 v1.2a1 slides.js -- released into the Public Domain +// +// Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information +// about all the wonderful and talented contributors to this code! + +var undef; +var slideCSS = ''; +var snum = 0; +var smax = 1; +var incpos = 0; +var number = undef; +var s5mode = true; +var defaultView = 'slideshow'; +var controlVis = 'visible'; + +var s5NotesWindow; +var s5NotesWindowLoaded = false; +var previousSlide = 0; +var presentationStart = new Date(); +var slideStart = new Date(); + +var countdown = { + timer: 0, + state: 'pause', + start: new Date(), + end: 0, + remaining: 0 +}; + + +var isIE = navigator.appName == 'Microsoft Internet Explorer' && navigator.userAgent.indexOf('Opera') < 1 ? 1 : 0; +var isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0; +var isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0; + +function hasClass(object, className) { + if (!object.className) return false; + return (object.className.search('(^|\\s)' + className + '(\\s|$)') != -1); +} + +function hasValue(object, value) { + if (!object) return false; + return (object.search('(^|\\s)' + value + '(\\s|$)') != -1); +} + +function removeClass(object,className) { + if (!object || !hasClass(object,className)) return; + object.className = object.className.replace(new RegExp('(^|\\s)'+className+'(\\s|$)'), RegExp.$1+RegExp.$2); +} + +function addClass(object,className) { + if (!object || hasClass(object, className)) return; + if (object.className) { + object.className += ' '+className; + } else { + object.className = className; + } +} + +function GetElementsWithClassName(elementName,className) { + var allElements = document.getElementsByTagName(elementName); + var elemColl = new Array(); + for (var i = 0; i< allElements.length; i++) { + if (hasClass(allElements[i], className)) { + elemColl[elemColl.length] = allElements[i]; + } + } + return elemColl; +} + +function isParentOrSelf(element, id) { + if (element == null || element.nodeName=='BODY') return false; + else if (element.id == id) return true; + else return isParentOrSelf(element.parentNode, id); +} + +function nodeValue(node) { + var result = ""; + if (node.nodeType == 1) { + var children = node.childNodes; + for (var i = 0; i < children.length; ++i) { + result += nodeValue(children[i]); + } + } + else if (node.nodeType == 3) { + result = node.nodeValue; + } + return(result); +} + +function slideLabel() { + var slideColl = GetElementsWithClassName('*','slide'); + var list = document.getElementById('jumplist'); + smax = slideColl.length; + for (var n = 0; n < smax; n++) { + var obj = slideColl[n]; + + var did = 'slide' + n.toString(); + obj.setAttribute('id',did); + +// if (isOp) continue; // Opera fix (hallvord) + + var otext = ''; + var menu = obj.firstChild; + if (!menu) continue; // to cope with empty slides + while (menu && menu.nodeType == 3) { + menu = menu.nextSibling; + } + if (!menu) continue; // to cope with slides with only text nodes + + var menunodes = menu.childNodes; + for (var o = 0; o < menunodes.length; o++) { + otext += nodeValue(menunodes[o]); + } + list.options[list.length] = new Option(n + ' : ' + otext, n); + } +} + +function currentSlide() { + var cs; + if (document.getElementById) { + cs = document.getElementById('currentSlide'); + } else { + cs = document.currentSlide; + } + cs.innerHTML = '<a id="plink" href="">' + + '<span id="csHere">' + snum + '<\/span> ' + + '<span id="csSep">\/<\/span> ' + + '<span id="csTotal">' + (smax-1) + '<\/span>' + + '<\/a>' + ; + if (snum == 0) { + cs.style.visibility = 'hidden'; + } else { + cs.style.visibility = 'visible'; + } +} + +function go(step) { + if (document.getElementById('slideProj').disabled || step == 0) return; + var jl = document.getElementById('jumplist'); + var cid = 'slide' + snum; + var ce = document.getElementById(cid); + if (incrementals[snum].length > 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + removeClass(incrementals[snum][i], 'current'); + removeClass(incrementals[snum][i], 'incremental'); + } + } + if (step != 'j') { + snum += step; + lmax = smax - 1; + if (snum > lmax) snum = lmax; + if (snum < 0) snum = 0; + } else + snum = parseInt(jl.value); + var nid = 'slide' + snum; + var ne = document.getElementById(nid); + if (!ne) { + ne = document.getElementById('slide0'); + snum = 0; + } + if (step < 0) {incpos = incrementals[snum].length} else {incpos = 0;} + if (incrementals[snum].length > 0 && incpos == 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + if (hasClass(incrementals[snum][i], 'current')) + incpos = i + 1; + else + addClass(incrementals[snum][i], 'incremental'); + } + } + if (incrementals[snum].length > 0 && incpos > 0) + addClass(incrementals[snum][incpos - 1], 'current'); + if (isOp) { //hallvord + location.hash = nid; + } else { + ce.style.visibility = 'hidden'; + ne.style.visibility = 'visible'; + } // /hallvord + jl.selectedIndex = snum; + currentSlide(); + loadNote(); + permaLink(); + number = undef; +} + +function goTo(target) { + if (target >= smax || target == snum) return; + go(target - snum); +} + +function subgo(step) { + if (step > 0) { + removeClass(incrementals[snum][incpos - 1],'current'); + removeClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos],'current'); + incpos++; + } else { + incpos--; + removeClass(incrementals[snum][incpos],'current'); + addClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos - 1],'current'); + } + loadNote(); +} + +function toggle() { + var slideColl = GetElementsWithClassName('*','slide'); + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + if (!slides.disabled) { + slides.disabled = true; + outline.disabled = false; + s5mode = false; + fontSize('1em'); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'visible'; + } + } else { + slides.disabled = false; + outline.disabled = true; + s5mode = true; + fontScale(); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'hidden'; + } + slideColl[snum].style.visibility = 'visible'; + } +} + +function showHide(action) { + var obj = GetElementsWithClassName('*','hideme')[0]; + switch (action) { + case 's': obj.style.visibility = 'visible'; break; + case 'h': obj.style.visibility = 'hidden'; break; + case 'k': + if (obj.style.visibility != 'visible') { + obj.style.visibility = 'visible'; + } else { + obj.style.visibility = 'hidden'; + } + break; + } +} + +// 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/) +function keys(key) { + if (!key) { + key = event; + key.which = key.keyCode; + } + if (key.which == 84) { + toggle(); + return; + } + if (s5mode) { + switch (key.which) { + case 10: // return + case 13: // enter + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + if(number != undef) { + goTo(number); + break; + } + case 32: // spacebar + case 34: // page down + case 39: // rightkey + case 40: // downkey + if(number != undef) { + go(number); + } else if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + break; + case 33: // page up + case 37: // leftkey + case 38: // upkey + if(number != undef) { + go(-1 * number); + } else if (!incrementals[snum] || incpos <= 0) { + go(-1); + } else { + subgo(-1); + } + break; + case 36: // home + goTo(0); + break; + case 35: // end + goTo(smax-1); + break; + case 67: // c + showHide('k'); + break; + case 78: // n + createNotesWindow(); + break; + } + if (key.which < 48 || key.which > 57) { + number = undef; + } else { + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + number = (((number != undef) ? number : 0) * 10) + (key.which - 48); + } + } + return false; +} + +function clicker(e) { + number = undef; + var target; + if (window.event) { + target = window.event.srcElement; + e = window.event; + } else target = e.target; + if (target.href != null || hasValue(target.rel, 'external') || isParentOrSelf(target, 'controls') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object')) return true; + if (!e.which || e.which == 1) { + if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + } +} + +function findSlide(hash) { + var target = null; + var slides = GetElementsWithClassName('*','slide'); + for (var i = 0; i < slides.length; i++) { + var targetSlide = slides[i]; + if ( (targetSlide.name && targetSlide.name == hash) + || (targetSlide.id && targetSlide.id == hash) ) { + target = targetSlide; + break; + } + } + while(target != null && target.nodeName != 'BODY') { + if (hasClass(target, 'slide')) { + return parseInt(target.id.slice(5)); + } + target = target.parentNode; + } + return null; +} + +function slideJump() { + if (window.location.hash == null) return; + var sregex = /^#slide(\d+)$/; + var matches = sregex.exec(window.location.hash); + var dest = null; + if (matches != null) { + dest = parseInt(matches[1]); + } else { + dest = findSlide(window.location.hash.slice(1)); + } + if (dest != null) + go(dest - snum); +} + +function fixLinks() { + var thisUri = window.location.href; + thisUri = thisUri.slice(0, thisUri.length - window.location.hash.length); + var aelements = document.getElementsByTagName('A'); + for (var i = 0; i < aelements.length; i++) { + var a = aelements[i].href; + var slideID = a.match('\#slide[0-9]{1,2}'); + if ((slideID) && (slideID[0].slice(0,1) == '#')) { + var dest = findSlide(slideID[0].slice(1)); + if (dest != null) { + if (aelements[i].addEventListener) { + aelements[i].addEventListener("click", new Function("e", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "if (e.preventDefault) e.preventDefault();"), true); + } else if (aelements[i].attachEvent) { + aelements[i].attachEvent("onclick", new Function("", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "event.returnValue = false;")); + } + } + } + } +} + +function externalLinks() { + if (!document.getElementsByTagName) return; + var anchors = document.getElementsByTagName('a'); + for (var i=0; i<anchors.length; i++) { + var anchor = anchors[i]; + if (anchor.getAttribute('href') && hasValue(anchor.rel, 'external')) { + anchor.target = '_blank'; + addClass(anchor,'external'); + } + } +} + +function permaLink() { + document.getElementById('plink').href = window.location.pathname + '#slide' + snum; +} + +function createControls() { + var controlsDiv = document.getElementById("controls"); + if (!controlsDiv) return; + var hider = ' onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"'; + var hideDiv, hideList = ''; + if (controlVis == 'hidden') { + hideDiv = hider; + } else { + hideList = hider; + } + controlsDiv.innerHTML = '<form action="#" id="controlForm"' + hideDiv + '>' + + '<div id="navLinks">' + + '<a accesskey="n" id="show-notes" href="javascript:createNotesWindow();" title="Show Notes">≡<\/a>' + + '<a accesskey="t" id="toggle" href="javascript:toggle();">Ø<\/a>' + + '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' + + '<a accesskey="x" id="next" href="javascript:go(1);">»<\/a>' + + '<div id="navList"' + hideList + '><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>' + + '<\/div><\/form>'; + if (controlVis == 'hidden') { + var hidden = document.getElementById('navLinks'); + } else { + var hidden = document.getElementById('jumplist'); + } + addClass(hidden,'hideme'); +} + +function fontScale() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers + if (!s5mode) return false; + var vScale = 48; // both yield 16 (the usual browser default) at 1024x768 + var hScale = 64; // perhaps should auto-calculate based on theme's declared value? + if (window.innerHeight) { + var vSize = window.innerHeight; + var hSize = window.innerWidth; + } else if (document.documentElement.clientHeight) { + var vSize = document.documentElement.clientHeight; + var hSize = document.documentElement.clientWidth; + } else if (document.body.clientHeight) { + var vSize = document.body.clientHeight; + var hSize = document.body.clientWidth; + } else { + var vSize = 700; // assuming 1024x768, minus chrome and such + var hSize = 1024; // these do not account for kiosk mode or Opera Show + } + var newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale)); + fontSize(newSize + 'px'); + if (isGe) { // hack to counter incremental reflow bugs + var obj = document.getElementsByTagName('body')[0]; + obj.style.display = 'none'; + obj.style.display = 'block'; + } +} + +function fontSize(value) { + if (!(s5ss = document.getElementById('s5ss'))) { + if (!document.createStyleSheet) { + document.getElementsByTagName('head')[0].appendChild(s5ss = document.createElement('style')); + s5ss.setAttribute('media','screen, projection'); + s5ss.setAttribute('id','s5ss'); + } else { + document.createStyleSheet(); + document.s5ss = document.styleSheets[document.styleSheets.length - 1]; + } + } + if (!(document.s5ss && document.s5ss.addRule)) { + while (s5ss.lastChild) s5ss.removeChild(s5ss.lastChild); + s5ss.appendChild(document.createTextNode('html {font-size: ' + value + ' !important;}')); + } else { + document.s5ss.addRule('html','font-size: ' + value + ' !important;'); + } +} + +function notOperaFix() { + slideCSS = document.getElementById('slideProj').href; + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + slides.setAttribute('media','screen'); + outline.disabled = true; + if (isGe) { + slides.setAttribute('href','null'); // Gecko fix + slides.setAttribute('href',slideCSS); // Gecko fix + } + if (isIE && document.styleSheets && document.styleSheets[0]) { + document.styleSheets[0].addRule('img', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('div', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('.slide', 'behavior: url(ui/default/iepngfix.htc)'); + } +} + +function getIncrementals(obj) { + var incrementals = new Array(); + if (!obj) + return incrementals; + var children = obj.childNodes; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (hasClass(child, 'incremental')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'incremental'); + for (var j = 0; j < child.childNodes.length; j++) { + if (child.childNodes[j].nodeType == 1) { + addClass(child.childNodes[j], 'incremental'); + } + } + } else { + incrementals[incrementals.length] = child; + removeClass(child,'incremental'); + } + } + if (hasClass(child, 'show-first')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'show-first'); + if (child.childNodes[isGe].nodeType == 1) { + removeClass(child.childNodes[isGe], 'incremental'); + } + } else { + incrementals[incrementals.length] = child; + } + } + incrementals = incrementals.concat(getIncrementals(child)); + } + return incrementals; +} + +function createIncrementals() { + var incrementals = new Array(); + for (var i = 0; i < smax; i++) { + incrementals[i] = getIncrementals(document.getElementById('slide'+i)); + } + return incrementals; +} + +function defaultCheck() { + var allMetas = document.getElementsByTagName('meta'); + for (var i = 0; i< allMetas.length; i++) { + if (allMetas[i].name == 'defaultView') { + defaultView = allMetas[i].content; + } + if (allMetas[i].name == 'controlVis') { + controlVis = allMetas[i].content; + } + } +} + +// Key trap fix, new function body for trap() +function trap(e) { + if (!e) { + e = event; + e.which = e.keyCode; + } + try { + modifierKey = e.ctrlKey || e.altKey || e.metaKey; + } + catch(e) { + modifierKey = false; + } + return modifierKey || e.which == 0; +} + +function noteLabel() { // Gives notes id's to match parent slides + var notes = GetElementsWithClassName('div','notes'); + for (var i = 0; i < notes.length; i++) { + var note = notes[i]; + var id = 'note' + note.parentNode.id.substring(5); + note.setAttribute('id',id); + } + resetElapsedSlide(); + resetRemainingTime(); + window.setInterval('updateElaspedTime()', 1000); +} + +function createNotesWindow() { // creates a window for our notes + if (!s5NotesWindow || s5NotesWindow.closed) { // Create the window if it doesn't exist + s5NotesWindowLoaded = false; + // Note: Safari has a tendency to ignore window options preferring to default to the settings of the parent window, grr. + s5NotesWindow = window.open('ui/s5-notes.html', 's5NotesWindow', 'top=0,left=0'); + } + if (s5NotesWindowLoaded) { // Load the current note if the Note HTML has loaded + loadNote(); + } else { // Keep trying... + window.setTimeout('createNotesWindow()', 50); + } +} + +function loadNote() { +// Loads a note into the note window + var notes = nextNotes = '<em class="disclaimer">There are no notes for this slide.</em>'; + if (document.getElementById('note' + snum)) { + notes = document.getElementById('note' + snum).innerHTML; + } + if (document.getElementById('note' + (snum + 1))) { + nextNotes = document.getElementById('note' + (snum + 1)).innerHTML; + } + + var jl = document.getElementById('jumplist'); + var slideTitle = jl.options[jl.selectedIndex].text.replace(/^\d+\s+:\s+/, '') + ((jl.selectedIndex) ? ' (' + jl.selectedIndex + '/' + (smax - 1) + ')' : ''); + if (incrementals[snum].length > 0) { +// alert('howdy'); + slideTitle += ' <small>[' + incpos + '/' + incrementals[snum].length + ']</small>'; + } + if (jl.selectedIndex < smax - 1) { + var nextTitle = jl.options[jl.selectedIndex + 1].text.replace(/^\d+\s+:\s+/, '') + ((jl.selectedIndex + 1) ? ' (' + (jl.selectedIndex + 1) + '/' + (smax - 1) + ')' : ''); + } else { + var nextTitle = '[end of slide show]'; + } + + if (s5NotesWindow && !s5NotesWindow.closed && s5NotesWindow.document) { + s5NotesWindow.document.getElementById('slide').innerHTML = slideTitle; + s5NotesWindow.document.getElementById('notes').innerHTML = notes; + s5NotesWindow.document.getElementById('next').innerHTML = nextTitle; + s5NotesWindow.document.getElementById('nextnotes').innerHTML = nextNotes; + } + resetElapsedSlide(); +} + +function minimizeTimer(id) { + var obj = s5NotesWindow.document.getElementById(id); + if (hasClass(obj,'collapsed')) { + removeClass(obj,'collapsed'); + } else { + addClass(obj,'collapsed'); + } +} + +function resetElapsedTime() { + presentationStart = new Date(); + slideStart = new Date(); + updateElaspedTime(); +} + +function resetElapsedSlide() { + if (snum != previousSlide) { + slideStart = new Date(); + previousSlide = snum; + updateElaspedTime(); + } +} + +function updateElaspedTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var now = new Date(); + var ep = s5NotesWindow.document.getElementById('elapsed-presentation'); + var es = s5NotesWindow.document.getElementById('elapsed-slide'); + ep.innerHTML = formatTime(now.valueOf() - presentationStart.valueOf()); + es.innerHTML = formatTime(now.valueOf() - slideStart.valueOf()); +} + +function resetRemainingTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var startField = s5NotesWindow.document.getElementById('startFrom'); + startFrom = readTime(startField.value); + countdown.remaining = startFrom * 60000; // convert to msecs + countdown.start = new Date().valueOf(); + countdown.end = countdown.start + countdown.remaining; + var tl = s5NotesWindow.document.getElementById('timeLeft'); + var timeLeft = formatTime(countdown.remaining); + tl.innerHTML = timeLeft; +} + +function updateRemainingTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var tl = s5NotesWindow.document.getElementById('timeLeft'); + var now = new Date(); + if (countdown.state == 'run') { + countdown.remaining = countdown.end - now; + } + tl.style.color = ''; + tl.style.backgroundColor = ''; + if (countdown.remaining >= 0) { + var timeLeft = formatTime(countdown.remaining); + removeClass(tl,'overtime'); + if (countdown.remaining < 300000) { + tl.style.color = 'rgb(' + (255-Math.round(countdown.remaining/2000)) + ',0,0)'; + tl.style.backgroundColor = 'rgb(255,255,' + (Math.round(countdown.remaining/2000)) + ')'; + } + } else { + var timeLeft = '-' + formatTime(-countdown.remaining); + addClass(tl,'overtime'); + } + tl.innerHTML = timeLeft; +} + +function toggleRemainingTime() { + if (countdown.state == 'pause') countdown.state = 'run'; else countdown.state = 'pause'; + if (countdown.state == 'pause') { + window.clearInterval(countdown.timer); + } + if (countdown.state == 'run') { + countdown.start = new Date().valueOf(); + countdown.end = countdown.start + countdown.remaining; + countdown.timer = window.setInterval('updateRemainingTime()', 1000); + } +} + +function alterRemainingTime(amt) { + var change = amt * 60000; // convert to msecs + countdown.end += change; + countdown.remaining += change; + updateRemainingTime(); +} + +function formatTime(msecs) { + var time = new Date(msecs); + + var hrs = time.getUTCHours() + ((time.getUTCDate() -1) * 24); // I doubt anyone will spend more than 24 hours on a presentation or single slide but just in case... + hrs = (hrs < 10) ? '0'+hrs : hrs; + if (hrs == 'NaN' || isNaN(hrs)) hrs = '--'; + + var min = time.getUTCMinutes(); + min = (min < 10) ? '0'+min : min; + if (min == 'NaN' || isNaN(min)) min = '--'; + + var sec = time.getUTCSeconds(); + sec = (sec < 10) ? '0'+sec : sec; + if (sec == 'NaN' || isNaN(sec)) sec = '--'; + + return hrs + ':' + min + ':' + sec; +} + +function readTime(val) { + var sregex = /:/; + var matches = sregex.exec(val); + if (matches == null) { + return val; + } else { + var times = val.split(':'); + var hours = parseInt(times[0]); + var mins = parseInt(times[1]); + var total = (hours * 60) + mins; + return total; + } +} + +function windowChange() { + fontScale(); +} + +function startup() { + defaultCheck(); + createControls(); // hallvord + slideLabel(); + incrementals = createIncrementals(); + noteLabel(); // [SI:060104] must follow slideLabel() + loadNote(); + fixLinks(); + externalLinks(); + fontScale(); + if (!isOp) notOperaFix(); + slideJump(); + if (defaultView == 'outline') { + toggle(); + } + document.onkeyup = keys; + document.onkeypress = trap; + document.onclick = clicker; +} + +window.onload = startup; +window.onresize = function(){setTimeout('windowChange()',5);} \ No newline at end of file diff --git a/Moose_YAPC_Asia_2008_ja/ui/s5-notes.html b/Moose_YAPC_Asia_2008_ja/ui/s5-notes.html new file mode 100644 index 0000000..5c6c4ca --- /dev/null +++ b/Moose_YAPC_Asia_2008_ja/ui/s5-notes.html @@ -0,0 +1,64 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<!-- Do not edit this document! The system will likely break if you do. --> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Notes</title> +<link rel="stylesheet" href="default/notes.css" type="text/css" /> +<script type="text/javascript"> +// <![CDATA[ + document.onkeyup = opener.keys; + document.onkeypress = opener.trap; + document.onclick = opener.clicker; +// ]]> +</script> +</head> + +<body onload="opener.s5NotesWindowLoaded=true;" onunload="opener.s5NotesWindowLoaded=false;"> + + +<div class="timers" id="elapsed"> +<h1> +<a href="#" onclick="opener.minimizeTimer('elapsed'); return false;">Elapsed Time</a> +</h1> +<ul> +<li> +<h2>Presentation</h2> +<span class="clock" id="elapsed-presentation">00:00:00</span> +</li> +<li> +<h2>Current Slide</h2> +<span class="clock" id="elapsed-slide">00:00:00</span> +</li> +</ul> +<div class="controls"> +<a href="#reset-elapsed" onclick="opener.resetElapsedTime(); return false;" title="Reset Elapsed Time">|←</a> +</div> +</div> + +<div class="timers" id="remaining"> +<h1> +<a href="#" onclick="opener.minimizeTimer('remaining'); return false;">Remaining Time</a> +</h1> +<p> +<a href="#subtract-remaining" class="control" id="minus" onclick="opener.alterRemainingTime('-5'); return false;" title="Subtract 5 Minutes">-</a> +<span class="clock" id="timeLeft">00:00:00</span> +<a href="#add-remaining" class="control" id="plus" onclick="opener.alterRemainingTime('5'); return false;" title="Add 5 Minutes">+</a> +</p> +<div class="controls"> +<form action="#" onsubmit="opener.resetRemainingTime(); return false;"> +<input type="text" class="text" id="startFrom" value="0" size="4" maxlength="4" /> +<a href="#toggle-remaining" onclick="opener.toggleRemainingTime(); return false;" title="Pause/Run Remaining Time">||</a> +<a href="#reset-remaining" onclick="opener.resetRemainingTime(); return false;" title="Reset Remaining Time">|←</a> +</form> +</div> +</div> + +<h2 id="slide">...</h2> +<div id="notes"></div> + +<h2 id="next">...</h2> +<div id="nextnotes"></div> + +</body> +</html> diff --git a/PPW-2008/._.DS_Store b/PPW-2008/._.DS_Store new file mode 100644 index 0000000..460d887 Binary files /dev/null and b/PPW-2008/._.DS_Store differ diff --git a/PPW-2008/._moose-manager.xul b/PPW-2008/._moose-manager.xul new file mode 100644 index 0000000..d7a8b48 Binary files /dev/null and b/PPW-2008/._moose-manager.xul differ diff --git a/PPW-2008/._moose.xul b/PPW-2008/._moose.xul new file mode 100644 index 0000000..f925402 Binary files /dev/null and b/PPW-2008/._moose.xul differ diff --git a/PPW-2008/._takahashi.css b/PPW-2008/._takahashi.css new file mode 100644 index 0000000..a5e1c31 Binary files /dev/null and b/PPW-2008/._takahashi.css differ diff --git a/PPW-2008/._takahashi.js b/PPW-2008/._takahashi.js new file mode 100644 index 0000000..2431394 Binary files /dev/null and b/PPW-2008/._takahashi.js differ diff --git a/PPW-2008/moose-manager.xul b/PPW-2008/moose-manager.xul new file mode 100644 index 0000000..6f5fc39 --- /dev/null +++ b/PPW-2008/moose-manager.xul @@ -0,0 +1,288 @@ +<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="chrome://global/skin/" type="text/css"?><?xml-stylesheet href="takahashi.css" type="text/css"?><page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="presentation" xmlns:html="http:/www.w3.org/1999/xhtml" orient="vertical" onkeypress="Presentation.onKeyPress(event);"> +<html:textarea id="builtinCode" style="visibility: collapse"><![CDATA[ +The Case for +Switching +to Python +---- +or +---- +A Manager's +Guide +to Moose +---- +Python is +---- +Simple +---- +Clean +---- +Object +Oriented +---- +Easy to +Learn +---- +Easy to +Maintain +---- +Executable +Pseudo-Code +---- +Batteries +Included +---- +General +Purpose +---- +"Keep It Simple Stupid" +---- +ã +---- +Perl is +---- +Large +---- +Ugly +---- +Not +Object +Oriented +---- +Impossible to +Write Good Code +---- +Executable +Line-Noise +---- +CPAN is full of +redundant crap +---- +TIMTOWTDI +---- +â +---- +Moose +---- +Postmodern +Object System +for Perl 5 +---- +TIMTOWTDI-BCINABT +---- +There Is More Than +One Way To Do It +---- +But Consistency Is +Not A Bad Thing +---- +TIMTOWTDOOP +---- +blessed-Hash blessed-Array +Inside-Out blessed-Scalar +XS blessed-TypeGlob +blessed-Regexp Closures +Tied-Objects AUTOLOAD ... +---- +TIMTOWTWOOP +---- +Class::Accessor Class::MakeMethods base.pm Spiffy +Class::HPLOO Class::Base Object::Tiny Object::Lexical +EO Class::Accessor::Fast Class::Closure Class::Meta +Class::Simple Class::Gomor Rose::Object Class::Builder +Class::InsideOut Object::LocalVars Oak::Object OOP +Object::InsideOut Class::Dot Class::NamedParms Myco +Class::Structured Class::Classless parent.pm Eobj +Class::Prototyped Class::Init Class::Maker Class::Object +Fukurama::Class Class::Declare Class::Std Object::Declare +Class::Struct Class::AutoClass Class::Root Badger Oryx +Object::Prototype Basset Object::Accessor Class::Lego +Class::Container Tangram OO::Closures Class::Trait MOP +Object::MultiType SLOOPS Class::TOM Class::PObject +Moose +... and many more +---- +Choices +---- +⺠+---- +Too Many +Choices +---- +â¹ +---- +Consistency +breeds +Maintainability +---- +... +---- +Moose is built +for extensibility +---- +Moose plays +well with CPAN +---- +Mooseification +is incremental +---- +Moose is a +bridge +to Perl 6 +---- +Moose means less code +(less code == less buggs) +---- +Moose means less tests +(why test what +Moose already does) +---- +Moose is +a skill +---- +Thank You +---- +Questions? +---- +]]></html:textarea> + +<deck flex="1" id="deck"> + +<vbox flex="1" + onmousemove="Presentation.onMouseMoveOnCanvas(event);"> + <toolbox id="canvasToolbar"> + <toolbar> + <toolbarbutton oncommand="Presentation.home()" label="|<<" + observes="canBack"/> + <toolbarbutton oncommand="Presentation.back()" label="<" + observes="canBack"/> + <toolbarbutton oncommand="Presentation.forward()" label=">" + observes="canForward"/> + <toolbarbutton oncommand="Presentation.end()" label=">>|" + observes="canForward"/> + <toolbarseparator/> + <hbox align="center"> + <textbox id="current_page" size="4" + oninput="if (this.value) Presentation.showPage(parseInt(this.value)-1);"/> + <description value="/"/> + <description id="max_page"/> + </hbox> + <toolbarseparator/> + <vbox flex="2"> + <spacer flex="1"/> + <scrollbar id="scroller" + align="center" orient="horizontal" + oncommand="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));" + onclick="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));" + onmousedown="Presentation.onScrollerDragStart();" + onmousemove="Presentation.onScrollerDragMove();" + onmouseup="Presentation.onScrollerDragDrop();"/> + <spacer flex="1"/> + </vbox> + <toolbarseparator/> + <spacer flex="1"/> + <toolbarseparator/> + <toolbarbutton id="toggleEva" label="Eva" + type="checkbox" + autoCheck="false" + oncommand="Presentation.toggleEvaMode();"/> + <toolbarseparator/> + <toolbarbutton label="Edit" + oncommand="Presentation.toggleEditMode();"/> + <toolbarbutton oncommand="Presentation.reload();" label="Reload"/> + </toolbar> + </toolbox> + <vbox flex="1" id="canvas" + onclick="Presentation.onPresentationClick(event);"> + <spacer flex="1"/> + <hbox flex="1"> + <spacer flex="1"/> + <vbox id="content"/> + <spacer flex="1"/> + </hbox> + <spacer flex="1"/> + </vbox> +</vbox> + + +<vbox flex="1" id="edit"> + <toolbox> + <toolbar> + <toolbarbutton label="New Page" + oncommand="Presentation.addPage()"/> + <spacer flex="1"/> + <toolbarseparator/> + <toolbarbutton label="View" + oncommand="Presentation.toggleEditMode();"/> + <toolbarbutton oncommand="Presentation.reload();" label="Reload"/> + </toolbar> + </toolbox> + <textbox id="textField" flex="1" multiline="true" + oninput="Presentation.onEdit()"/> + <hbox collapsed="true"> + <iframe id="dataLoader" onload="if (window.Presentation) Presentation.onDataLoad();"/> + </hbox> +</vbox> + +</deck> + + +<broadcasterset> + <broadcaster id="canBack"/> + <broadcaster id="canForward"/> +</broadcasterset> + +<commandset> + <command id="cmd_forward" + oncommand="if (Presentation.isPresentationMode) Presentation.forward();"/> + <command id="cmd_back" + oncommand="if (Presentation.isPresentationMode) Presentation.back();"/> + <command id="cmd_home" + oncommand="if (Presentation.isPresentationMode) Presentation.home();"/> + <command id="cmd_end" + oncommand="if (Presentation.isPresentationMode) Presentation.end();"/> +</commandset> +<keyset> + <key keycode="VK_ENTER" command="cmd_forward"/> + <key keycode="VK_RETURN" command="cmd_forward"/> + <key keycode="VK_PAGE_DOWN" command="cmd_forward"/> + <key keycode="VK_RIGHT" command="cmd_forward"/> + <key keycode="VK_DOWN" command="cmd_forward"/> + <!-- key keycode="VK_BACK_SPACE" command="cmd_back"/--> + <key keycode="VK_PAGE_UP" command="cmd_back"/> + <!-- <key keycode="VK_BACK_UP" command="cmd_back"/>--> + <!-- <key keycode="VK_BACK_LEFT" command="cmd_back"/>--> + <key keycode="VK_HOME" command="cmd_home"/> + <key keycode="VK_END" command="cmd_end"/> + <key key="n" modifiers="accel" oncommand="Presentation.addPage();"/> + <key key="r" modifiers="accel" oncommand="window.location.reload();"/> + <key key="e" modifiers="accel" oncommand="Presentation.toggleEditMode();"/> + <key key="a" modifiers="accel" oncommand="Presentation.toggleEvaMode();"/> +</keyset> + + +<script src="takahashi.js" type="application/x-javascript" /> +</page> +<!-- ***** BEGIN LICENSE BLOCK ***** + - Version: MPL 1.1 + - + - The contents of this file are subject to the Mozilla Public License Version + - 1.1 (the "License"); you may not use this file except in compliance with + - the License. You may obtain a copy of the License at + - http://www.mozilla.org/MPL/ + - + - Software distributed under the License is distributed on an "AS IS" basis, + - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + - for the specific language governing rights and limitations under the + - License. + - + - The Original Code is the Takahashi-Method-based Presentation Tool in XUL. + - + - The Initial Developer of the Original Code is SHIMODA Hiroshi. + - Portions created by the Initial Developer are Copyright (C) 2005 + - the Initial Developer. All Rights Reserved. + - + - Contributor(s): SHIMODA Hiroshi <piro@p.club.ne.jp> + - + - ***** END LICENSE BLOCK ***** --> + + diff --git a/PPW-2008/moose.xul b/PPW-2008/moose.xul new file mode 100644 index 0000000..b1eb3c1 --- /dev/null +++ b/PPW-2008/moose.xul @@ -0,0 +1,533 @@ +<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="chrome://global/skin/" type="text/css"?><?xml-stylesheet href="takahashi.css" type="text/css"?><page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="presentation" xmlns:html="http:/www.w3.org/1999/xhtml" orient="vertical" onkeypress="Presentation.onKeyPress(event);"> +<html:textarea id="builtinCode" style="visibility: collapse"><![CDATA[ +Moose +---- +A Postmodern +Object System +for Perl 5 +---- +Stevan Little +stevan@cpan.org +http://moose.perl.org/ +---- +What is +Moose? +---- +What is +Class::MOP? +---- +What is +a MOP?? +---- +Meta +Object +Protocol +---- +CLOS +---- +20 year old +LISP +technology +---- +Formalization +of the +object system +---- +How +classes +work +---- +How +methods +work +---- +How objects +are created +... etc. +---- +Class::MOP +is CLOS for +Perl 5 +---- +Class::MOP +is a +formalization +of Perl 5 OO +---- +Clarity & +Structure +---- +Class::MOP is +a platform for +---- +Moose +---- + package Person; + use Moose; + + has name => (is => 'rw'); + has age => (is => 'rw'); + + 1; +---- +turns on +strict & +warnings +---- +Moose::Object +in the @ISA +---- +`has` creates +accessor +called 'name' +---- +`has` creates +accessor +called 'age' +---- +*lots* +of class +metadata +---- + package Person; + use Moose; + + has name => (is => 'rw'); + has age => (is => 'rw'); + + 1; +---- +Types +---- + has name => ( + is => 'rw', + isa => 'Str', + required => 1 + ); +---- + has age => ( + is => 'rw', + isa => 'DateTime::Duration', + lazy => 1, + default => sub { + DateTime::Duration->new + } + ); +---- +Custom +Types +---- + use Moose::Util::TypeConstraints; +---- + subtype 'NonEmptyStr' + => as 'Str' + => where { length $_ > 0 }; +---- + has name => ( + is => 'rw', + isa => 'NonEmptyStr', + required => 1 + ); +---- + my $me = Person->new( + name => 'Stevan', + age => DateTime::Duration->new( + years => 35 + ) + ); +---- + my $me = Person->new; # BOOM! name is required +---- + my $me = Person->new( + name => 'Stevan', + age => 35 + ); # BOOM! age should be DateTime::Duration +---- +Coercions +---- + class_type 'DateTime::Duration'; + coerce 'DateTime::Duration' + => from 'Int' + => via { + DateTime::Duration->new( + years => $_ + ) + }; +---- + has age => ( + is => 'rw', + isa => 'DateTime::Duration', + coerce => 1, + lazy => 1, + default => sub { + DateTime::Duration->new + } + ); +---- + my $me = Person->new( + name => 'Stevan', + age => 35 + ); +---- + coerce 'DateTime::Duration' + => from 'Int' + => via { + DateTime::Duration->new( + years => $_ + ) + } + => from 'HashRef' + => via { + DateTime::Duration->new(%$_) + }; +---- + my $me = Person->new( + name => 'Stevan', + age => { years => 35, months => 2 } + ); +---- + my $me = Person->new( + name => 'Stevan', + age => { years => 35, months => 2 } + ); + + $me->name # 'Stevan' + $me->age # DateTime::Duration object +---- + my $xoe = Person->new(name => 'Xoe'); + + $xoe->age(11); + + $xoe->age({ years => 11, months => 10 }); + + $xoe->age(DateTime::Duration->new({ + years => 11, + months => 10 + })); +---- +Delegation +---- + has age => ( + is => 'rw', + isa => 'DateTime::Duration', + coerce => 1, + lazy => 1, + default => sub { + DateTime::Duration->new + }, + handles => { + 'years_old' => 'years' + } + ); +---- + $me->years_old # 35 +---- +Unconventional +Delegation +---- + package Conference; + use Moose; + use MooseX::AttributeHelpers; + + has attendees => ( + metaclass => 'Collection::Array', + is => 'rw', + isa => 'ArrayRef[Person]', + provides => { + push => 'add_attendee', + count => 'number_of_attendees', + }, + ); +---- + my $ppw = Conference->new( + attendees => [ $me, @all_you_guys ] + ); + + $ppw->number_of_attendees; # lots of people + $ppw->add_attendee($some_slacker); # add a late comer +---- +Method Modifiers +---- + before 'add_attendee' => sub { + my ($self, $attendee) = @_; + $self->setup_more_chairs(1); + }; +---- + after 'add_attendee' => sub { + my ($self, $attendee) = @_; + $self->log("Attendee " . $attendee->name . " added"); + }; +---- + around 'add_attendee' => sub { + my ($next, $self, @args) = @_; + ... + my @return = $self->$next(@args); + ... + return @return; + }; +---- +Roles +---- +â +---- +Classes +---- +Roles +do /not/ +inherit. +---- +Inheritance is +â +vertical reuse. +---- +Roles +compose. +---- +Composition is +â +horizontal reuse. +---- +... +---- +When +to use +Roles +---- +My general rule +of thumb is ... +---- +s/MI/Roles/g +---- +When +to /not/ use +Roles +---- +When a class +just makes +more sense. +---- +Roles are /not/ a +replacement for +inheritance. +---- +How Roles +Work +---- +Roles are +orphans. +---- +Roles are +composed. +---- +Local class +overrides role. +---- +Role overrides +inherited class. +---- +Roles can +conflict. +---- +Method conflicts +must be +disambiguated. +---- +Attribute conflicts +cannot be +disambiguated. +---- + package Age; + use Moose::Role; + + # ... all that type stuff + + has age => ( + is => 'rw', + isa => 'DateTime::Duration', + coerce => 1, + lazy => 1, + default => sub { + DateTime::Duration->new + }, + handles => { + 'years_old' => 'years' + } + ); + + 1; +---- + package Person; + use Moose; + + with 'Age'; + + # ... +---- +Conclusion +---- +Moose code is shorter +---- +less code == less bugs +---- +Less testing +needed +---- +Moose/Class::MOP +have +5400 +tests and growing +---- +Why test, when +Moose already does. +---- +More Readable +---- +Declarative code +Descriptive code +---- +The End +---- +Questions? +---- +]]></html:textarea> + +<deck flex="1" id="deck"> + +<vbox flex="1" + onmousemove="Presentation.onMouseMoveOnCanvas(event);"> + <toolbox id="canvasToolbar"> + <toolbar> + <toolbarbutton oncommand="Presentation.home()" label="|<<" + observes="canBack"/> + <toolbarbutton oncommand="Presentation.back()" label="<" + observes="canBack"/> + <toolbarbutton oncommand="Presentation.forward()" label=">" + observes="canForward"/> + <toolbarbutton oncommand="Presentation.end()" label=">>|" + observes="canForward"/> + <toolbarseparator/> + <hbox align="center"> + <textbox id="current_page" size="4" + oninput="if (this.value) Presentation.showPage(parseInt(this.value)-1);"/> + <description value="/"/> + <description id="max_page"/> + </hbox> + <toolbarseparator/> + <vbox flex="2"> + <spacer flex="1"/> + <scrollbar id="scroller" + align="center" orient="horizontal" + oncommand="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));" + onclick="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));" + onmousedown="Presentation.onScrollerDragStart();" + onmousemove="Presentation.onScrollerDragMove();" + onmouseup="Presentation.onScrollerDragDrop();"/> + <spacer flex="1"/> + </vbox> + <toolbarseparator/> + <spacer flex="1"/> + <toolbarseparator/> + <toolbarbutton id="toggleEva" label="Eva" + type="checkbox" + autoCheck="false" + oncommand="Presentation.toggleEvaMode();"/> + <toolbarseparator/> + <toolbarbutton label="Edit" + oncommand="Presentation.toggleEditMode();"/> + <toolbarbutton oncommand="Presentation.reload();" label="Reload"/> + </toolbar> + </toolbox> + <vbox flex="1" id="canvas" + onclick="Presentation.onPresentationClick(event);"> + <spacer flex="1"/> + <hbox flex="1"> + <spacer flex="1"/> + <vbox id="content"/> + <spacer flex="1"/> + </hbox> + <spacer flex="1"/> + </vbox> +</vbox> + + +<vbox flex="1" id="edit"> + <toolbox> + <toolbar> + <toolbarbutton label="New Page" + oncommand="Presentation.addPage()"/> + <spacer flex="1"/> + <toolbarseparator/> + <toolbarbutton label="View" + oncommand="Presentation.toggleEditMode();"/> + <toolbarbutton oncommand="Presentation.reload();" label="Reload"/> + </toolbar> + </toolbox> + <textbox id="textField" flex="1" multiline="true" + oninput="Presentation.onEdit()"/> + <hbox collapsed="true"> + <iframe id="dataLoader" onload="if (window.Presentation) Presentation.onDataLoad();"/> + </hbox> +</vbox> + +</deck> + + +<broadcasterset> + <broadcaster id="canBack"/> + <broadcaster id="canForward"/> +</broadcasterset> + +<commandset> + <command id="cmd_forward" + oncommand="if (Presentation.isPresentationMode) Presentation.forward();"/> + <command id="cmd_back" + oncommand="if (Presentation.isPresentationMode) Presentation.back();"/> + <command id="cmd_home" + oncommand="if (Presentation.isPresentationMode) Presentation.home();"/> + <command id="cmd_end" + oncommand="if (Presentation.isPresentationMode) Presentation.end();"/> +</commandset> +<keyset> + <key keycode="VK_ENTER" command="cmd_forward"/> + <key keycode="VK_RETURN" command="cmd_forward"/> + <key keycode="VK_PAGE_DOWN" command="cmd_forward"/> + <key keycode="VK_RIGHT" command="cmd_forward"/> + <key keycode="VK_DOWN" command="cmd_forward"/> + <!-- key keycode="VK_BACK_SPACE" command="cmd_back"/--> + <key keycode="VK_PAGE_UP" command="cmd_back"/> + <!-- <key keycode="VK_BACK_UP" command="cmd_back"/>--> + <!-- <key keycode="VK_BACK_LEFT" command="cmd_back"/>--> + <key keycode="VK_HOME" command="cmd_home"/> + <key keycode="VK_END" command="cmd_end"/> + <key key="n" modifiers="accel" oncommand="Presentation.addPage();"/> + <key key="r" modifiers="accel" oncommand="window.location.reload();"/> + <key key="e" modifiers="accel" oncommand="Presentation.toggleEditMode();"/> + <key key="a" modifiers="accel" oncommand="Presentation.toggleEvaMode();"/> +</keyset> + + +<script src="takahashi.js" type="application/x-javascript" /> +</page> +<!-- ***** BEGIN LICENSE BLOCK ***** + - Version: MPL 1.1 + - + - The contents of this file are subject to the Mozilla Public License Version + - 1.1 (the "License"); you may not use this file except in compliance with + - the License. You may obtain a copy of the License at + - http://www.mozilla.org/MPL/ + - + - Software distributed under the License is distributed on an "AS IS" basis, + - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + - for the specific language governing rights and limitations under the + - License. + - + - The Original Code is the Takahashi-Method-based Presentation Tool in XUL. + - + - The Initial Developer of the Original Code is SHIMODA Hiroshi. + - Portions created by the Initial Developer are Copyright (C) 2005 + - the Initial Developer. All Rights Reserved. + - + - Contributor(s): SHIMODA Hiroshi <piro@p.club.ne.jp> + - + - ***** END LICENSE BLOCK ***** --> + + diff --git a/PPW-2008/takahashi.css b/PPW-2008/takahashi.css new file mode 100644 index 0000000..591a815 --- /dev/null +++ b/PPW-2008/takahashi.css @@ -0,0 +1,162 @@ +@charset "UTF-8"; + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Takahashi-Method-based Presentation Tool in XUL. + * + * The Initial Developer of the Original Code is SHIMODA Hiroshi. + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): SHIMODA Hiroshi <piro@p.club.ne.jp> + * + * ***** END LICENSE BLOCK ***** */ + +#canvas { + background: black !important; + color: white !important; + /* font-weight: bold; */ + font-family: + "Georgia" + "DejaVu Serif Condensed" + "Arial" + "Bitstream Vera Sans" + "Verdana" + "Apple LiGothic" + "Arial Black" + "Bitstream Vera Sans" + sans-serif !important; +} +#canvas * { + cursor: pointer !important; +} +#canvas image { + width: auto; + height: auto; +} +.link-text { + color: #99CCFF !important; + text-decoration: none !important; +} +.link-text:hover { + color: #CCEEFF !important; +/* border-bottom: dotted 1px; */ +} +.link-text:active { + color: white !important; +} +.s { + text-decoration: line-through; +} +.iu { + text-decoration: underline; + font-style: italic; +} +.ui { +/* text-decoration: underline; */ + font-style: italic; +} +.u { + text-decoration: underline; +} +.i { + font-style: italic; + font-family: "Times New Roman" + "Bitstream Vera Serif" + serif; +} +.c { + font-family: + "Monaco" + "Andale Mono" + "Bitstream Vera Sans Mono" + monospace; +} +.t { + font-style: italic; +} +.tag { + color: #33ff33; +} +.att { + color: #9999cc; +} +.key { + color: #00ffff; +} +.hid { + color: #999999; +} +.hidt { + color: #999999; + font-style: italic; +} +.pre { + font-family: "Monaco" + "Lucida Console" + "Andale Mono" + "Bitstream Vera Sans Mono" + monospace; + padding-bottom: 8px; +} +#canvas[rendering="true"] image { + display: none; +} +#canvas[rendering="true"] *, +#canvas[rendering="true"] .text-link { + color: white !important; +} + + +tabbox, tabpanels, tabpanel { + margin: 0; + padding: 0; +} + + + + +#canvas[eva="true"] { + background: white !important; + color: black !important; + font-family: + "Georgia" + "DejaVu Serif Condensed" + "Apple LiGothic" + "Arial Black" + serif !important; +} +#canvas[eva="true"] .link-text { + color: red !important; + text-decoration: none !important; +} +#canvas[eva="true"] .link-text:hover { + color: pink !important; +} +#canvas[eva="true"] .link-text:active { + color: orange !important; +} +#canvas[rendering="true"] *, +#canvas[rendering="true"] .text-link { + color: black !important; +} + + + + +#canvasToolbar { + position: relative; +} + +.smallfont { font-size: 20pt; } \ No newline at end of file diff --git a/PPW-2008/takahashi.js b/PPW-2008/takahashi.js new file mode 100644 index 0000000..c5d6933 --- /dev/null +++ b/PPW-2008/takahashi.js @@ -0,0 +1,503 @@ +var Presentation = { + init : function(option){ + this.size = 9; + + this._offset = 0; + this.canvas = document.getElementById('canvas'); + this.content = document.getElementById('content'); + this.textbox = document.getElementById('textField'); + this.deck = document.getElementById('deck'); + this.scroller = document.getElementById('scroller'); + + this.toolbar = document.getElementById('canvasToolbar'); + this.toolbarHeight = this.toolbar.boxObject.height; + this.isToolbarHidden = true; + this.toolbar.setAttribute('style', 'margin-top:'+(0-this.toolbarHeight)+'px;margin-bottom:0px;'); + + if(option){ + for(var i in option){this[i] = option[i]} + } + + if (this.readParameter()) { + this.takahashi(); + } + + document.documentElement.focus(); + }, + + takahashi : function(){ + if (!document.title) + document.title = this.data[0].replace(/[\r\n]/g, ' '); + + if(!this.data[this.offset]){ + this.offset = this.data.length-1; + } + document.getElementById("current_page").value = this.offset+1; + document.getElementById("max_page").value = this.data.length; + + this.scroller.setAttribute('maxpos', this.data.length-1); + this.scroller.setAttribute('curpos', this.offset); + + var broadcaster = document.getElementById('canBack'); + if (!this.offset) + broadcaster.setAttribute('disabled', true); + else + broadcaster.removeAttribute('disabled'); + + var broadcaster = document.getElementById('canForward'); + if (this.offset == this.data.length-1) + broadcaster.setAttribute('disabled', true); + else + broadcaster.removeAttribute('disabled'); + + this.canvas.setAttribute('rendering', true); + + var text = this.data[this.offset]. + replace(/^[\r\n]+/g,"").replace(/[\r\n]+$/g,"").replace(/(\r\n|[\r\n])/g,"\n") + .split('\n'); + var range = document.createRange(); + range.selectNodeContents(this.content); + range.deleteContents(); + range.detach(); + + var line; + var newLine; + var uri; + var image_width; + var image_total_width = 0; + var image_height; + var image_total_height = 0; + var image_src; + var code_listing = 0; + + + var labelId = 0; + + for (var i = 0; i < text.length; i++) + { + this.content.appendChild(document.createElement('hbox')); + this.content.lastChild.setAttribute('align', 'center'); + this.content.lastChild.setAttribute('pack', 'center'); + + line = text[i]; + image_width = 0; + image_height = 0; + + if (line.match(/^ /)) { + code_listing = 1; + this.content.lastChild.setAttribute('align', 'left'); + this.content.lastChild.setAttribute('class', 'pre'); + line = line.substring(1) + } + + while (line.match(/^([^\{]+)?(\{\{ima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^\}]*\}\}|\{\{(([^\|]+)?\||)([^\}]+)\}\})(.+)?/)) + { + if (RegExp.$1) { + this.content.lastChild.appendChild(document.createElement('description')); + this.content.lastChild.lastChild.setAttribute('value', RegExp.$1); + } + newLine = line.substring((RegExp.$1+RegExp.$2).length); + + // Images + if (/^([^\{]+)?\{\{ima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^\}]*\}\}/.test(line)) { + this.content.lastChild.appendChild(document.createElement('image')); + image_src = RegExp.$2; + if (image_src.indexOf('http://') < 0 && + image_src.indexOf('https://') < 0) + image_src = this.dataFolder+image_src; + this.content.lastChild.lastChild.setAttribute('src', image_src); + this.content.lastChild.lastChild.setAttribute('width', parseInt(RegExp.$3 || '0')); + this.content.lastChild.lastChild.setAttribute('height', parseInt(RegExp.$4 || '0')); + image_width += parseInt(RegExp.$3 || '0'); + image_height = Math.max(image_height, parseInt(RegExp.$4 || '0')); + } + + // Styles + // else if (/^([^\{]+)?\{\{#([^\|]+)\|([^\}]+)\}\}/.test(line)) { + else if (/^([^\{]+)?\{\{(#([^\|]+)?\|)([^\}]+)\}\}/.test(line)) { + uri = RegExp.$4; + this.content.lastChild.appendChild(document.createElement('description')); + this.content.lastChild.lastChild.setAttribute('value', uri); + this.content.lastChild.lastChild.setAttribute('class', RegExp.$3); + } + + // Links + else if (/^([^\{]+)?\{\{(([^\|]+)?\||)([^\}]+)\}\}/.test(line)) { + uri = RegExp.$4; + if (uri.indexOf('://') < 0) + uri = this.dataFolder+uri; + this.content.lastChild.appendChild(document.createElement('description')); + this.content.lastChild.lastChild.setAttribute('value', RegExp.$3 || RegExp.$4); + this.content.lastChild.lastChild.setAttribute('href', uri); + this.content.lastChild.lastChild.setAttribute('tooltiptext', uri); + this.content.lastChild.lastChild.setAttribute('statustext', uri); + this.content.lastChild.lastChild.setAttribute('class', 'link-text'); + } + + line = newLine; + } + + if (line) { + this.content.lastChild.appendChild(document.createElement('description')); + this.content.lastChild.lastChild.setAttribute('value', line); + } + + image_total_width = Math.max(image_total_width, image_width); + image_total_height += image_height; + } + + this.content.setAttribute('style', 'font-size:10px;'); + + if (this.content.boxObject.width) { + var canvas_w = this.canvas.boxObject.width; + var canvas_h = this.canvas.boxObject.height-image_total_height; + + var content_w = this.content.boxObject.width; + var new_fs = Math.round((canvas_w/content_w) * this.size); + + new_fs = new_fs - (new_fs % 32); + if (code_listing) { new_fs = 48;} + + this.content.setAttribute('style', 'top: 0'); + this.content.setAttribute('style', 'font-size:'+ new_fs + "px"); + + if (this.content.boxObject.width < image_total_width) { + content_w = image_total_width; + new_fs = Math.round((canvas_w/content_w) * this.size); + this.content.setAttribute('style', 'font-size:'+ new_fs + "px"); + } + + var content_h = this.content.boxObject.height; + if(content_h >= canvas_h){ + content_h = this.content.boxObject.height; + new_fs = Math.round((canvas_h/content_h) * new_fs); + this.content.setAttribute('style', 'font-size:'+ new_fs + "px"); + } + } + + + + this.canvas.removeAttribute('rendering'); + }, + + reload : function() { + if (this.dataPath != location.href) { + var path = this.dataPath; + if (location.href.match(/^https?:/)) { + var request = new XMLHttpRequest(); + request.open('GET', path); + request.onload = function() { + Presentation.textbox.value = request.responseText; + Presentation.data = Presentation.textbox.value.split('----'); + + Presentation.takahashi(); + + path = null; + request = null; + }; + request.send(null); + } + else { + document.getElementById('dataLoader').setAttribute('src', 'about:blank'); + window.setTimeout(function() { + document.getElementById('dataLoader').setAttribute('src', path); + path = null; + }, 10); + } + } + else + window.location.reload(); + }, + + forward : function(){ + this.offset++; + this.takahashi(); + }, + back : function(){ + this.offset--; + if(this.offset < 0){this.offset = 0} + this.takahashi(); + }, + home : function(){ + this.offset = 0; + this.takahashi(); + }, + end : function(){ + this.offset = this.data.length-1; + this.takahashi(); + }, + showPage : function(aPageOffset){ + this.offset = aPageOffset ? aPageOffset : 0 ; + this.takahashi(); + }, + + addPage : function() { + if (this.textbox.value && + !this.textbox.value.match(/(\r\n|[\r\n])$/)) + this.textbox.value += '\n'; + this.textbox.value += '----\n'; + this.onEdit(); + }, + + toggleEditMode : function(){ + this.deck.selectedIndex = (this.deck.selectedIndex == 0) ? 1 : 0 ; + }, + toggleEvaMode : function(){ + var check = document.getElementById('toggleEva'); + if (this.canvas.getAttribute('eva') == 'true') { + this.canvas.removeAttribute('eva'); + check.checked = false; + } + else { + this.canvas.setAttribute('eva', true); + check.checked = true; + } + }, + + onPresentationClick : function(aEvent){ + if (!this.isToolbarHidden) + this.showHideToolbar(); + + switch(aEvent.button) + { + case 0: + var uri = aEvent.target.getAttribute('href'); + if (uri) + window.open(uri); + else { + this.forward(); + document.documentElement.focus(); + } + break; + case 2: + this.back(); + document.documentElement.focus(); + break; + default: + break; + } + }, + onScrollerDragStart : function(){ + this.scroller.dragging = true; + }, + onScrollerDragMove : function(){ + if (this.scroller.dragging) + this.showPage(parseInt(this.scroller.getAttribute('curpos'))); + }, + onScrollerDragDrop : function(){ + if (this.scroller.dragging) { + this.showPage(parseInt(this.scroller.getAttribute('curpos'))); + } + this.scroller.dragging = false; + }, + onEdit : function() { + this.data = this.textbox.value.split('----'); + this.takahashi(); + }, + + onKeyPress : function(aEvent) { + switch(aEvent.keyCode) + { + case aEvent.DOM_VK_BACK_SPACE: + if (this.isPresentationMode) { + aEvent.preventBubble(); + aEvent.preventDefault(); + Presentation.back(); + } + break; + default: + break; + } + }, + + + onToolbarArea : false, + toolbarHeight : 0, + toolbarDelay : 300, + toolbarTimer : null, + isToolbarHidden : false, + onMouseMoveOnCanvas : function(aEvent) { + if (this.scroller.dragging) return; + + this.onToolbarArea = (aEvent.clientY < this.toolbarHeight); + + if (this.isToolbarHidden == this.onToolbarArea) { + if (this.toolbarTimer) window.clearTimeout(this.toolbarTimer); + this.toolbarTimer = window.setTimeout('Presentation.onMouseMoveOnCanvasCallback()', this.toolbarDelay); + } + }, + onMouseMoveOnCanvasCallback : function() { + if (this.isToolbarHidden == this.onToolbarArea) + this.showHideToolbar(); + }, + + toolbarAnimationDelay : 100, + toolbarAnimationSteps : 5, + toolbarAnimationInfo : null, + toolbarAnimationTimer : null, + showHideToolbar : function() + { + if (this.toolbarAnimationTimer) window.clearTimeout(this.toolbarAnimationTimer); + + this.toolbarAnimationInfo = { count : 0 }; + if (this.isToolbarHidden) { + this.toolbarAnimationInfo.start = 0; + this.toolbarAnimationInfo.end = this.toolbarHeight; + } + else { + this.toolbarAnimationInfo.start = this.toolbarHeight; + this.toolbarAnimationInfo.end = 0; + } + this.toolbarAnimationInfo.current = 0; + + this.toolbar.setAttribute('style', 'margin-top:'+(0-(this.toolbarHeight-this.toolbarAnimationInfo.start))+'px; margin-bottom:'+(0-this.toolbarAnimationInfo.start)+'px;'); + + this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps); + }, + animateToolbar : function() + { + this.toolbarAnimationInfo.current += parseInt(this.toolbarHeight/this.toolbarAnimationSteps); + + var top, bottom; + if (this.toolbarAnimationInfo.start < this.toolbarAnimationInfo.end) { + top = this.toolbarHeight-this.toolbarAnimationInfo.current; + bottom = this.toolbarAnimationInfo.current; + } + else { + top = this.toolbarAnimationInfo.current; + bottom = this.toolbarHeight-this.toolbarAnimationInfo.current; + } + + top = Math.min(Math.max(top, 0), this.toolbarHeight); + bottom = Math.min(Math.max(bottom, 0), this.toolbarHeight); + + this.toolbar.setAttribute('style', 'margin-top:'+(0-top)+'px; margin-bottom:'+(0-bottom)+'px'); + + if (this.toolbarAnimationInfo.count < this.toolbarAnimationSteps) { + this.toolbarAnimationInfo.count++; + this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps); + } + else + this.isToolbarHidden = !this.isToolbarHidden; + }, + + + + get offset(){ + return this._offset; + }, + set offset(aValue){ + this._offset = parseInt(aValue || 0); + document.documentElement.setAttribute('lastoffset', this.offset); + return this.offset; + }, + + get data(){ + if (!this._data) { + // Make sure you break the text into parts smaller than 4096 + // characters, and name them as indicated. Tweak as required. + // (What a hack. A JS programmer should find a better way.) + // Luc St-Louis, and email is lucs@pobox.com. + + nodes = document.getElementById('builtinCode').childNodes; + content = ''; + for (i in nodes) { + if (nodes[i].nodeValue) { + content = content + nodes[i].nodeValue; + } + } + + this._data = content.split("----"); + } + + return this._data; + }, + set data(aValue){ + this._data = aValue; + return aValue; + }, + + + get isPresentationMode(){ + return (this.deck.selectedIndex == 0); + }, + + + get dataPath(){ + if (!this._dataPath) + this.dataPath = location.href; + return this._dataPath; + }, + set dataPath(aValue){ + var oldDataPath = this._dataPath; + this._dataPath = aValue; + if (oldDataPath != aValue) { + this._dataFolder = this._dataPath.split('?')[0].replace(/[^\/]+$/, ''); + } + return this._dataPath; + }, + + get dataFolder(){ + if (!this._dataFolder) + this.dataPath = this.dataPath; + return this._dataFolder; + }, + set dataFolder(aValue){ + this._dataFolder = aValue; + return this._dataFolder; + }, + + readParameter : function() { + if (location.search) { + var param = location.search.replace(/^\?/, ''); + + if (param.match(/page=([0-9]+)/i)) + this.offset = parseInt(RegExp.$1)-1; + + if (param.match(/edit=(1|true|yes)/i)) + this.toggleEditMode(); + + if (param.match(/eva=(1|true|yes)/i)) + this.toggleEvaMode(); + + if (param.match(/data=([^&;]+)/i)) { + var path = unescape(RegExp.$1); + this.dataPath = path; + if (location.href.match(/^https?:/)) { + var request = new XMLHttpRequest(); + request.open('GET', path); + request.onload = function() { + Presentation.textbox.value = request.responseText; + Presentation.data = Presentation.textbox.value.split('----'); + + Presentation.takahashi(); + }; + request.send(null); + } + else { + document.getElementById('dataLoader').setAttribute('src', path); + } + return false; + } + } + return true; + }, + onDataLoad : function() { + if (!window.frames[0].document.body.hasChildNodes()) return; + var data = window.frames[0].document.body.firstChild.innerHTML; + if (!data) return; + + this.textbox.value = data; + this.data = this.textbox.value.split('----'); + + this.takahashi(); + } +}; + +function init() +{ + window.removeEventListener('load', init, false); + + Presentation.init(); +} +window.addEventListener('load', init, false); diff --git a/PTPW_2008/porn/4581xiyi01.jpg b/PTPW_2008/porn/4581xiyi01.jpg new file mode 100644 index 0000000..52369aa Binary files /dev/null and b/PTPW_2008/porn/4581xiyi01.jpg differ diff --git a/PTPW_2008/porn/Picture 6.png b/PTPW_2008/porn/Picture 6.png new file mode 100644 index 0000000..2a29c5d Binary files /dev/null and b/PTPW_2008/porn/Picture 6.png differ diff --git a/PTPW_2008/porn/Picture 8.png b/PTPW_2008/porn/Picture 8.png new file mode 100644 index 0000000..4e38f47 Binary files /dev/null and b/PTPW_2008/porn/Picture 8.png differ diff --git a/PTPW_2008/porn/Picture 9.png b/PTPW_2008/porn/Picture 9.png new file mode 100644 index 0000000..8dc6015 Binary files /dev/null and b/PTPW_2008/porn/Picture 9.png differ diff --git a/PTPW_2008/porn/beer.jpg b/PTPW_2008/porn/beer.jpg new file mode 100644 index 0000000..79a5082 Binary files /dev/null and b/PTPW_2008/porn/beer.jpg differ diff --git a/PTPW_2008/porn/blood.jpg b/PTPW_2008/porn/blood.jpg new file mode 100644 index 0000000..cb31ce1 Binary files /dev/null and b/PTPW_2008/porn/blood.jpg differ diff --git a/PTPW_2008/porn/chamonix.jpg b/PTPW_2008/porn/chamonix.jpg new file mode 100644 index 0000000..7905aa4 Binary files /dev/null and b/PTPW_2008/porn/chamonix.jpg differ diff --git a/PTPW_2008/porn/clkao.jpg b/PTPW_2008/porn/clkao.jpg new file mode 100644 index 0000000..8d78c54 Binary files /dev/null and b/PTPW_2008/porn/clkao.jpg differ diff --git a/PTPW_2008/porn/cog.jpg b/PTPW_2008/porn/cog.jpg new file mode 100644 index 0000000..1764d83 Binary files /dev/null and b/PTPW_2008/porn/cog.jpg differ diff --git a/PTPW_2008/porn/duck_head.jpg b/PTPW_2008/porn/duck_head.jpg new file mode 100644 index 0000000..131e9a0 Binary files /dev/null and b/PTPW_2008/porn/duck_head.jpg differ diff --git a/PTPW_2008/porn/food.jpg b/PTPW_2008/porn/food.jpg new file mode 100644 index 0000000..49d7869 Binary files /dev/null and b/PTPW_2008/porn/food.jpg differ diff --git a/PTPW_2008/porn/glasses.jpg b/PTPW_2008/porn/glasses.jpg new file mode 100644 index 0000000..6e52ea7 Binary files /dev/null and b/PTPW_2008/porn/glasses.jpg differ diff --git a/PTPW_2008/porn/glasses_no.jpg b/PTPW_2008/porn/glasses_no.jpg new file mode 100644 index 0000000..5799468 Binary files /dev/null and b/PTPW_2008/porn/glasses_no.jpg differ diff --git a/PTPW_2008/porn/hackathon.jpg b/PTPW_2008/porn/hackathon.jpg new file mode 100644 index 0000000..c1d4972 Binary files /dev/null and b/PTPW_2008/porn/hackathon.jpg differ diff --git a/PTPW_2008/porn/hunting.jpg b/PTPW_2008/porn/hunting.jpg new file mode 100644 index 0000000..750a279 Binary files /dev/null and b/PTPW_2008/porn/hunting.jpg differ diff --git a/PTPW_2008/porn/intestines.jpg b/PTPW_2008/porn/intestines.jpg new file mode 100644 index 0000000..bf89350 Binary files /dev/null and b/PTPW_2008/porn/intestines.jpg differ diff --git a/PTPW_2008/porn/jetpack.jpg b/PTPW_2008/porn/jetpack.jpg new file mode 100644 index 0000000..e9a0df3 Binary files /dev/null and b/PTPW_2008/porn/jetpack.jpg differ diff --git a/PTPW_2008/porn/kitchen.jpg b/PTPW_2008/porn/kitchen.jpg new file mode 100644 index 0000000..5ca34f3 Binary files /dev/null and b/PTPW_2008/porn/kitchen.jpg differ diff --git a/PTPW_2008/porn/laundry.jpg b/PTPW_2008/porn/laundry.jpg new file mode 100644 index 0000000..979c12f Binary files /dev/null and b/PTPW_2008/porn/laundry.jpg differ diff --git a/PTPW_2008/porn/moose_danger.jpg b/PTPW_2008/porn/moose_danger.jpg new file mode 100644 index 0000000..23dfb53 Binary files /dev/null and b/PTPW_2008/porn/moose_danger.jpg differ diff --git a/PTPW_2008/porn/mousse.jpg b/PTPW_2008/porn/mousse.jpg new file mode 100644 index 0000000..fd327c2 Binary files /dev/null and b/PTPW_2008/porn/mousse.jpg differ diff --git a/PTPW_2008/porn/office.jpg b/PTPW_2008/porn/office.jpg new file mode 100644 index 0000000..010f660 Binary files /dev/null and b/PTPW_2008/porn/office.jpg differ diff --git a/PTPW_2008/porn/orz.jpg b/PTPW_2008/porn/orz.jpg new file mode 100644 index 0000000..5780cb0 Binary files /dev/null and b/PTPW_2008/porn/orz.jpg differ diff --git a/PTPW_2008/porn/phone.jpg b/PTPW_2008/porn/phone.jpg new file mode 100644 index 0000000..f1d9284 Binary files /dev/null and b/PTPW_2008/porn/phone.jpg differ diff --git a/PTPW_2008/porn/phone_no.jpg b/PTPW_2008/porn/phone_no.jpg new file mode 100644 index 0000000..3bc9742 Binary files /dev/null and b/PTPW_2008/porn/phone_no.jpg differ diff --git a/PTPW_2008/porn/stinkytofu.jpg b/PTPW_2008/porn/stinkytofu.jpg new file mode 100644 index 0000000..32a42f7 Binary files /dev/null and b/PTPW_2008/porn/stinkytofu.jpg differ diff --git a/PTPW_2008/porn/tokyo.jpg b/PTPW_2008/porn/tokyo.jpg new file mode 100644 index 0000000..8e9da0d Binary files /dev/null and b/PTPW_2008/porn/tokyo.jpg differ diff --git a/PTPW_2008/porn/tokyo_crazy.jpg b/PTPW_2008/porn/tokyo_crazy.jpg new file mode 100644 index 0000000..d8e62ef Binary files /dev/null and b/PTPW_2008/porn/tokyo_crazy.jpg differ diff --git a/PTPW_2008/porn/tubes.jpg b/PTPW_2008/porn/tubes.jpg new file mode 100644 index 0000000..ac0a962 Binary files /dev/null and b/PTPW_2008/porn/tubes.jpg differ diff --git a/PTPW_2008/porn/uni.jpg b/PTPW_2008/porn/uni.jpg new file mode 100644 index 0000000..057a12d Binary files /dev/null and b/PTPW_2008/porn/uni.jpg differ diff --git a/PTPW_2008/porn/visa.jpg b/PTPW_2008/porn/visa.jpg new file mode 100644 index 0000000..8f0cc2d Binary files /dev/null and b/PTPW_2008/porn/visa.jpg differ diff --git a/PTPW_2008/porn/visa_no.jpg b/PTPW_2008/porn/visa_no.jpg new file mode 100644 index 0000000..ef95f47 Binary files /dev/null and b/PTPW_2008/porn/visa_no.jpg differ diff --git a/PTPW_2008/porn/vomit.jpg b/PTPW_2008/porn/vomit.jpg new file mode 100644 index 0000000..d9a1c51 Binary files /dev/null and b/PTPW_2008/porn/vomit.jpg differ diff --git a/PTPW_2008/porn/zipbox.jpg b/PTPW_2008/porn/zipbox.jpg new file mode 100644 index 0000000..1819f0b Binary files /dev/null and b/PTPW_2008/porn/zipbox.jpg differ diff --git a/PTPW_2008/practical_moose.html b/PTPW_2008/practical_moose.html new file mode 100644 index 0000000..e731ac7 --- /dev/null +++ b/PTPW_2008/practical_moose.html @@ -0,0 +1,1453 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + +<head> +<title>Moose</title> +<!-- metadata --> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> +<meta name="generator" content="TextMate/S5" /> +<meta name="version" content="S5 1.2a2" /> +<meta name="presdate" content="2008" /> +<meta name="author" content="Yuval Kogman" /> +<meta name="company" content="" /> +<!-- configuration parameters --> +<meta name="defaultView" content="slideshow" /> +<meta name="controlVis" content="visible" /> +<!-- style sheet links --> +<link rel="stylesheet" href="./ui/moose/slides.css" type="text/css" media="projection" id="slideProj" /> +<link rel="stylesheet" href="./ui/moose/outline.css" type="text/css" media="screen" id="outlineStyle" /> +<link rel="stylesheet" href="./ui/moose/print.css" type="text/css" media="print" id="slidePrint" /> +<link rel="stylesheet" href="./ui/moose/opera.css" type="text/css" media="projection" id="operaFix" /> +<!-- embedded styles --> +<style type="text/css" media="all"> +.imgcon {width: 525px; margin: 0 auto; padding: 0; text-align: center;} +#anim {width: 270px; height: 320px; position: relative; margin-top: 0.5em;} +#anim img {position: absolute; top: 42px; left: 24px;} +img#me01 {top: 0; left: 0;} +img#me02 {left: 23px;} +img#me04 {top: 44px;} +img#me05 {top: 43px;left: 36px;} +</style> +<!-- S5 JS --> +<script src="./ui/moose/slides.js" type="text/javascript"></script> +</head> +<body> + +<div class="layout"> +<div id="controls"><!-- DO NOT EDIT --></div> +<div id="currentSlide"><!-- DO NOT EDIT --></div> +<div id="header"></div> +<div id="footer"> +<h1>YAPC::Asia::2008</h1> +<h2>Moose</h2> +</div> +<div class="topleft"></div> +<div class="topright"></div> +<div class="bottomleft"></div> +<div class="bottomright"></div> +</div> + +<div class="presentation"> + +<div class="slide"> +<h1>Moose</h1> +<h2></h2> +<h3>Yuval Kogman</h3> +<h4></h4> +</div> + + +<div class="slide"> +<h1>HAI FRENDS</h1> + +<ul> +<li>My name is Yuval</li> +</ul> + +</div> + +<div class="slide"> +<h1>WHY AM I HERE?</h1> + +</div> + +<div class="slide"> +<p><img src="porn/cog.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/chamonix.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/clkao.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/office.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/kitchen.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/blood.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/intestines.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/duck_head.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/stinkytofu.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/hunting.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/tokyo.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/tokyo_crazy.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/uni.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/vomit.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/phone.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/phone_no.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/glasses.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/glasses_no.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/visa.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/visa_no.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/orz.jpg" style="height: 50%"></p> + +<p><span style="font-family: sans-serif; font-weight: bold; font-size: 3em">orz orz orz </span></p> + +</div> + +<div class="slide"> +<p><img src="porn/cog.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/tubes.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/jetpack.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/food.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/mousse.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/beer.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/zipbox.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<p><img src="porn/laundry.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<h1>So here I am</h1> + +<ul> +<li>Anywayâ¦</li> +</ul> + +</div> + +<div class="slide"> +<h1>Moose</h1> + +<p><img src="porn/moose_danger.jpg" style="height: 75%"></p> + +</div> + +<div class="slide"> +<h1>Moose Is Not</h1> + +<ul> +<li>Experimental</li> +<li>A toy</li> +<li>Just another accessor builder</li> +<li>A source filter</li> +<li>Perl black magic</li> +<li>Perl 6 in Perl 5</li> +</ul> + +</div> + +<div class="slide"> +<h1>Moose Is</h1> + +<ul> +<li><a href="http://moose.perl.org">http://moose.perl.org</a></li> +<li>A complete modern object framework for Perl</li> +</ul> + +</div> + +<div class="slide"> +<h1>Moose Is</h1> + +<ul> +<li>Syntactic Sugar for <code>Class::MOP</code></li> +<li>Rich ancestry +<ul> +<li>CLOS (Common Lisp Object System)</li> +<li>Smalltalk</li> +<li>Alces latifrons</li> +<li>Perl 6</li> +<li>â¦</li> +</ul></li> +<li>Stable & Production ready</li> +<li>Polite, incremental</li> +</ul> + +</div> + +<div class="slide"> +<h1>A Simple Example</h1> + +<pre><code> +package Person; + +use strict; +use warnings; + +sub new { + my ( $class, @args ) = @_; + + @args = %{$args[0]} if @args == 1; + + return bless { + @args, + }, $class; +} + +sub name { + my ($self, @args) = @_; + $self->{name} = $args[0] if @args; + return $self->{name}; +} + +sub age { + my ($self, @args) = @_; + $self->{age} = $args[0] if @args; + return $self->{age}; +} + +1; +</code></pre> + +</div> + +<div class="slide"> +<h1>A Simple Moose Example</h1> + +<pre><code> +package Person; +use Moose; + +has name => (is => 'rw'); +has age => (is => 'rw'); + +1; +</code></pre> + +</div> + +<div class="slide"> +<h1>A Simple Moose Example (cont.)</h1> + +<ul> +<li><code>use Moose;</code> +<ul> +<li>imports keywords</li> +<li><code>use strict; use warnings;</code></li> +<li><code>@ISA = qw(Moose::Object) unless @ISA</code></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>A Simple Moose Example (cont.)</h1> + +<ul> +<li><p><code>has</code> declares attributes</p> + +<ul> +<li>generates accessors</li> +<li><code>is => 'rw'</code> â read/write accessor</li> +<li><code>is => 'ro'</code> â read only accessor</li> +<li><code>writer</code>, <code>reader</code></li> +</ul></li> +<li><p><code>new</code> inherited from <code>Moose::Object</code></p></li> +</ul> + +<div class="notes"> +<p>Now we’re going to discuss more features of the attributes</p> +</div> +</div> + +<div class="slide"> +<h1>Variations on a Moose Example</h1> + +<pre><code> +package Manager; +use Moose; + +has name => ( + is => 'rw', + isa => 'Str', + default => 'Bob' +); + +has staff => ( + is => 'ro', + isa => 'ArrayRef', + lazy => 1, + default => sub { [qw(Bob Alice Tim)] }, +); +</code></pre> + +<div class="notes"> +<p>Adds default, isa</p> +</div> +</div> + +<div class="slide"> +<h1>Variations on a Moose Example (cont.)</h1> + +<ul> +<li><p><code>default</code> is a</p> + +<ul> +<li>code reference</li> +<li>or non-reference (numbers, strings)</li> +<li>used when no parameter is given to <code>new</code></li> +</ul></li> +<li><p><code>lazy</code> delays <code>default</code></p> + +<ul> +<li>called on first usage of <code>$object->staff</code></li> +<li>not inside <code>new</code></li> +</ul></li> +</ul> + +<div class="notes"> +<p>discusses default</p> + +<p>non refs make accidental sharing hard</p> +</div> +</div> + +<div class="slide"> +<h1>Variations on a Moose Example (cont.)</h1> + +<ul> +<li><code>isa</code> specifies a type +<ul> +<li><code>Moose::Util::TypeConstraints</code> +<ul> +<li><code>Any, Item, Bool, Undef, Defined, Value, Num, Int, Str, Ref, ScalarRef, ArrayRef, HashRef, CodeRef, RegexpRef, GlobRef, FileHandle, Object and Role</code></li> +</ul></li> +<li>Types don’t need to exist</li> +</ul></li> +</ul> + +<pre><code> + has 'date' => (isa => 'DateTime'); # DWIM +</code></pre> + +<div class="notes"> +<p>isa, type constraints</p> +</div> +</div> + +<div class="slide"> +<h1>Typical Family</h1> + +<ul> +<li>Types have a hierarchy +<ul> +<li><code>Item</code> â <code>Defined</code> â <code>Ref</code> â <code>Object</code></li> +</ul></li> +</ul> + +<pre><code> + subtype 'Ref' + => as 'Defined' + => where { ref($_) }; + + subtype 'Object' + => as 'Ref' + => where { blessed($_) } +</code></pre> + +<div class="notes"> +<p>type hierarchy</p> +</div> +</div> + +<div class="slide"> +<h1>Conventional Delegates</h1> + +<pre><code> +package Employee; +use Moose; +extends qw(Person); + +has manager => ( + is => 'ro', + isa => 'Manager', + handles => { + manager_name => 'name', + coworkers => 'staff', + } +); +</code></pre> + +<ul> +<li>manager <code>handles</code> certain methods for <code>Employee</code> +<ul> +<li><code>$emp->coworkers</code> == <code>$emp->manager->staff</code></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Conventional Delegates (cont.)</h1> + +<pre><code> +has phone => ( + ... + handles => [qw(number extension)], +); +</code></pre> + +</div> + +<div class="slide"> +<h1>Conventional Delegates (cont.)</h1> + +<pre><code> +has phone => ( + ... + isa => "Phone", + handles => qr/^[a-z]w+$/, +); +</code></pre> + +</div> + +<div class="slide"> +<h1>Conventional Delegates (cont.)</h1> + +<pre><code> +has phone => ( + ... + handles => "Dialing", # a role +); +</code></pre> + +</div> + +<div class="slide"> +<h1>UnConventional Delegates</h1> + +<pre><code> +package Company; +use Moose; +use MooseX::AttributeHelpers; + +has employees => ( + metaclass => 'Collection::Array', + isa => 'ArrayRef[Employees]', + is => 'rw', + provides => { + push => 'add_employee', + pop => 'remove_employee', + count => 'number_of_employees', + empty => 'any_employees', + }, +); +</code></pre> + +</div> + +<div class="slide"> +<h1>Modified Methods</h1> + +<pre><code> +before 'employees' => sub { warn 'calling employees' }; + +after 'employees' => sub { warn 'finished calling employees' }; +</code></pre> + +<ul> +<li>Pre/Post hooks +<ul> +<li>Get a copy of <code>@_</code></li> +<li>Return value is ignored</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Modified Methods (cont.)</h1> + +<pre><code> +around 'employees' => sub { + my ($next, $self, @args) = @_; + ... + my @return = $self->$next(@args); + ... + return @return; +}; +</code></pre> + +</div> + +<div class="slide"> +<h1>Modified Methods (cont.)</h1> + +<pre><code> +package Employee; +use Moose; + +sub do_work { + my $self = shift; + + $self->punch_in; + + inner(); # call subclass here + + $self->punch_out; +} +</code></pre> + +</div> + +<div class="slide"> +<h1>Modified Methods (cont.)</h1> + +<pre><code> +package Employee::Chef; +use Moose; + +extends qw(Employee); + +augment do_work => sub { + my $self = shift; + + while ( @burgers ) { + $self->flip_burger(shift @burgers); + } +}; + +$chef->do_work; # punch in, flip burgers, punch out +</code></pre> + +</div> + +<div class="slide"> +<h1>Some Type of Coercion</h1> + +<pre><code> +package Employee; +use Moose; +use Moose::Util::TypeConstraints; +extends qw(Person); + +class_type 'Manager'; + +coerce 'Manager' => ( + from 'Str' => via { Manager->new( name => $_ ) }, +); + +has manager => ( + is => 'ro', + isa => 'Manager', + required => 1, + coerce => 1, +); +</code></pre> + +</div> + +<div class="slide"> +<h1>Some Type of Coercion (cont.)</h1> + +<pre><code> +# import type constraint keywords +use Moose::Util::TypeConstraints; + + +# define Manager, a subtype of Object +class_type "Manager"; + + +# define the conversion +... via { Manager->new( name => $_ ) } + + +# enable it per attribute +has manager => ( + ... + coerce => 1, +); +</code></pre> + +<div class="notes"> +<p>breakdown of the example</p> + +<p>class types are automatically created for all Moose classes</p> +</div> +</div> + +<div class="slide"> +<h1>Some Type of Digression</h1> + +<pre><code> +has employees => ( + is => 'rw', + isa => 'ArrayRef[Employee]', +); + +has shopping_carts => ( + is => 'rw', + isa => 'ArrayRef[ArrayRef[ShinyBead]]' +); +</code></pre> + +<div class="notes"> +<p>Going to go into features of the type system for a bit</p> + +<p>Parametrized types</p> +</div> +</div> + +<div class="slide"> +<h1>Some Type of Digression (cont.)</h1> + +<pre><code> +has language => ( + is => 'rw', + isa => 'English | Welsh | Scots | Gaelic', +); + +has member => ( + is => 'rw', + isa => 'Employee | ArrayRef[ Employee | Group ]', +); +</code></pre> + +<div class="notes"> +<p>Union types</p> +</div> +</div> + +<div class="slide"> +<h1>Some Type of Digression (cont.)</h1> + +<pre><code> +package Foo; +use Moose; +use Moose::Util::TypeConstraints; + +use Test::Deep qw(eq_deeply ...); + +type 'SomethingTricky' => where { + eq_deeply( $_, ... ); +}; + +has 'bar' => ( + is => 'rw', + isa => 'SomethingTricky', +); +</code></pre> + +<div class="notes"> +<p>Test::Deep custom validator</p> + +<p>Can use any validation from the CPAN</p> +</div> +</div> + +<div class="slide"> +<h1>Some Parametrized Type of Coercion</h1> + +<pre><code> +use Moose::Util::TypeConstraints; + +subtype 'ArrayRef[Employee]' => as 'ArrayRef'; + +coerce 'ArrayRef[Employee]' => ( + from 'ArrayRef[Str]' via { + [ map { Employee->new( name => $_ ) } @$_ ] + }, +); + +has staff => ( + isa => 'ArrayRef[Employee]', + coerce => 1, +); +</code></pre> + +<div class="notes"> +<p>coerce parametrized ArrayRef[Employee] from ArrayRef[Str]</p> +</div> +</div> + +<div class="slide"> +<h1>Role of the Moose </h1> + +<ul> +<li>A role is like a⦠+<ul> +<li>Java Interface: safe</li> +<li>mixin: useful</li> +</ul></li> +<li>A role is for small reusable behaviors +<ul> +<li>better than using a multiple inheritence</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<ul> +<li>Roles on the CPAN: +<ul> +<li><code>MooseX::Clone</code> - Flexible <code>clone</code> method</li> +<li><code>MooseX::Storage</code> - Flexible serialization</li> +<li><code>MooseX::Getopt</code> - <code>@ARGV</code> aware constructor</li> +<li><code>MooseX::LogDispatch</code> - <code>$self->logger->info("something happenned")</code></li> +<li><code>MooseX::Param</code> - <code>param</code> method like <code>CGI.pm</code>’s,</li> +</ul></li> +</ul> + +<div class="notes"> +<p>Some examples of small reusable behaviors</p> + +<p>Param is good for interacting with e.g. CGI::Expand or similar modules</p> +</div> +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<pre><code> +package Minion; +use Moose; + +extends qw(Employee); + +with qw(Salaried::Hourly); + + +package Boss; +use Moose; + +extends qw(Employee); + +with qw(Salaried::Monthly); + +</code></pre> + +<ul> +<li><code>with</code> adds roles into your class +<ul> +<li><code>Salaried::Hourly</code> was added to <code>Minion</code></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<pre><code> +package Salaried; +use Moose::Role; + +requires 'paycheck_amount'; +</code></pre> + +<ul> +<li>Just an interface</li> +</ul> + +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<pre><code> +package Salaried::Hourly; +use Moose::Role; + +with qw(Salaried); + +has hourly_rate => ( + isa => "Num", + is => "rw", + required => 1, +); + +has logged_hours => ( + isa => "Num", + is => "rw", + default => 0, +); + +# satisfy the Salaried interface: +sub paycheck_amount { + my $self = shift; + $self->logged_hours * $self->hourly_rate; +} + +</code></pre> + +<ul> +<li>More than an interface</li> +</ul> + +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<ul> +<li>More than Java Interfaces +<ul> +<li>Interfaces are behavior “contracts”</li> +<li>Roles can also have code</li> +</ul></li> +</ul> + +<div class="notes"> +<p>roles can have attributes and methods +roles provide behavior, not just interface</p> +</div> +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<ul> +<li>Role Composition +<ul> +<li>Not inheritence</li> +<li>Symmetric</li> +<li>Unordered</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<ul> +<li>Role Composition +<ul> +<li>Less ambiguity</li> +<li>Compile time errors</li> +<li>â¦And ways to fix them</li> +</ul></li> +</ul> + +<div class="notes"> +<p>symmetric composition means no precedence - if two roles try to define the same thing you get a compile time error that needs to be resolved +multiple inheritence silently assumes you want the first class</p> + +<p>roles cause errors at compile time, unlike multiple inheritence</p> + +<p>roles also provide easy ways to fix the errors</p> +</div> +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<pre><code> +package Ballet; +use Moose::Role; + +sub dance { + pirouette(); +} + +package Punk; +use Moose::Role + +sub dance { + MOSH!!!11one(); +} + +package Foo; +use Moose; + +# KABOOM: +with qw( + Punk + Ballet +); +</code></pre> + +<div class="notes"> +<p>conflicts</p> +</div> +</div> + +<div class="slide"> +<h1>Role of the Moose (cont.)</h1> + +<pre><code> +package Ent::Puppy; +use Moose; + +with ( + Tree => { + alias => { + bark => "tree_bark", + }, + }, + Dog => { + alias => { + bark => "bark_sound", + } + }, +); + +sub bark { + my $self = shift; + + if ( $condition ) { + $self->tree_bark; + } else { + $self->bark_sound; + } +} +</code></pre> + +<ul> +<li>Not that common in practice</li> +</ul> + +<div class="notes"> +<p>Composition parameters +Easier conflict resolution +Finer grained control</p> +</div> +</div> + +<div class="slide"> +<h1>MOPs Mean Cleanliness</h1> + +<ul> +<li>Moose is based on <code>Class::MOP</code> +<ul> +<li>Metaobject Protocol for Perl 5</li> +<li>“makes an object for everything”</li> +</ul></li> +</ul> + +<pre><code> +my $class = $obj->meta; # $obj's metaclass +my $meta = MyApp->meta; # MyApp's metaclass +my $emo = $obj->meta->meta; # even more meta! + +warn $obj->meta->name; +</code></pre> + +</div> + +<div class="slide"> +<h1>Looking in From the Inside</h1> + +<pre><code> +my $metaclass = $self->meta; + +$metaclass->superclasses; + +$metaclass->linearized_isa; + +$metaclass->has_method("foo"); + +$metaclass->compute_all_applicable_attributes; + +# ⦠lots more +</code></pre> + +<div class="notes"> +<p>simple introspection</p> +</div> +</div> + +<div class="slide"> +<h1>Looking in From the Inside (cont.)</h1> + +<pre><code> +Moose::Meta::Class->create( Bar => + version => '0.01', + superclasses => [ 'Foo' ], + attributes => [ + Moose::Meta::Attribute->new( bar => ... ), + Moose::Meta::Attribute->new( baz => ... ), + ], + methods => { + calculate_bar => sub { ... }, + construct_baz => sub { ... } + }, +); + +my $anon_meta = Moose::Meta::Class->create_anon_class( ... ); +</code></pre> + +<div class="notes"> +<p>Classes can be created programmatically</p> +</div> +</div> + +<div class="slide"> +<h1>Looking in From the Inside (cont.)</h1> + +<pre><code> +has foo => ( is => "rw" ); + +__PACKAGE__->meta->add_attribute( + "foo", + is => "rw", +); +</code></pre> + +<ul> +<li>Moose is just sugar +<ul> +<li>The MOP does the hard work</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>The Metaclass Tango</h1> + +<ul> +<li>Metaclassses control class behavior</li> +</ul> + +<pre><code> +has employees => ( + metaclass => 'Collection::Array', + ... +); +</code></pre> + +<ul> +<li>custom attribute metaclasses +<ul> +<li>change how attributes work</li> +</ul></li> +<li>Many customizable parts +<ul> +<li><code>Moose::Meta::Class</code>, <code>Moose::Meta::Attribute,</code><code>Moose::Meta::Method</code>, <code>Moose::Meta::Method::Accessor</code> <code>Moose::Meta::Instance</code>, <code>Moose::Meta::Role</code>, <code>Moose::Meta::TypeConstraint</code>, â¦,</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Working in the Meta Frame</h1> + +<ul> +<li><code>$work</code> project:</li> +<li>CMS for a flash website</li> +<li>Content is in XML</li> +</ul> + +</div> + +<div class="slide"> +<h1>Working in the Meta Frame (cont.)</h1> + +<ul> +<li>Step 1. use Moose</li> +<li>Step 2. ???</li> +<li>Step 3. Profit!</li> +</ul> + +</div> + +<div class="slide"> +<h1>Working in the Meta Frame (cont.)</h1> + +<ul> +<li>Step 2.1. Client’s XML schemas â Moose classes +<ul> +<li>Automatic class definitions</li> +<li>High level objects in runtime</li> +<li>XML storage backed +<ul> +<li>SAX â Moose</li> +<li>Moose â SAX</li> +</ul></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Working in the Meta Frame (cont.)</h1> + +<ul> +<li>Step 2.2. Meta descriptions +<ul> +<li>Extend the metaclasses</li> +<li>Embed additional information +<ul> +<li>field types</li> +<li>access control</li> +</ul></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Working in the Meta Frame (cont.)</h1> + +<ul> +<li>Step 2.3 Introspection goodness +<ul> +<li>Generic web frontend</li> +<li>Object introspection based +<ul> +<li>HTML view</li> +<li>Editing widgets</li> +</ul></li> +<li>Clean, extensible</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Drawbacks of Moose</h1> + +<ul> +<li>Load time +<ul> +<li><code>MooseX::Compile</code> is in the works</li> +</ul></li> +<li>Some features are slow +<ul> +<li>but you only pay for what you use</li> +</ul></li> +<li>Extending non-Hash based classes is tricky. +<ul> +<li>but possible: <code>MooseX::GlobRef::Object</code></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Benefits of Moose</h1> + +<ul> +<li>Less boilerplate +<ul> +<li>attribute storage/access</li> +<li>construction</li> +<li>destruction</li> +<li>verification</li> +<li>â¦</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Benefits of Moose (cont.)</h1> + +<ul> +<li>Shorter +<ul> +<li>less reading</li> +<li>less writing</li> +<li>less code means fewer bugs</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Benefits of Moose (cont.)</h1> + +<ul> +<li>Less testing +<ul> +<li>Moose is very well tested +<ul> +<li>no need to check accessor behavior, etc</li> +</ul></li> +<li>focus on your code’s purpose +<ul> +<li>not that it is “assembled” correctly</li> +<li>http://c2.com/cgi/wiki?IntentionNotAlgorithm</li> +</ul></li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Benefits of Moose (cont.)</h1> + +<ul> +<li>More readable +<ul> +<li>declarative style is self documenting</li> +<li>good signal to noise ratio</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Benefits of Moose (cont.)</h1> + +<ul> +<li>Meta object protocol +<ul> +<li>Cleans up Perl’s OO</li> +<li>Provides introspection</li> +<li>Enables powerful abstractions</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Benefits of Moose (cont.)</h1> + +<ul> +<li>It’s the new black +<ul> +<li>All the cool kids hang out on #moose</li> +<li>Smart sounding buzzwords</li> +<li>Chicks dig antlers</li> +<li>Ruby is so 2007</li> +</ul></li> +</ul> + +</div> + +<div class="slide"> +<h1>Bonus Material</h1> + +</div> + +<div class="slide"> +<h1>Autobox</h1> + +<pre><code> +package Units::Bytes; +use Moose::Role; +use Moose::Autobox; + +sub bytes { $_[0] } +sub kilobytes { $_[0] * 1024 } +sub megabytes { $_[0] * 1024->kilobytes } +sub gigabytes { $_[0] * 1024->megabytes } +sub terabytes { $_[0] * 1024->gigabytes } + +Moose::Autobox->mixin_additional_role( + SCALAR => 'Units::Bytes', +); +</code></pre> + +</div> + +<div class="slide"> +<h1>Autobox (cont.)</h1> + +<pre><code> +use Units::Bytes; +use Moose::Autobox; # autoboxing is lexical + +is(5->bytes, 5, '... got 5 bytes'); +is(5->kilobytes, 5120, '... got 5 kilobytes'); +is(2->megabytes, 2097152, '... got 2 megabytes'); +is(1->gigabytes, 1073741824, '... got 1 gigabyte'); +is(2->terabytes, 2199023255552, '... got 2 terabytes'); +</code></pre> + +</div> + +<div class="slide"> +<h1>perl -Moose</h1> + +<ul> +<li>Moose One Liners with <code>oose.pm</code></li> +</ul> + +<pre><code> +perl -Moose -e 'has foo => ( is=> "rw" ); Class->new( foo => 1 )' +</code></pre> + +<ul> +<li>Useful for testing if something works</li> +<li>Helpful on IRC</li> +<li><code>Devel::REPL</code> is cooler though ;-)</li> +</ul> + +</div> + +<div class="slide"> +<h1>MooseX::POE</h1> + +<pre><code> +package Counter; +use MooseX::POE; +use MooseX::AttributeHelpers; + +has count => ( + metaclass => 'Counter', + provides => { inc => "increment_count" }, +); + +sub START { + shift->yield('increment'); +} + +event increment => sub { + my $self = shift; + + warn "Count is now " . $self->count; + + $self->increment_count; + $self->yield('increment') unless $self->count > 3; +}; + +Counter->new( count => 0 ); +POE::Kernel->run(); +</code></pre> + +<ul> +<li>PoCos made easy</li> +<li>Every object has a <code>POE::Session</code></li> +<li><code>event</code> declares POE object states</li> +</ul> + +</div> + +<div class="slide"> +<h1>Fin</h1> + +<ul> +<li><p>Slides written by:</p> + +<ul> +<li>Chris Prather</li> +<li>Stevan Little</li> +<li>Robert Boone</li> +</ul></li> +<li><p>Slides deleted by:</p> + +<ul> +<li>Yuval Kogman</li> +</ul></li> +</ul> + +</div> + + +</div> + +</body> +</html> diff --git a/PTPW_2008/practical_moose.s5 b/PTPW_2008/practical_moose.s5 new file mode 100644 index 0000000..fb0ecdc --- /dev/null +++ b/PTPW_2008/practical_moose.s5 @@ -0,0 +1,1202 @@ +Title: Moose +Location: YAPC::Asia::2008 +Presenter: Yuval Kogman +Date: 2008 +Theme: moose + +HAI FRENDS +========== + +* My name is Yuval + +â------â------â------â------â------â------â------â------â------â------ + +WHY AM I HERE? +============== + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/cog.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/chamonix.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/clkao.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/office.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/kitchen.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/blood.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/intestines.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/duck_head.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/stinkytofu.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/hunting.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/tokyo.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/tokyo_crazy.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/uni.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/vomit.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/phone.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/phone_no.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/glasses.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/glasses_no.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/visa.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/visa_no.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/orz.jpg" style="height: 50%"> + +<span style="font-family: sans-serif; font-weight: bold; font-size: 3em">orz orz orz </span> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/cog.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/tubes.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/jetpack.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/food.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/mousse.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/beer.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/zipbox.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +<img src="porn/laundry.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +So here I am +============ + +* Anyway⦠+ +â------â------â------â------â------â------â------â------â------â------ + +Moose +===== + +<img src="porn/moose_danger.jpg" style="height: 75%"> + +â------â------â------â------â------â------â------â------â------â------ + +Moose Is Not +============ + +* Experimental +* A toy +* Just another accessor builder +* A source filter +* Perl black magic +* Perl 6 in Perl 5 + +â------â------â------â------â------â------â------â------â------â------ + +Moose Is +======== + +* <a href="http://moose.perl.org">http://moose.perl.org</a> +* A complete modern object framework for Perl + +â------â------â------â------â------â------â------â------â------â------ + +Moose Is +======== + +* Syntactic Sugar for `Class::MOP` +* Rich ancestry + * CLOS (Common Lisp Object System) + * Smalltalk + * Alces latifrons + * Perl 6 + * ⦠+* Stable & Production ready +* Polite, incremental + +â------â------â------â------â------â------â------â------â------â------ + +A Simple Example +================ + +<pre><code> +package Person; + +use strict; +use warnings; + +sub new { + my ( $class, @args ) = @_; + + @args = %{$args[0]} if @args == 1; + + return bless { + @args, + }, $class; +} + +sub name { + my ($self, @args) = @_; + $self->{name} = $args[0] if @args; + return $self->{name}; +} + +sub age { + my ($self, @args) = @_; + $self->{age} = $args[0] if @args; + return $self->{age}; +} + +1; +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +A Simple Moose Example +====================== + +<pre><code> +package Person; +use Moose; + +has name => (is => 'rw'); +has age => (is => 'rw'); + +1; +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +A Simple Moose Example (cont.) +============================== + +* `use Moose;` + * imports keywords + * `use strict; use warnings;` + * `@ISA = qw(Moose::Object) unless @ISA` + +â------â------â------â------â------â------â------â------â------â------ + +A Simple Moose Example (cont.) +============================== + +* `has` declares attributes + * generates accessors + * `is => 'rw'` â read/write accessor + * `is => 'ro'` â read only accessor + * `writer`, `reader` + +* `new` inherited from `Moose::Object` + + +########## + +Now we're going to discuss more features of the attributes + +â------â------â------â------â------â------â------â------â------â------ + +Variations on a Moose Example +============================= + +<pre><code> +package Manager; +use Moose; + +has name => ( + is => 'rw', + isa => 'Str', + default => 'Bob' +); + +has staff => ( + is => 'ro', + isa => 'ArrayRef', + lazy => 1, + default => sub { [qw(Bob Alice Tim)] }, +); +</code></pre> +########## + +Adds default, isa + +â------â------â------â------â------â------â------â------â------â------ + +Variations on a Moose Example (cont.) +===================================== + +* `default` is a + * code reference + * or non-reference (numbers, strings) + * used when no parameter is given to `new` + +* `lazy` delays `default` + * called on first usage of `$object->staff` + * not inside `new` + +########## +discusses default + +non refs make accidental sharing hard + +â------â------â------â------â------â------â------â------â------â------ + +Variations on a Moose Example (cont.) +===================================== + +* `isa` specifies a type + * `Moose::Util::TypeConstraints` + * `Any, Item, Bool, Undef, Defined, Value, Num, Int, Str, Ref, ScalarRef, ArrayRef, HashRef, CodeRef, RegexpRef, GlobRef, FileHandle, Object and Role` + * Types don't need to exist +<pre><code> + has 'date' => (isa => 'DateTime'); # DWIM +</code></pre> +########## + +isa, type constraints + +â------â------â------â------â------â------â------â------â------â------ + +Typical Family +============== + +* Types have a hierarchy + * `Item` â `Defined` â `Ref` â `Object` + +<pre><code> + subtype 'Ref' + => as 'Defined' + => where { ref($_) }; + + subtype 'Object' + => as 'Ref' + => where { blessed($_) } +</code></pre> +########## + +type hierarchy + +â------â------â------â------â------â------â------â------â------â------ + +Conventional Delegates +====================== + +<pre><code> +package Employee; +use Moose; +extends qw(Person); + +has manager => ( + is => 'ro', + isa => 'Manager', + handles => { + manager_name => 'name', + coworkers => 'staff', + } +); +</code></pre> + +* manager `handles` certain methods for `Employee` + * `$emp->coworkers` == `$emp->manager->staff ` + +â------â------â------â------â------â------â------â------â------â------ + +Conventional Delegates (cont.) +============================== + +<pre><code> +has phone => ( + ... + handles => [qw(number extension)], +); +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +Conventional Delegates (cont.) +============================== + +<pre><code> +has phone => ( + ... + isa => "Phone", + handles => qr/^[a-z]\w+$/, +); +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +Conventional Delegates (cont.) +============================== + +<pre><code> +has phone => ( + ... + handles => "Dialing", # a role +); +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +UnConventional Delegates +======================== + +<pre><code> +package Company; +use Moose; +use MooseX::AttributeHelpers; + +has employees => ( + metaclass => 'Collection::Array', + isa => 'ArrayRef[Employees]', + is => 'rw', + provides => { + push => 'add_employee', + pop => 'remove_employee', + count => 'number_of_employees', + empty => 'any_employees', + }, +); +</code></pre> +â------â------â------â------â------â------â------â------â------â------ + +Modified Methods +================ + +<pre><code> +before 'employees' => sub { warn 'calling employees' }; + +after 'employees' => sub { warn 'finished calling employees' }; +</code></pre> + +* Pre/Post hooks + * Get a copy of `@_` + * Return value is ignored + +â------â------â------â------â------â------â------â------â------â------ + +Modified Methods (cont.) +======================== + +<pre><code> +around 'employees' => sub { + my ($next, $self, @args) = @_; + ... + my @return = $self->$next(@args); + ... + return @return; +}; +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +Modified Methods (cont.) +======================== + +<pre><code> +package Employee; +use Moose; + +sub do_work { + my $self = shift; + + $self->punch_in; + + inner(); # call subclass here + + $self->punch_out; +} +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +Modified Methods (cont.) +======================== + +<pre><code> +package Employee::Chef; +use Moose; + +extends qw(Employee); + +augment do_work => sub { + my $self = shift; + + while ( @burgers ) { + $self->flip_burger(shift @burgers); + } +}; + +$chef->do_work; # punch in, flip burgers, punch out +</code></pre> +â------â------â------â------â------â------â------â------â------â------ + +Some Type of Coercion +===================== + +<pre><code> +package Employee; +use Moose; +use Moose::Util::TypeConstraints; +extends qw(Person); + +class_type 'Manager'; + +coerce 'Manager' => ( + from 'Str' => via { Manager->new( name => $_ ) }, +); + +has manager => ( + is => 'ro', + isa => 'Manager', + required => 1, + coerce => 1, +); +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +Some Type of Coercion (cont.) +============================= + +<pre><code> +# import type constraint keywords +use Moose::Util::TypeConstraints; + + +# define Manager, a subtype of Object +class_type "Manager"; + + +# define the conversion +... via { Manager->new( name => $_ ) } + + +# enable it per attribute +has manager => ( + ... + coerce => 1, +); +</code></pre> + +########## + +breakdown of the example + +class types are automatically created for all Moose classes + +â------â------â------â------â------â------â------â------â------â------ + +Some Type of Digression +======================= + +<pre><code> +has employees => ( + is => 'rw', + isa => 'ArrayRef[Employee]', +); + +has shopping_carts => ( + is => 'rw', + isa => 'ArrayRef[ArrayRef[ShinyBead]]' +); +</code></pre> + +########## + +Going to go into features of the type system for a bit + +Parametrized types + +â------â------â------â------â------â------â------â------â------â------ +Some Type of Digression (cont.) +=============================== + +<pre><code> +has language => ( + is => 'rw', + isa => 'English | Welsh | Scots | Gaelic', +); + +has member => ( + is => 'rw', + isa => 'Employee | ArrayRef[ Employee | Group ]', +); +</code></pre> + +########## + +Union types + +â------â------â------â------â------â------â------â------â------â------ + +Some Type of Digression (cont.) +=============================== + +<pre><code> +package Foo; +use Moose; +use Moose::Util::TypeConstraints; + +use Test::Deep qw(eq_deeply ...); + +type 'SomethingTricky' => where { + eq_deeply( $_, ... ); +}; + +has 'bar' => ( + is => 'rw', + isa => 'SomethingTricky', +); +</code></pre> + +########## + +Test::Deep custom validator + +Can use any validation from the CPAN + +â------â------â------â------â------â------â------â------â------â------ + +Some Parametrized Type of Coercion +================================== + +<pre><code> +use Moose::Util::TypeConstraints; + +subtype 'ArrayRef[Employee]' => as 'ArrayRef'; + +coerce 'ArrayRef[Employee]' => ( + from 'ArrayRef[Str]' via { + [ map { Employee->new( name => $_ ) } @$_ ] + }, +); + +has staff => ( + isa => 'ArrayRef[Employee]', + coerce => 1, +); +</code></pre> + +########## + +coerce parametrized ArrayRef[Employee] from ArrayRef[Str] + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose +================= + +* A role is like a⦠+ * Java Interface: safe + * mixin: useful +* A role is for small reusable behaviors + * better than using a multiple inheritence + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +* Roles on the CPAN: + * `MooseX::Clone` - Flexible `clone` method + * `MooseX::Storage` - Flexible serialization + * `MooseX::Getopt` - `@ARGV` aware constructor + * `MooseX::LogDispatch` - `$self->logger->info("something happenned")` + * `MooseX::Param` - `param` method like `CGI.pm`'s, + +########## + +Some examples of small reusable behaviors + +Param is good for interacting with e.g. CGI::Expand or similar modules + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +<pre><code> +package Minion; +use Moose; + +extends qw(Employee); + +with qw(Salaried::Hourly); + + +package Boss; +use Moose; + +extends qw(Employee); + +with qw(Salaried::Monthly); + +</code></pre> + +* `with` adds roles into your class + * `Salaried::Hourly` was added to `Minion` + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +<pre><code> +package Salaried; +use Moose::Role; + +requires 'paycheck_amount'; +</code></pre> + +* Just an interface + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +<pre><code> +package Salaried::Hourly; +use Moose::Role; + +with qw(Salaried); + +has hourly_rate => ( + isa => "Num", + is => "rw", + required => 1, +); + +has logged_hours => ( + isa => "Num", + is => "rw", + default => 0, +); + +# satisfy the Salaried interface: +sub paycheck_amount { + my $self = shift; + $self->logged_hours * $self->hourly_rate; +} + +</code></pre> + +* More than an interface + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +* More than Java Interfaces + * Interfaces are behavior "contracts" + * Roles can also have code + +########## +roles can have attributes and methods +roles provide behavior, not just interface + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +* Role Composition + * Not inheritence + * Symmetric + * Unordered + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +* Role Composition + * Less ambiguity + * Compile time errors + * â¦And ways to fix them + +########## +symmetric composition means no precedence - if two roles try to define the same thing you get a compile time error that needs to be resolved +multiple inheritence silently assumes you want the first class + +roles cause errors at compile time, unlike multiple inheritence + +roles also provide easy ways to fix the errors + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +<pre><code> +package Ballet; +use Moose::Role; + +sub dance { + pirouette(); +} + +package Punk; +use Moose::Role + +sub dance { + MOSH!!!11one(); +} + +package Foo; +use Moose; + +# KABOOM: +with qw( + Punk + Ballet +); +</code></pre> + +########## + +conflicts + +â------â------â------â------â------â------â------â------â------â------ + +Role of the Moose (cont.) +========================= + +<pre><code> +package Ent::Puppy; +use Moose; + +with ( + Tree => { + alias => { + bark => "tree_bark", + }, + }, + Dog => { + alias => { + bark => "bark_sound", + } + }, +); + +sub bark { + my $self = shift; + + if ( $condition ) { + $self->tree_bark; + } else { + $self->bark_sound; + } +} +</code></pre> + +* Not that common in practice + +########## + +Composition parameters +Easier conflict resolution +Finer grained control + +â------â------â------â------â------â------â------â------â------â------ + +MOPs Mean Cleanliness +===================== + +* Moose is based on `Class::MOP` + * Metaobject Protocol for Perl 5 + * "makes an object for everything" + +<pre><code> +my $class = $obj->meta; # $obj's metaclass +my $meta = MyApp->meta; # MyApp's metaclass +my $emo = $obj->meta->meta; # even more meta! + +warn $obj->meta->name; +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +Looking in From the Inside +=========================== + +<pre><code> +my $metaclass = $self->meta; + +$metaclass->superclasses; + +$metaclass->linearized_isa; + +$metaclass->has_method("foo"); + +$metaclass->compute_all_applicable_attributes; + +# ⦠lots more +</code></pre> +########## + +simple introspection + +â------â------â------â------â------â------â------â------â------â------ + +Looking in From the Inside (cont.) +================================== + +<pre><code> +Moose::Meta::Class->create( Bar => + version => '0.01', + superclasses => [ 'Foo' ], + attributes => [ + Moose::Meta::Attribute->new( bar => ... ), + Moose::Meta::Attribute->new( baz => ... ), + ], + methods => { + calculate_bar => sub { ... }, + construct_baz => sub { ... } + }, +); + +my $anon_meta = Moose::Meta::Class->create_anon_class( ... ); +</code></pre> + +########## + +Classes can be created programmatically +â------â------â------â------â------â------â------â------â------â------ + +Looking in From the Inside (cont.) +================================== + +<pre><code> +has foo => ( is => "rw" ); + +__PACKAGE__->meta->add_attribute( + "foo", + is => "rw", +); +</code></pre> + +* Moose is just sugar + * The MOP does the hard work + +â------â------â------â------â------â------â------â------â------â------ + +The Metaclass Tango +=================== + +* Metaclassses control class behavior + +<pre><code> +has employees => ( + metaclass => 'Collection::Array', + ... +); +</code></pre> + +* custom attribute metaclasses + * change how attributes work +* Many customizable parts + * `Moose::Meta::Class`, `Moose::Meta::Attribute, ``Moose::Meta::Method`, `Moose::Meta::Method::Accessor` `Moose::Meta::Instance`, `Moose::Meta::Role`, `Moose::Meta::TypeConstraint`, â¦, + +â------â------â------â------â------â------â------â------â------â------ + +Working in the Meta Frame +========================= + +* `$work` project: +* CMS for a flash website +* Content is in XML + +â------â------â------â------â------â------â------â------â------â------ + +Working in the Meta Frame (cont.) +================================= + +* Step 1. use Moose +* Step 2. ??? +* Step 3. Profit! + +â------â------â------â------â------â------â------â------â------â------ + +Working in the Meta Frame (cont.) +================================= + +* Step 2.1. Client's XML schemas â Moose classes + * Automatic class definitions + * High level objects in runtime + * XML storage backed + * SAX â Moose + * Moose â SAX + +â------â------â------â------â------â------â------â------â------â------ + +Working in the Meta Frame (cont.) +================================= + +* Step 2.2. Meta descriptions + * Extend the metaclasses + * Embed additional information + * field types + * access control + +â------â------â------â------â------â------â------â------â------â------ + +Working in the Meta Frame (cont.) +================================= + +* Step 2.3 Introspection goodness + * Generic web frontend + * Object introspection based + * HTML view + * Editing widgets + * Clean, extensible + +â------â------â------â------â------â------â------â------â------â------ + +Drawbacks of Moose +================== + +* Load time + * `MooseX::Compile` is in the works +* Some features are slow + * but you only pay for what you use +* Extending non-Hash based classes is tricky. + * but possible: `MooseX::GlobRef::Object` + +â------â------â------â------â------â------â------â------â------â------ + +Benefits of Moose +================= + +* Less boilerplate + * attribute storage/access + * construction + * destruction + * verification + * ⦠+ +â------â------â------â------â------â------â------â------â------â------ + +Benefits of Moose (cont.) +========================= + +* Shorter + * less reading + * less writing + * less code means fewer bugs + +â------â------â------â------â------â------â------â------â------â------ + +Benefits of Moose (cont.) +========================= + +* Less testing + * Moose is very well tested + * no need to check accessor behavior, etc + * focus on your code's purpose + * not that it is "assembled" correctly + * http://c2.com/cgi/wiki?IntentionNotAlgorithm + +â------â------â------â------â------â------â------â------â------â------ + +Benefits of Moose (cont.) +========================= + +* More readable + * declarative style is self documenting + * good signal to noise ratio + +â------â------â------â------â------â------â------â------â------â------ + +Benefits of Moose (cont.) +========================= + +* Meta object protocol + * Cleans up Perl's OO + * Provides introspection + * Enables powerful abstractions + +â------â------â------â------â------â------â------â------â------â------ + +Benefits of Moose (cont.) +========================= + +* It's the new black + * All the cool kids hang out on #moose + * Smart sounding buzzwords + * Chicks dig antlers + * Ruby is so 2007 + +â------â------â------â------â------â------â------â------â------â------ + +Bonus Material +============== + +â------â------â------â------â------â------â------â------â------â------ + +Autobox +======= + +<pre><code> +package Units::Bytes; +use Moose::Role; +use Moose::Autobox; + +sub bytes { $_[0] } +sub kilobytes { $_[0] * 1024 } +sub megabytes { $_[0] * 1024->kilobytes } +sub gigabytes { $_[0] * 1024->megabytes } +sub terabytes { $_[0] * 1024->gigabytes } + +Moose::Autobox->mixin_additional_role( + SCALAR => 'Units::Bytes', +); +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +Autobox (cont.) +=============== + +<pre><code> +use Units::Bytes; +use Moose::Autobox; # autoboxing is lexical + +is(5->bytes, 5, '... got 5 bytes'); +is(5->kilobytes, 5120, '... got 5 kilobytes'); +is(2->megabytes, 2097152, '... got 2 megabytes'); +is(1->gigabytes, 1073741824, '... got 1 gigabyte'); +is(2->terabytes, 2199023255552, '... got 2 terabytes'); +</code></pre> + +â------â------â------â------â------â------â------â------â------â------ + +perl -Moose +=========== + +* Moose One Liners with `oose.pm` + +<pre><code> +perl -Moose -e 'has foo => ( is=> "rw" ); Class->new( foo => 1 )' +</code></pre> + +* Useful for testing if something works +* Helpful on IRC +* `Devel::REPL` is cooler though ;-) + +â------â------â------â------â------â------â------â------â------â------ + +MooseX::POE +=========== + +<pre><code> +package Counter; +use MooseX::POE; +use MooseX::AttributeHelpers; + +has count => ( + metaclass => 'Counter', + provides => { inc => "increment_count" }, +); + +sub START { + shift->yield('increment'); +} + +event increment => sub { + my $self = shift; + + warn "Count is now " . $self->count; + + $self->increment_count; + $self->yield('increment') unless $self->count > 3; +}; + +Counter->new( count => 0 ); +POE::Kernel->run(); +</code></pre> + +* PoCos made easy +* Every object has a `POE::Session` +* `event` declares POE object states + +â------â------â------â------â------â------â------â------â------â------ + +Fin +=== + +* Slides written by: + * Chris Prather + * Stevan Little + * Robert Boone + +* Slides deleted by: + * Yuval Kogman diff --git a/PTPW_2008/ui/default/blank.gif b/PTPW_2008/ui/default/blank.gif new file mode 100644 index 0000000..75b945d Binary files /dev/null and b/PTPW_2008/ui/default/blank.gif differ diff --git a/PTPW_2008/ui/default/bodybg.gif b/PTPW_2008/ui/default/bodybg.gif new file mode 100755 index 0000000..5f448a1 Binary files /dev/null and b/PTPW_2008/ui/default/bodybg.gif differ diff --git a/PTPW_2008/ui/default/framing.css b/PTPW_2008/ui/default/framing.css new file mode 100644 index 0000000..2a27daf --- /dev/null +++ b/PTPW_2008/ui/default/framing.css @@ -0,0 +1,22 @@ +/* The following styles size, place, and layer the slide components. + Edit these if you want to change the overall slide layout. + The commented lines can be uncommented (and modified, if necessary) + to help you with the rearrangement process. */ + +/* target = 1024x768 */ + +div#header, div#footer, .slide {width: 100%; top: 0; left: 0;} +div#header {top: 0; height: 3em; z-index: 1;} +div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;} +.slide {top: 0; width: 92%; padding: 3.5em 4% 4%; z-index: 2; list-style: none;} +div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;} +div#controls form {text-align: right; width: 100%; margin: 0;} +#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; z-index: 10;} +html>body #currentSlide {position: fixed;} + +/* +div#header {background: #FCC;} +div#footer {background: #CCF;} +div#controls {background: #BBD;} +div#currentSlide {background: #FFC;} +*/ diff --git a/PTPW_2008/ui/default/iepngfix.htc b/PTPW_2008/ui/default/iepngfix.htc new file mode 100644 index 0000000..bba2db7 --- /dev/null +++ b/PTPW_2008/ui/default/iepngfix.htc @@ -0,0 +1,42 @@ +<public:component> +<public:attach event="onpropertychange" onevent="doFix()" /> + +<script> + +// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com +// Free usage permitted as long as this notice remains intact. + +// This must be a path to a blank image. That's all the configuration you need here. +var blankImg = 'ui/default/blank.gif'; + +var f = 'DXImageTransform.Microsoft.AlphaImageLoader'; + +function filt(s, m) { + if (filters[f]) { + filters[f].enabled = s ? true : false; + if (s) with (filters[f]) { src = s; sizingMethod = m } + } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")'; +} + +function doFix() { + if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) || + (event && !/(background|src)/.test(event.propertyName))) return; + + if (tagName == 'IMG') { + if ((/\.png$/i).test(src)) { + filt(src, 'image'); // was 'scale' + src = blankImg; + } else if (src.indexOf(blankImg) < 0) filt(); + } else if (style.backgroundImage) { + if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) { + var s = RegExp.$1; + style.backgroundImage = ''; + filt(s, 'crop'); + } else filt(); + } +} + +doFix(); + +</script> +</public:component> \ No newline at end of file diff --git a/PTPW_2008/ui/default/notes.css b/PTPW_2008/ui/default/notes.css new file mode 100644 index 0000000..5858cf2 --- /dev/null +++ b/PTPW_2008/ui/default/notes.css @@ -0,0 +1,122 @@ +/* Following are the note styles -- edit away! */ + +body { + margin: 0; + padding: 1.0em; + background: #333; + color: #FFF; + font: 2em/1.4em 'Lucida Grande', Verdana, sans-serif; +} + +div.timers { + background: #FFF; + color: #333; + border: 0.08em solid #222; + border-top-width: 1px; + border-left-width: 1px; + float: left; + padding: 0.2em; + margin: 0 0 0.5em; + position: relative; +} + +div.timers h1 { + text-align: left; + font-size: 0.6em; + line-height: 1.4em; + background-color: #FF9; + padding: 0 0.75em; + margin: 0.25em 0 0; + border: 1px solid #EE8; +} + +div.timers div.controls { + position: absolute; + right: 0.25em; + top: 0.1em; + line-height: 1em; +} + +div.timers h1 a { + text-decoration: none; + color: #000; +} + +div.timers div.controls a { + font-size: 0.5em; + padding: 0; + color: #330; +} + +div.timers a.control { + position: absolute; + text-decoration: none; + padding: 0 0.25em; + color: #AAA; + outline: 0; +} + +#minus { + left: 0.25em; +} + +#plus { + right: 0.25em; +} + +.overtime { + background: yellow; + color: red; + border: 3px solid; + padding: 0.1em 0.25em; + font-weight: bold; +} + +div.timers h2 { + font-size: 0.6em; + line-height: 1.0em; + font-weight: normal; + margin: 0 0 -0.25em; + padding-top: 0.5em; + color: #666; +} + +div.timers p {margin: 0; padding: 0 0.5em;} +div.timers form {margin: 0;} + +div.timers span.clock { + font-family: monospace; +} + +div.timers ul {margin: 0; padding: 0; list-style: none;} +div.timers li {float: left; width: 5em; margin: 0; padding: 0 0.5em; + text-align: center;} + +div#elapsed {width: 12.1em;} +div#remaining {clear: left; width: 12.1em;} +div#remaining p {text-align: center;} + +#slide, +#next, +#notes, +#nextnotes { + font-size: 0.75em; + line-height: 1.4em; + clear: left; +/* max-width: 30.0em; */ + text-shadow: 0.1em 0.1em 0.1em #111; +} + +#next {margin-top: 2.5em;} +#next, #nextnotes { + color: #999; + font-size: 0.66em; +} + +em.disclaimer { + color: #666; +} + +div.collapsed h1 {display: block; font-size: 0.33em;} +div.collapsed h1 a {display: inline;} +div.collapsed * {display: none;} diff --git a/PTPW_2008/ui/default/opera.css b/PTPW_2008/ui/default/opera.css new file mode 100644 index 0000000..9e9d2a3 --- /dev/null +++ b/PTPW_2008/ui/default/opera.css @@ -0,0 +1,7 @@ +/* DO NOT CHANGE THESE unless you really want to break Opera Show */ +.slide { + visibility: visible !important; + position: static !important; + page-break-before: always; +} +#slide0 {page-break-before: avoid;} diff --git a/PTPW_2008/ui/default/outline.css b/PTPW_2008/ui/default/outline.css new file mode 100644 index 0000000..62db519 --- /dev/null +++ b/PTPW_2008/ui/default/outline.css @@ -0,0 +1,15 @@ +/* don't change this unless you want the layout stuff to show up in the outline view! */ + +.layout div, #footer *, #controlForm * {display: none;} +#footer, #controls, #controlForm, #navLinks, #toggle { + display: block; visibility: visible; margin: 0; padding: 0;} +#toggle {float: right; padding: 0.5em;} +html>body #toggle {position: fixed; top: 0; right: 0;} + +/* making the outline look pretty-ish */ + +#slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;} +#slide0 h1 {padding-top: 1.5em;} +.slide h1 {margin: 1.5em 0 0; padding-top: 0.25em; + border-top: 1px solid #888; border-bottom: 1px solid #AAA;} +#toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;} diff --git a/PTPW_2008/ui/default/pretty.css b/PTPW_2008/ui/default/pretty.css new file mode 100644 index 0000000..838a7cf --- /dev/null +++ b/PTPW_2008/ui/default/pretty.css @@ -0,0 +1,82 @@ +/* Following are the presentation styles -- edit away! */ + +body {background: #FFF url(bodybg.gif) -16px 0 no-repeat; color: #000; font-size: 2.25em;} +:link, :visited {text-decoration: none; color: #00C;} +#controls :active {color: #88A !important;} +#controls :focus {outline: 1px dotted #227;} +h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;} +ul, pre {margin: 0; line-height: 1em;} +html, body {margin: 0; padding: 0;} + +blockquote, q {font-style: italic;} +blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;} +blockquote p {margin: 0;} +blockquote i {font-style: normal;} +blockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;} +blockquote b i {font-style: italic;} + +kbd {font-weight: bold; font-size: 1em;} +sup {font-size: smaller; line-height: 1px;} + +.slide code {padding: 2px 0.25em; font-weight: bold; color: #533;} +.slide code.bad, code del {color: red;} +.slide code.old {color: silver;} +.slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: #533; font-size: 90%;} +.slide pre code {display: block;} +.slide ul {margin-left: 5%; margin-right: 7%; list-style: disc;} +.slide li {margin-top: 0.75em; margin-right: 0;} +.slide ul ul {line-height: 1;} +.slide ul ul li {margin: .2em; font-size: 85%; list-style: square;} +.slide img.leader {display: block; margin: 0 auto;} + +div#header, div#footer {background: #005; color: #AAB; + font-family: Verdana, Helvetica, sans-serif;} +div#header {background: #005 url(bodybg.gif) -16px 0 no-repeat; + line-height: 1px;} +div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;} +#footer h1, #footer h2 {display: block; padding: 0 1em;} +#footer h2 {font-style: italic;} + +div.long {font-size: 0.75em;} +.slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1; + margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap; + font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize; + color: #DDE; background: #005;} +.slide h3 {font-size: 130%;} +h1 abbr {font-variant: small-caps;} + +div#controls {position: absolute; left: 60%; bottom: 0; + width: 40%; + text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;} +html>body div#controls {position: fixed; padding: 0; top: auto;} +#controls #navLinks a {padding: 0; margin: 0 0.5em; + background: #005; border: none; color: #779; + cursor: pointer;} +#controls #navList #jumplist {background: #DDD; color: #227;} + +#currentSlide {text-align: center; font-size: 0.5em; color: #449;} + +#slide0 {padding-top: 3.5em; font-size: 90%;} +#slide0 h1 {position: static; margin: 1em 0 0; padding: 0; + font: bold 2em Helvetica, sans-serif; white-space: normal; + color: #000; background: transparent;} +#slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;} +#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;} +#slide0 h4 {margin-top: 0; font-size: 1em;} + +ul.urls {list-style: none; display: inline; margin: 0;} +.urls li {display: inline; margin: 0;} +.note {display: none;} +.external {border-bottom: 1px dotted gray;} +html>body .external {border-bottom: none;} +.external:after {content: " \274F"; font-size: smaller; color: #77B;} + +.incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;} +img.incremental {visibility: hidden;} +.slide .current {color: #B02;} + + +/* diagnostics + +li:after {content: " [" attr(class) "]"; color: #F88;} + */ \ No newline at end of file diff --git a/PTPW_2008/ui/default/print.css b/PTPW_2008/ui/default/print.css new file mode 100644 index 0000000..e7a71d1 --- /dev/null +++ b/PTPW_2008/ui/default/print.css @@ -0,0 +1 @@ +/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */ .slide, ul {page-break-inside: avoid; visibility: visible !important;} h1 {page-break-after: avoid;} body {font-size: 12pt; background: white;} * {color: black;} #slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;} #slide0 h3 {margin: 0; padding: 0;} #slide0 h4 {margin: 0 0 0.5em; padding: 0;} #slide0 {margin-bottom: 3em;} h1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;} .extra {background: transparent !important;} div.extra, pre.extra, .example {font-size: 10pt; color: #333;} ul.extra a {font-weight: bold;} p.example {display: none;} #header {display: none;} #footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;} #footer h2, #controls {display: none;} /* The following rule keeps the layout stuff out of print. Remove at your own risk! */ .layout, .layout * {display: none !important;} \ No newline at end of file diff --git a/PTPW_2008/ui/default/s5-core.css b/PTPW_2008/ui/default/s5-core.css new file mode 100644 index 0000000..ad1530b --- /dev/null +++ b/PTPW_2008/ui/default/s5-core.css @@ -0,0 +1,9 @@ +/* Do not edit or override these styles! The system will likely break if you do. */ + +div#header, div#footer, div#controls, .slide {position: absolute;} +html>body div#header, html>body div#footer, + html>body div#controls, html>body .slide {position: fixed;} +.handout, .notes {display: none;} +.layout {display: block;} +.slide, .hideme, .incremental {visibility: hidden;} +#slide0 {visibility: visible;} diff --git a/PTPW_2008/ui/default/slides.css b/PTPW_2008/ui/default/slides.css new file mode 100644 index 0000000..0786d7d --- /dev/null +++ b/PTPW_2008/ui/default/slides.css @@ -0,0 +1,3 @@ +@import url(s5-core.css); /* required to make the slide show run at all */ +@import url(framing.css); /* sets basic placement and size of slide components */ +@import url(pretty.css); /* stuff that makes the slides look better than blah */ \ No newline at end of file diff --git a/PTPW_2008/ui/default/slides.js b/PTPW_2008/ui/default/slides.js new file mode 100644 index 0000000..ab2a4b2 --- /dev/null +++ b/PTPW_2008/ui/default/slides.js @@ -0,0 +1,764 @@ +// S5 v1.2a1 slides.js -- released into the Public Domain +// +// Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information +// about all the wonderful and talented contributors to this code! + +var undef; +var slideCSS = ''; +var snum = 0; +var smax = 1; +var incpos = 0; +var number = undef; +var s5mode = true; +var defaultView = 'slideshow'; +var controlVis = 'visible'; + +var s5NotesWindow; +var s5NotesWindowLoaded = false; +var previousSlide = 0; +var presentationStart = new Date(); +var slideStart = new Date(); + +var countdown = { + timer: 0, + state: 'pause', + start: new Date(), + end: 0, + remaining: 0 +}; + + +var isIE = navigator.appName == 'Microsoft Internet Explorer' && navigator.userAgent.indexOf('Opera') < 1 ? 1 : 0; +var isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0; +var isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0; + +function hasClass(object, className) { + if (!object.className) return false; + return (object.className.search('(^|\\s)' + className + '(\\s|$)') != -1); +} + +function hasValue(object, value) { + if (!object) return false; + return (object.search('(^|\\s)' + value + '(\\s|$)') != -1); +} + +function removeClass(object,className) { + if (!object || !hasClass(object,className)) return; + object.className = object.className.replace(new RegExp('(^|\\s)'+className+'(\\s|$)'), RegExp.$1+RegExp.$2); +} + +function addClass(object,className) { + if (!object || hasClass(object, className)) return; + if (object.className) { + object.className += ' '+className; + } else { + object.className = className; + } +} + +function GetElementsWithClassName(elementName,className) { + var allElements = document.getElementsByTagName(elementName); + var elemColl = new Array(); + for (var i = 0; i< allElements.length; i++) { + if (hasClass(allElements[i], className)) { + elemColl[elemColl.length] = allElements[i]; + } + } + return elemColl; +} + +function isParentOrSelf(element, id) { + if (element == null || element.nodeName=='BODY') return false; + else if (element.id == id) return true; + else return isParentOrSelf(element.parentNode, id); +} + +function nodeValue(node) { + var result = ""; + if (node.nodeType == 1) { + var children = node.childNodes; + for (var i = 0; i < children.length; ++i) { + result += nodeValue(children[i]); + } + } + else if (node.nodeType == 3) { + result = node.nodeValue; + } + return(result); +} + +function slideLabel() { + var slideColl = GetElementsWithClassName('*','slide'); + var list = document.getElementById('jumplist'); + smax = slideColl.length; + for (var n = 0; n < smax; n++) { + var obj = slideColl[n]; + + var did = 'slide' + n.toString(); + obj.setAttribute('id',did); + +// if (isOp) continue; // Opera fix (hallvord) + + var otext = ''; + var menu = obj.firstChild; + if (!menu) continue; // to cope with empty slides + while (menu && menu.nodeType == 3) { + menu = menu.nextSibling; + } + if (!menu) continue; // to cope with slides with only text nodes + + var menunodes = menu.childNodes; + for (var o = 0; o < menunodes.length; o++) { + otext += nodeValue(menunodes[o]); + } + list.options[list.length] = new Option(n + ' : ' + otext, n); + } +} + +function currentSlide() { + var cs; + if (document.getElementById) { + cs = document.getElementById('currentSlide'); + } else { + cs = document.currentSlide; + } + cs.innerHTML = '<a id="plink" href="">' + + '<span id="csHere">' + snum + '<\/span> ' + + '<span id="csSep">\/<\/span> ' + + '<span id="csTotal">' + (smax-1) + '<\/span>' + + '<\/a>' + ; + if (snum == 0) { + cs.style.visibility = 'hidden'; + } else { + cs.style.visibility = 'visible'; + } +} + +function go(step) { + if (document.getElementById('slideProj').disabled || step == 0) return; + var jl = document.getElementById('jumplist'); + var cid = 'slide' + snum; + var ce = document.getElementById(cid); + if (incrementals[snum].length > 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + removeClass(incrementals[snum][i], 'current'); + removeClass(incrementals[snum][i], 'incremental'); + } + } + if (step != 'j') { + snum += step; + lmax = smax - 1; + if (snum > lmax) snum = lmax; + if (snum < 0) snum = 0; + } else + snum = parseInt(jl.value); + var nid = 'slide' + snum; + var ne = document.getElementById(nid); + if (!ne) { + ne = document.getElementById('slide0'); + snum = 0; + } + if (step < 0) {incpos = incrementals[snum].length} else {incpos = 0;} + if (incrementals[snum].length > 0 && incpos == 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + if (hasClass(incrementals[snum][i], 'current')) + incpos = i + 1; + else + addClass(incrementals[snum][i], 'incremental'); + } + } + if (incrementals[snum].length > 0 && incpos > 0) + addClass(incrementals[snum][incpos - 1], 'current'); + if (isOp) { //hallvord + location.hash = nid; + } else { + ce.style.visibility = 'hidden'; + ne.style.visibility = 'visible'; + } // /hallvord + jl.selectedIndex = snum; + currentSlide(); + loadNote(); + permaLink(); + number = undef; +} + +function goTo(target) { + if (target >= smax || target == snum) return; + go(target - snum); +} + +function subgo(step) { + if (step > 0) { + removeClass(incrementals[snum][incpos - 1],'current'); + removeClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos],'current'); + incpos++; + } else { + incpos--; + removeClass(incrementals[snum][incpos],'current'); + addClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos - 1],'current'); + } + loadNote(); +} + +function toggle() { + var slideColl = GetElementsWithClassName('*','slide'); + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + if (!slides.disabled) { + slides.disabled = true; + outline.disabled = false; + s5mode = false; + fontSize('1em'); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'visible'; + } + } else { + slides.disabled = false; + outline.disabled = true; + s5mode = true; + fontScale(); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'hidden'; + } + slideColl[snum].style.visibility = 'visible'; + } +} + +function showHide(action) { + var obj = GetElementsWithClassName('*','hideme')[0]; + switch (action) { + case 's': obj.style.visibility = 'visible'; break; + case 'h': obj.style.visibility = 'hidden'; break; + case 'k': + if (obj.style.visibility != 'visible') { + obj.style.visibility = 'visible'; + } else { + obj.style.visibility = 'hidden'; + } + break; + } +} + +// 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/) +function keys(key) { + if (!key) { + key = event; + key.which = key.keyCode; + } + if (key.which == 84) { + toggle(); + return; + } + if (s5mode) { + switch (key.which) { + case 10: // return + case 13: // enter + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + if(number != undef) { + goTo(number); + break; + } + case 32: // spacebar + case 34: // page down + case 39: // rightkey + case 40: // downkey + if(number != undef) { + go(number); + } else if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + break; + case 33: // page up + case 37: // leftkey + case 38: // upkey + if(number != undef) { + go(-1 * number); + } else if (!incrementals[snum] || incpos <= 0) { + go(-1); + } else { + subgo(-1); + } + break; + case 36: // home + goTo(0); + break; + case 35: // end + goTo(smax-1); + break; + case 67: // c + showHide('k'); + break; + case 78: // n + createNotesWindow(); + break; + } + if (key.which < 48 || key.which > 57) { + number = undef; + } else { + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + number = (((number != undef) ? number : 0) * 10) + (key.which - 48); + } + } + return false; +} + +function clicker(e) { + number = undef; + var target; + if (window.event) { + target = window.event.srcElement; + e = window.event; + } else target = e.target; + if (target.href != null || hasValue(target.rel, 'external') || isParentOrSelf(target, 'controls') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object')) return true; + if (!e.which || e.which == 1) { + if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + } +} + +function findSlide(hash) { + var target = null; + var slides = GetElementsWithClassName('*','slide'); + for (var i = 0; i < slides.length; i++) { + var targetSlide = slides[i]; + if ( (targetSlide.name && targetSlide.name == hash) + || (targetSlide.id && targetSlide.id == hash) ) { + target = targetSlide; + break; + } + } + while(target != null && target.nodeName != 'BODY') { + if (hasClass(target, 'slide')) { + return parseInt(target.id.slice(5)); + } + target = target.parentNode; + } + return null; +} + +function slideJump() { + if (window.location.hash == null) return; + var sregex = /^#slide(\d+)$/; + var matches = sregex.exec(window.location.hash); + var dest = null; + if (matches != null) { + dest = parseInt(matches[1]); + } else { + dest = findSlide(window.location.hash.slice(1)); + } + if (dest != null) + go(dest - snum); +} + +function fixLinks() { + var thisUri = window.location.href; + thisUri = thisUri.slice(0, thisUri.length - window.location.hash.length); + var aelements = document.getElementsByTagName('A'); + for (var i = 0; i < aelements.length; i++) { + var a = aelements[i].href; + var slideID = a.match('\#slide[0-9]{1,2}'); + if ((slideID) && (slideID[0].slice(0,1) == '#')) { + var dest = findSlide(slideID[0].slice(1)); + if (dest != null) { + if (aelements[i].addEventListener) { + aelements[i].addEventListener("click", new Function("e", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "if (e.preventDefault) e.preventDefault();"), true); + } else if (aelements[i].attachEvent) { + aelements[i].attachEvent("onclick", new Function("", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "event.returnValue = false;")); + } + } + } + } +} + +function externalLinks() { + if (!document.getElementsByTagName) return; + var anchors = document.getElementsByTagName('a'); + for (var i=0; i<anchors.length; i++) { + var anchor = anchors[i]; + if (anchor.getAttribute('href') && hasValue(anchor.rel, 'external')) { + anchor.target = '_blank'; + addClass(anchor,'external'); + } + } +} + +function permaLink() { + document.getElementById('plink').href = window.location.pathname + '#slide' + snum; +} + +function createControls() { + var controlsDiv = document.getElementById("controls"); + if (!controlsDiv) return; + var hider = ' onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"'; + var hideDiv, hideList = ''; + if (controlVis == 'hidden') { + hideDiv = hider; + } else { + hideList = hider; + } + controlsDiv.innerHTML = '<form action="#" id="controlForm"' + hideDiv + '>' + + '<div id="navLinks">' + + '<a accesskey="n" id="show-notes" href="javascript:createNotesWindow();" title="Show Notes">≡<\/a>' + + '<a accesskey="t" id="toggle" href="javascript:toggle();">Ø<\/a>' + + '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' + + '<a accesskey="x" id="next" href="javascript:go(1);">»<\/a>' + + '<div id="navList"' + hideList + '><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>' + + '<\/div><\/form>'; + if (controlVis == 'hidden') { + var hidden = document.getElementById('navLinks'); + } else { + var hidden = document.getElementById('jumplist'); + } + addClass(hidden,'hideme'); +} + +function fontScale() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers + if (!s5mode) return false; + var vScale = 48; // both yield 16 (the usual browser default) at 1024x768 + var hScale = 64; // perhaps should auto-calculate based on theme's declared value? + if (window.innerHeight) { + var vSize = window.innerHeight; + var hSize = window.innerWidth; + } else if (document.documentElement.clientHeight) { + var vSize = document.documentElement.clientHeight; + var hSize = document.documentElement.clientWidth; + } else if (document.body.clientHeight) { + var vSize = document.body.clientHeight; + var hSize = document.body.clientWidth; + } else { + var vSize = 700; // assuming 1024x768, minus chrome and such + var hSize = 1024; // these do not account for kiosk mode or Opera Show + } + var newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale)); + fontSize(newSize + 'px'); + if (isGe) { // hack to counter incremental reflow bugs + var obj = document.getElementsByTagName('body')[0]; + obj.style.display = 'none'; + obj.style.display = 'block'; + } +} + +function fontSize(value) { + if (!(s5ss = document.getElementById('s5ss'))) { + if (!document.createStyleSheet) { + document.getElementsByTagName('head')[0].appendChild(s5ss = document.createElement('style')); + s5ss.setAttribute('media','screen, projection'); + s5ss.setAttribute('id','s5ss'); + } else { + document.createStyleSheet(); + document.s5ss = document.styleSheets[document.styleSheets.length - 1]; + } + } + if (!(document.s5ss && document.s5ss.addRule)) { + while (s5ss.lastChild) s5ss.removeChild(s5ss.lastChild); + s5ss.appendChild(document.createTextNode('html {font-size: ' + value + ' !important;}')); + } else { + document.s5ss.addRule('html','font-size: ' + value + ' !important;'); + } +} + +function notOperaFix() { + slideCSS = document.getElementById('slideProj').href; + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + slides.setAttribute('media','screen'); + outline.disabled = true; + if (isGe) { + slides.setAttribute('href','null'); // Gecko fix + slides.setAttribute('href',slideCSS); // Gecko fix + } + if (isIE && document.styleSheets && document.styleSheets[0]) { + document.styleSheets[0].addRule('img', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('div', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('.slide', 'behavior: url(ui/default/iepngfix.htc)'); + } +} + +function getIncrementals(obj) { + var incrementals = new Array(); + if (!obj) + return incrementals; + var children = obj.childNodes; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (hasClass(child, 'incremental')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'incremental'); + for (var j = 0; j < child.childNodes.length; j++) { + if (child.childNodes[j].nodeType == 1) { + addClass(child.childNodes[j], 'incremental'); + } + } + } else { + incrementals[incrementals.length] = child; + removeClass(child,'incremental'); + } + } + if (hasClass(child, 'show-first')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'show-first'); + if (child.childNodes[isGe].nodeType == 1) { + removeClass(child.childNodes[isGe], 'incremental'); + } + } else { + incrementals[incrementals.length] = child; + } + } + incrementals = incrementals.concat(getIncrementals(child)); + } + return incrementals; +} + +function createIncrementals() { + var incrementals = new Array(); + for (var i = 0; i < smax; i++) { + incrementals[i] = getIncrementals(document.getElementById('slide'+i)); + } + return incrementals; +} + +function defaultCheck() { + var allMetas = document.getElementsByTagName('meta'); + for (var i = 0; i< allMetas.length; i++) { + if (allMetas[i].name == 'defaultView') { + defaultView = allMetas[i].content; + } + if (allMetas[i].name == 'controlVis') { + controlVis = allMetas[i].content; + } + } +} + +// Key trap fix, new function body for trap() +function trap(e) { + if (!e) { + e = event; + e.which = e.keyCode; + } + try { + modifierKey = e.ctrlKey || e.altKey || e.metaKey; + } + catch(e) { + modifierKey = false; + } + return modifierKey || e.which == 0; +} + +function noteLabel() { // Gives notes id's to match parent slides + var notes = GetElementsWithClassName('div','notes'); + for (var i = 0; i < notes.length; i++) { + var note = notes[i]; + var id = 'note' + note.parentNode.id.substring(5); + note.setAttribute('id',id); + } + resetElapsedSlide(); + resetRemainingTime(); + window.setInterval('updateElaspedTime()', 1000); +} + +function createNotesWindow() { // creates a window for our notes + if (!s5NotesWindow || s5NotesWindow.closed) { // Create the window if it doesn't exist + s5NotesWindowLoaded = false; + // Note: Safari has a tendency to ignore window options preferring to default to the settings of the parent window, grr. + s5NotesWindow = window.open('ui/s5-notes.html', 's5NotesWindow', 'top=0,left=0'); + } + if (s5NotesWindowLoaded) { // Load the current note if the Note HTML has loaded + loadNote(); + } else { // Keep trying... + window.setTimeout('createNotesWindow()', 50); + } +} + +function loadNote() { +// Loads a note into the note window + var notes = nextNotes = '<em class="disclaimer">There are no notes for this slide.</em>'; + if (document.getElementById('note' + snum)) { + notes = document.getElementById('note' + snum).innerHTML; + } + if (document.getElementById('note' + (snum + 1))) { + nextNotes = document.getElementById('note' + (snum + 1)).innerHTML; + } + + var jl = document.getElementById('jumplist'); + var slideTitle = jl.options[jl.selectedIndex].text.replace(/^\d+\s+:\s+/, '') + ((jl.selectedIndex) ? ' (' + jl.selectedIndex + '/' + (smax - 1) + ')' : ''); + if (incrementals[snum].length > 0) { +// alert('howdy'); + slideTitle += ' <small>[' + incpos + '/' + incrementals[snum].length + ']</small>'; + } + if (jl.selectedIndex < smax - 1) { + var nextTitle = jl.options[jl.selectedIndex + 1].text.replace(/^\d+\s+:\s+/, '') + ((jl.selectedIndex + 1) ? ' (' + (jl.selectedIndex + 1) + '/' + (smax - 1) + ')' : ''); + } else { + var nextTitle = '[end of slide show]'; + } + + if (s5NotesWindow && !s5NotesWindow.closed && s5NotesWindow.document) { + s5NotesWindow.document.getElementById('slide').innerHTML = slideTitle; + s5NotesWindow.document.getElementById('notes').innerHTML = notes; + s5NotesWindow.document.getElementById('next').innerHTML = nextTitle; + s5NotesWindow.document.getElementById('nextnotes').innerHTML = nextNotes; + } + resetElapsedSlide(); +} + +function minimizeTimer(id) { + var obj = s5NotesWindow.document.getElementById(id); + if (hasClass(obj,'collapsed')) { + removeClass(obj,'collapsed'); + } else { + addClass(obj,'collapsed'); + } +} + +function resetElapsedTime() { + presentationStart = new Date(); + slideStart = new Date(); + updateElaspedTime(); +} + +function resetElapsedSlide() { + if (snum != previousSlide) { + slideStart = new Date(); + previousSlide = snum; + updateElaspedTime(); + } +} + +function updateElaspedTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var now = new Date(); + var ep = s5NotesWindow.document.getElementById('elapsed-presentation'); + var es = s5NotesWindow.document.getElementById('elapsed-slide'); + ep.innerHTML = formatTime(now.valueOf() - presentationStart.valueOf()); + es.innerHTML = formatTime(now.valueOf() - slideStart.valueOf()); +} + +function resetRemainingTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var startField = s5NotesWindow.document.getElementById('startFrom'); + startFrom = readTime(startField.value); + countdown.remaining = startFrom * 60000; // convert to msecs + countdown.start = new Date().valueOf(); + countdown.end = countdown.start + countdown.remaining; + var tl = s5NotesWindow.document.getElementById('timeLeft'); + var timeLeft = formatTime(countdown.remaining); + tl.innerHTML = timeLeft; +} + +function updateRemainingTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var tl = s5NotesWindow.document.getElementById('timeLeft'); + var now = new Date(); + if (countdown.state == 'run') { + countdown.remaining = countdown.end - now; + } + tl.style.color = ''; + tl.style.backgroundColor = ''; + if (countdown.remaining >= 0) { + var timeLeft = formatTime(countdown.remaining); + removeClass(tl,'overtime'); + if (countdown.remaining < 300000) { + tl.style.color = 'rgb(' + (255-Math.round(countdown.remaining/2000)) + ',0,0)'; + tl.style.backgroundColor = 'rgb(255,255,' + (Math.round(countdown.remaining/2000)) + ')'; + } + } else { + var timeLeft = '-' + formatTime(-countdown.remaining); + addClass(tl,'overtime'); + } + tl.innerHTML = timeLeft; +} + +function toggleRemainingTime() { + if (countdown.state == 'pause') countdown.state = 'run'; else countdown.state = 'pause'; + if (countdown.state == 'pause') { + window.clearInterval(countdown.timer); + } + if (countdown.state == 'run') { + countdown.start = new Date().valueOf(); + countdown.end = countdown.start + countdown.remaining; + countdown.timer = window.setInterval('updateRemainingTime()', 1000); + } +} + +function alterRemainingTime(amt) { + var change = amt * 60000; // convert to msecs + countdown.end += change; + countdown.remaining += change; + updateRemainingTime(); +} + +function formatTime(msecs) { + var time = new Date(msecs); + + var hrs = time.getUTCHours() + ((time.getUTCDate() -1) * 24); // I doubt anyone will spend more than 24 hours on a presentation or single slide but just in case... + hrs = (hrs < 10) ? '0'+hrs : hrs; + if (hrs == 'NaN' || isNaN(hrs)) hrs = '--'; + + var min = time.getUTCMinutes(); + min = (min < 10) ? '0'+min : min; + if (min == 'NaN' || isNaN(min)) min = '--'; + + var sec = time.getUTCSeconds(); + sec = (sec < 10) ? '0'+sec : sec; + if (sec == 'NaN' || isNaN(sec)) sec = '--'; + + return hrs + ':' + min + ':' + sec; +} + +function readTime(val) { + var sregex = /:/; + var matches = sregex.exec(val); + if (matches == null) { + return val; + } else { + var times = val.split(':'); + var hours = parseInt(times[0]); + var mins = parseInt(times[1]); + var total = (hours * 60) + mins; + return total; + } +} + +function windowChange() { + fontScale(); +} + +function startup() { + defaultCheck(); + createControls(); // hallvord + slideLabel(); + incrementals = createIncrementals(); + noteLabel(); // [SI:060104] must follow slideLabel() + loadNote(); + fixLinks(); + externalLinks(); + fontScale(); + if (!isOp) notOperaFix(); + slideJump(); + if (defaultView == 'outline') { + toggle(); + } + document.onkeyup = keys; + document.onkeypress = trap; + document.onclick = clicker; +} + +window.onload = startup; +window.onresize = function(){setTimeout('windowChange()',5);} \ No newline at end of file diff --git a/PTPW_2008/ui/moose/blank.gif b/PTPW_2008/ui/moose/blank.gif new file mode 100644 index 0000000..75b945d Binary files /dev/null and b/PTPW_2008/ui/moose/blank.gif differ diff --git a/PTPW_2008/ui/moose/bodybg.gif b/PTPW_2008/ui/moose/bodybg.gif new file mode 100755 index 0000000..5f448a1 Binary files /dev/null and b/PTPW_2008/ui/moose/bodybg.gif differ diff --git a/PTPW_2008/ui/moose/framing.css b/PTPW_2008/ui/moose/framing.css new file mode 100644 index 0000000..2a27daf --- /dev/null +++ b/PTPW_2008/ui/moose/framing.css @@ -0,0 +1,22 @@ +/* The following styles size, place, and layer the slide components. + Edit these if you want to change the overall slide layout. + The commented lines can be uncommented (and modified, if necessary) + to help you with the rearrangement process. */ + +/* target = 1024x768 */ + +div#header, div#footer, .slide {width: 100%; top: 0; left: 0;} +div#header {top: 0; height: 3em; z-index: 1;} +div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;} +.slide {top: 0; width: 92%; padding: 3.5em 4% 4%; z-index: 2; list-style: none;} +div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;} +div#controls form {text-align: right; width: 100%; margin: 0;} +#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; z-index: 10;} +html>body #currentSlide {position: fixed;} + +/* +div#header {background: #FCC;} +div#footer {background: #CCF;} +div#controls {background: #BBD;} +div#currentSlide {background: #FFC;} +*/ diff --git a/PTPW_2008/ui/moose/iepngfix.htc b/PTPW_2008/ui/moose/iepngfix.htc new file mode 100644 index 0000000..bba2db7 --- /dev/null +++ b/PTPW_2008/ui/moose/iepngfix.htc @@ -0,0 +1,42 @@ +<public:component> +<public:attach event="onpropertychange" onevent="doFix()" /> + +<script> + +// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com +// Free usage permitted as long as this notice remains intact. + +// This must be a path to a blank image. That's all the configuration you need here. +var blankImg = 'ui/default/blank.gif'; + +var f = 'DXImageTransform.Microsoft.AlphaImageLoader'; + +function filt(s, m) { + if (filters[f]) { + filters[f].enabled = s ? true : false; + if (s) with (filters[f]) { src = s; sizingMethod = m } + } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")'; +} + +function doFix() { + if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) || + (event && !/(background|src)/.test(event.propertyName))) return; + + if (tagName == 'IMG') { + if ((/\.png$/i).test(src)) { + filt(src, 'image'); // was 'scale' + src = blankImg; + } else if (src.indexOf(blankImg) < 0) filt(); + } else if (style.backgroundImage) { + if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) { + var s = RegExp.$1; + style.backgroundImage = ''; + filt(s, 'crop'); + } else filt(); + } +} + +doFix(); + +</script> +</public:component> \ No newline at end of file diff --git a/PTPW_2008/ui/moose/moose_watermark.gif b/PTPW_2008/ui/moose/moose_watermark.gif new file mode 100644 index 0000000..a67bafc Binary files /dev/null and b/PTPW_2008/ui/moose/moose_watermark.gif differ diff --git a/PTPW_2008/ui/moose/moose_watermark.png b/PTPW_2008/ui/moose/moose_watermark.png new file mode 100644 index 0000000..3963b59 Binary files /dev/null and b/PTPW_2008/ui/moose/moose_watermark.png differ diff --git a/PTPW_2008/ui/moose/notes.css b/PTPW_2008/ui/moose/notes.css new file mode 100644 index 0000000..5858cf2 --- /dev/null +++ b/PTPW_2008/ui/moose/notes.css @@ -0,0 +1,122 @@ +/* Following are the note styles -- edit away! */ + +body { + margin: 0; + padding: 1.0em; + background: #333; + color: #FFF; + font: 2em/1.4em 'Lucida Grande', Verdana, sans-serif; +} + +div.timers { + background: #FFF; + color: #333; + border: 0.08em solid #222; + border-top-width: 1px; + border-left-width: 1px; + float: left; + padding: 0.2em; + margin: 0 0 0.5em; + position: relative; +} + +div.timers h1 { + text-align: left; + font-size: 0.6em; + line-height: 1.4em; + background-color: #FF9; + padding: 0 0.75em; + margin: 0.25em 0 0; + border: 1px solid #EE8; +} + +div.timers div.controls { + position: absolute; + right: 0.25em; + top: 0.1em; + line-height: 1em; +} + +div.timers h1 a { + text-decoration: none; + color: #000; +} + +div.timers div.controls a { + font-size: 0.5em; + padding: 0; + color: #330; +} + +div.timers a.control { + position: absolute; + text-decoration: none; + padding: 0 0.25em; + color: #AAA; + outline: 0; +} + +#minus { + left: 0.25em; +} + +#plus { + right: 0.25em; +} + +.overtime { + background: yellow; + color: red; + border: 3px solid; + padding: 0.1em 0.25em; + font-weight: bold; +} + +div.timers h2 { + font-size: 0.6em; + line-height: 1.0em; + font-weight: normal; + margin: 0 0 -0.25em; + padding-top: 0.5em; + color: #666; +} + +div.timers p {margin: 0; padding: 0 0.5em;} +div.timers form {margin: 0;} + +div.timers span.clock { + font-family: monospace; +} + +div.timers ul {margin: 0; padding: 0; list-style: none;} +div.timers li {float: left; width: 5em; margin: 0; padding: 0 0.5em; + text-align: center;} + +div#elapsed {width: 12.1em;} +div#remaining {clear: left; width: 12.1em;} +div#remaining p {text-align: center;} + +#slide, +#next, +#notes, +#nextnotes { + font-size: 0.75em; + line-height: 1.4em; + clear: left; +/* max-width: 30.0em; */ + text-shadow: 0.1em 0.1em 0.1em #111; +} + +#next {margin-top: 2.5em;} +#next, #nextnotes { + color: #999; + font-size: 0.66em; +} + +em.disclaimer { + color: #666; +} + +div.collapsed h1 {display: block; font-size: 0.33em;} +div.collapsed h1 a {display: inline;} +div.collapsed * {display: none;} diff --git a/PTPW_2008/ui/moose/opera.css b/PTPW_2008/ui/moose/opera.css new file mode 100644 index 0000000..9e9d2a3 --- /dev/null +++ b/PTPW_2008/ui/moose/opera.css @@ -0,0 +1,7 @@ +/* DO NOT CHANGE THESE unless you really want to break Opera Show */ +.slide { + visibility: visible !important; + position: static !important; + page-break-before: always; +} +#slide0 {page-break-before: avoid;} diff --git a/PTPW_2008/ui/moose/outline.css b/PTPW_2008/ui/moose/outline.css new file mode 100644 index 0000000..62db519 --- /dev/null +++ b/PTPW_2008/ui/moose/outline.css @@ -0,0 +1,15 @@ +/* don't change this unless you want the layout stuff to show up in the outline view! */ + +.layout div, #footer *, #controlForm * {display: none;} +#footer, #controls, #controlForm, #navLinks, #toggle { + display: block; visibility: visible; margin: 0; padding: 0;} +#toggle {float: right; padding: 0.5em;} +html>body #toggle {position: fixed; top: 0; right: 0;} + +/* making the outline look pretty-ish */ + +#slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;} +#slide0 h1 {padding-top: 1.5em;} +.slide h1 {margin: 1.5em 0 0; padding-top: 0.25em; + border-top: 1px solid #888; border-bottom: 1px solid #AAA;} +#toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;} diff --git a/PTPW_2008/ui/moose/pretty.css b/PTPW_2008/ui/moose/pretty.css new file mode 100644 index 0000000..80fdf85 --- /dev/null +++ b/PTPW_2008/ui/moose/pretty.css @@ -0,0 +1,86 @@ +/* Following are the presentation styles -- edit away! */ + +body {background: #FFF url(moose_watermark.png) -16px 0 no-repeat; color: #000; font-size: 1.5em;} +:link, :visited {text-decoration: none; color: #3399cc;} +#controls :active {color: #333 !important;} +#controls :focus {outline: 1px dotted #227;} +h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;} +ul, pre {margin: 0; line-height: 1em;} +html, body {margin: 0; padding: 0;} + +blockquote, q {font-style: italic;} +blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;} +blockquote p {margin: 0;} +blockquote i {font-style: normal;} +blockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;} +blockquote b i {font-style: italic;} + +kbd {font-weight: bold; font-size: 1em;} +sup {font-size: smaller; line-height: 1px;} + +.slide code {font-size: 0.75em; padding: 2px 0.2em; font-weight: bold; color: #533;} +.slide code.bad, code del {color: red;} +.slide code.old {color: silver;} +.slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: #533; font-size: 90%;} +.slide pre code {font-size: 0.75em; margin-left: 5%; display: block; line-height: 1.25em;} +.slide ul {margin-left: 5%; margin-right: 7%; list-style: disc;} +.slide li {margin-top: 0.75em; margin-right: 0;} +.slide ul ul {line-height: 1;} +.slide ul ul li {margin: .2em; font-size: 85%; list-style: square;} +.slide img.leader {display: block; margin: 0 auto;} + +div#header, div#footer {background: #39c; color: #333; + font-family: Verdana, Helvetica, sans-serif;} +div#header {background: #3399cc url(moose_watermark.png) -16px 0 no-repeat; + line-height: 1px;} +div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;} +#footer h1, #footer h2 {display: block; padding: 0 1em;} +#footer h2 {font-style: italic;} + +div.long {font-size: 0.75em;} +.slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1; + margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap; + font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize; + color: #333;} +.slide h2 {position: absolute; top: 1.9em; left: 87px; z-index: 1; + margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap; + font: bold 120%/.7em Helvetica, sans-serif; text-transform: capitalize; + color: #333;} +.slide h3 {font-size: 130%;} +h1 abbr {font-variant: small-caps;} + +div#controls {position: absolute; left: 60%; bottom: 0; + width: 40%; + text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;} +html>body div#controls {position: fixed; padding: 0; top: auto;} +#controls #navLinks a {padding: 0; margin: 0 0.5em; + background: #3399cc; border: none; color: #333; + cursor: pointer;} +#controls #navList #jumplist {background: #DDD; color: #227;} + +#currentSlide {text-align: center; font-size: 0.5em; color: #333;} + +#slide0 {padding-top: 3.5em; font-size: 90%;} +#slide0 h1 {position: static; margin: 1em 0 0; padding: 0; + font: bold 2em Helvetica, sans-serif; white-space: normal; + color: #000; background: transparent;} +#slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;} +#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;} +#slide0 h4 {margin-top: 0; font-size: 1em;} + +ul.urls {list-style: none; display: inline; margin: 0;} +.urls li {display: inline; margin: 0;} +.note {display: none;} +.external {border-bottom: 1px dotted gray;} +html>body .external {border-bottom: none;} +.external:after {content: " \274F"; font-size: smaller; color: #77B;} + +.incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;} +img.incremental {visibility: hidden;} +.slide .current {color: #B02;} + + +/* diagnostics + +li:after {content: " [" attr(class) "]"; color: #F88;} + */ diff --git a/PTPW_2008/ui/moose/print.css b/PTPW_2008/ui/moose/print.css new file mode 100644 index 0000000..e7a71d1 --- /dev/null +++ b/PTPW_2008/ui/moose/print.css @@ -0,0 +1 @@ +/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */ .slide, ul {page-break-inside: avoid; visibility: visible !important;} h1 {page-break-after: avoid;} body {font-size: 12pt; background: white;} * {color: black;} #slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;} #slide0 h3 {margin: 0; padding: 0;} #slide0 h4 {margin: 0 0 0.5em; padding: 0;} #slide0 {margin-bottom: 3em;} h1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;} .extra {background: transparent !important;} div.extra, pre.extra, .example {font-size: 10pt; color: #333;} ul.extra a {font-weight: bold;} p.example {display: none;} #header {display: none;} #footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;} #footer h2, #controls {display: none;} /* The following rule keeps the layout stuff out of print. Remove at your own risk! */ .layout, .layout * {display: none !important;} \ No newline at end of file diff --git a/PTPW_2008/ui/moose/s5-core.css b/PTPW_2008/ui/moose/s5-core.css new file mode 100644 index 0000000..ad1530b --- /dev/null +++ b/PTPW_2008/ui/moose/s5-core.css @@ -0,0 +1,9 @@ +/* Do not edit or override these styles! The system will likely break if you do. */ + +div#header, div#footer, div#controls, .slide {position: absolute;} +html>body div#header, html>body div#footer, + html>body div#controls, html>body .slide {position: fixed;} +.handout, .notes {display: none;} +.layout {display: block;} +.slide, .hideme, .incremental {visibility: hidden;} +#slide0 {visibility: visible;} diff --git a/PTPW_2008/ui/moose/slides.css b/PTPW_2008/ui/moose/slides.css new file mode 100644 index 0000000..0786d7d --- /dev/null +++ b/PTPW_2008/ui/moose/slides.css @@ -0,0 +1,3 @@ +@import url(s5-core.css); /* required to make the slide show run at all */ +@import url(framing.css); /* sets basic placement and size of slide components */ +@import url(pretty.css); /* stuff that makes the slides look better than blah */ \ No newline at end of file diff --git a/PTPW_2008/ui/moose/slides.js b/PTPW_2008/ui/moose/slides.js new file mode 100644 index 0000000..ab2a4b2 --- /dev/null +++ b/PTPW_2008/ui/moose/slides.js @@ -0,0 +1,764 @@ +// S5 v1.2a1 slides.js -- released into the Public Domain +// +// Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information +// about all the wonderful and talented contributors to this code! + +var undef; +var slideCSS = ''; +var snum = 0; +var smax = 1; +var incpos = 0; +var number = undef; +var s5mode = true; +var defaultView = 'slideshow'; +var controlVis = 'visible'; + +var s5NotesWindow; +var s5NotesWindowLoaded = false; +var previousSlide = 0; +var presentationStart = new Date(); +var slideStart = new Date(); + +var countdown = { + timer: 0, + state: 'pause', + start: new Date(), + end: 0, + remaining: 0 +}; + + +var isIE = navigator.appName == 'Microsoft Internet Explorer' && navigator.userAgent.indexOf('Opera') < 1 ? 1 : 0; +var isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0; +var isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0; + +function hasClass(object, className) { + if (!object.className) return false; + return (object.className.search('(^|\\s)' + className + '(\\s|$)') != -1); +} + +function hasValue(object, value) { + if (!object) return false; + return (object.search('(^|\\s)' + value + '(\\s|$)') != -1); +} + +function removeClass(object,className) { + if (!object || !hasClass(object,className)) return; + object.className = object.className.replace(new RegExp('(^|\\s)'+className+'(\\s|$)'), RegExp.$1+RegExp.$2); +} + +function addClass(object,className) { + if (!object || hasClass(object, className)) return; + if (object.className) { + object.className += ' '+className; + } else { + object.className = className; + } +} + +function GetElementsWithClassName(elementName,className) { + var allElements = document.getElementsByTagName(elementName); + var elemColl = new Array(); + for (var i = 0; i< allElements.length; i++) { + if (hasClass(allElements[i], className)) { + elemColl[elemColl.length] = allElements[i]; + } + } + return elemColl; +} + +function isParentOrSelf(element, id) { + if (element == null || element.nodeName=='BODY') return false; + else if (element.id == id) return true; + else return isParentOrSelf(element.parentNode, id); +} + +function nodeValue(node) { + var result = ""; + if (node.nodeType == 1) { + var children = node.childNodes; + for (var i = 0; i < children.length; ++i) { + result += nodeValue(children[i]); + } + } + else if (node.nodeType == 3) { + result = node.nodeValue; + } + return(result); +} + +function slideLabel() { + var slideColl = GetElementsWithClassName('*','slide'); + var list = document.getElementById('jumplist'); + smax = slideColl.length; + for (var n = 0; n < smax; n++) { + var obj = slideColl[n]; + + var did = 'slide' + n.toString(); + obj.setAttribute('id',did); + +// if (isOp) continue; // Opera fix (hallvord) + + var otext = ''; + var menu = obj.firstChild; + if (!menu) continue; // to cope with empty slides + while (menu && menu.nodeType == 3) { + menu = menu.nextSibling; + } + if (!menu) continue; // to cope with slides with only text nodes + + var menunodes = menu.childNodes; + for (var o = 0; o < menunodes.length; o++) { + otext += nodeValue(menunodes[o]); + } + list.options[list.length] = new Option(n + ' : ' + otext, n); + } +} + +function currentSlide() { + var cs; + if (document.getElementById) { + cs = document.getElementById('currentSlide'); + } else { + cs = document.currentSlide; + } + cs.innerHTML = '<a id="plink" href="">' + + '<span id="csHere">' + snum + '<\/span> ' + + '<span id="csSep">\/<\/span> ' + + '<span id="csTotal">' + (smax-1) + '<\/span>' + + '<\/a>' + ; + if (snum == 0) { + cs.style.visibility = 'hidden'; + } else { + cs.style.visibility = 'visible'; + } +} + +function go(step) { + if (document.getElementById('slideProj').disabled || step == 0) return; + var jl = document.getElementById('jumplist'); + var cid = 'slide' + snum; + var ce = document.getElementById(cid); + if (incrementals[snum].length > 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + removeClass(incrementals[snum][i], 'current'); + removeClass(incrementals[snum][i], 'incremental'); + } + } + if (step != 'j') { + snum += step; + lmax = smax - 1; + if (snum > lmax) snum = lmax; + if (snum < 0) snum = 0; + } else + snum = parseInt(jl.value); + var nid = 'slide' + snum; + var ne = document.getElementById(nid); + if (!ne) { + ne = document.getElementById('slide0'); + snum = 0; + } + if (step < 0) {incpos = incrementals[snum].length} else {incpos = 0;} + if (incrementals[snum].length > 0 && incpos == 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + if (hasClass(incrementals[snum][i], 'current')) + incpos = i + 1; + else + addClass(incrementals[snum][i], 'incremental'); + } + } + if (incrementals[snum].length > 0 && incpos > 0) + addClass(incrementals[snum][incpos - 1], 'current'); + if (isOp) { //hallvord + location.hash = nid; + } else { + ce.style.visibility = 'hidden'; + ne.style.visibility = 'visible'; + } // /hallvord + jl.selectedIndex = snum; + currentSlide(); + loadNote(); + permaLink(); + number = undef; +} + +function goTo(target) { + if (target >= smax || target == snum) return; + go(target - snum); +} + +function subgo(step) { + if (step > 0) { + removeClass(incrementals[snum][incpos - 1],'current'); + removeClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos],'current'); + incpos++; + } else { + incpos--; + removeClass(incrementals[snum][incpos],'current'); + addClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos - 1],'current'); + } + loadNote(); +} + +function toggle() { + var slideColl = GetElementsWithClassName('*','slide'); + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + if (!slides.disabled) { + slides.disabled = true; + outline.disabled = false; + s5mode = false; + fontSize('1em'); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'visible'; + } + } else { + slides.disabled = false; + outline.disabled = true; + s5mode = true; + fontScale(); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'hidden'; + } + slideColl[snum].style.visibility = 'visible'; + } +} + +function showHide(action) { + var obj = GetElementsWithClassName('*','hideme')[0]; + switch (action) { + case 's': obj.style.visibility = 'visible'; break; + case 'h': obj.style.visibility = 'hidden'; break; + case 'k': + if (obj.style.visibility != 'visible') { + obj.style.visibility = 'visible'; + } else { + obj.style.visibility = 'hidden'; + } + break; + } +} + +// 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/) +function keys(key) { + if (!key) { + key = event; + key.which = key.keyCode; + } + if (key.which == 84) { + toggle(); + return; + } + if (s5mode) { + switch (key.which) { + case 10: // return + case 13: // enter + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + if(number != undef) { + goTo(number); + break; + } + case 32: // spacebar + case 34: // page down + case 39: // rightkey + case 40: // downkey + if(number != undef) { + go(number); + } else if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + break; + case 33: // page up + case 37: // leftkey + case 38: // upkey + if(number != undef) { + go(-1 * number); + } else if (!incrementals[snum] || incpos <= 0) { + go(-1); + } else { + subgo(-1); + } + break; + case 36: // home + goTo(0); + break; + case 35: // end + goTo(smax-1); + break; + case 67: // c + showHide('k'); + break; + case 78: // n + createNotesWindow(); + break; + } + if (key.which < 48 || key.which > 57) { + number = undef; + } else { + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + number = (((number != undef) ? number : 0) * 10) + (key.which - 48); + } + } + return false; +} + +function clicker(e) { + number = undef; + var target; + if (window.event) { + target = window.event.srcElement; + e = window.event; + } else target = e.target; + if (target.href != null || hasValue(target.rel, 'external') || isParentOrSelf(target, 'controls') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object')) return true; + if (!e.which || e.which == 1) { + if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + } +} + +function findSlide(hash) { + var target = null; + var slides = GetElementsWithClassName('*','slide'); + for (var i = 0; i < slides.length; i++) { + var targetSlide = slides[i]; + if ( (targetSlide.name && targetSlide.name == hash) + || (targetSlide.id && targetSlide.id == hash) ) { + target = targetSlide; + break; + } + } + while(target != null && target.nodeName != 'BODY') { + if (hasClass(target, 'slide')) { + return parseInt(target.id.slice(5)); + } + target = target.parentNode; + } + return null; +} + +function slideJump() { + if (window.location.hash == null) return; + var sregex = /^#slide(\d+)$/; + var matches = sregex.exec(window.location.hash); + var dest = null; + if (matches != null) { + dest = parseInt(matches[1]); + } else { + dest = findSlide(window.location.hash.slice(1)); + } + if (dest != null) + go(dest - snum); +} + +function fixLinks() { + var thisUri = window.location.href; + thisUri = thisUri.slice(0, thisUri.length - window.location.hash.length); + var aelements = document.getElementsByTagName('A'); + for (var i = 0; i < aelements.length; i++) { + var a = aelements[i].href; + var slideID = a.match('\#slide[0-9]{1,2}'); + if ((slideID) && (slideID[0].slice(0,1) == '#')) { + var dest = findSlide(slideID[0].slice(1)); + if (dest != null) { + if (aelements[i].addEventListener) { + aelements[i].addEventListener("click", new Function("e", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "if (e.preventDefault) e.preventDefault();"), true); + } else if (aelements[i].attachEvent) { + aelements[i].attachEvent("onclick", new Function("", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "event.returnValue = false;")); + } + } + } + } +} + +function externalLinks() { + if (!document.getElementsByTagName) return; + var anchors = document.getElementsByTagName('a'); + for (var i=0; i<anchors.length; i++) { + var anchor = anchors[i]; + if (anchor.getAttribute('href') && hasValue(anchor.rel, 'external')) { + anchor.target = '_blank'; + addClass(anchor,'external'); + } + } +} + +function permaLink() { + document.getElementById('plink').href = window.location.pathname + '#slide' + snum; +} + +function createControls() { + var controlsDiv = document.getElementById("controls"); + if (!controlsDiv) return; + var hider = ' onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"'; + var hideDiv, hideList = ''; + if (controlVis == 'hidden') { + hideDiv = hider; + } else { + hideList = hider; + } + controlsDiv.innerHTML = '<form action="#" id="controlForm"' + hideDiv + '>' + + '<div id="navLinks">' + + '<a accesskey="n" id="show-notes" href="javascript:createNotesWindow();" title="Show Notes">≡<\/a>' + + '<a accesskey="t" id="toggle" href="javascript:toggle();">Ø<\/a>' + + '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' + + '<a accesskey="x" id="next" href="javascript:go(1);">»<\/a>' + + '<div id="navList"' + hideList + '><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>' + + '<\/div><\/form>'; + if (controlVis == 'hidden') { + var hidden = document.getElementById('navLinks'); + } else { + var hidden = document.getElementById('jumplist'); + } + addClass(hidden,'hideme'); +} + +function fontScale() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers + if (!s5mode) return false; + var vScale = 48; // both yield 16 (the usual browser default) at 1024x768 + var hScale = 64; // perhaps should auto-calculate based on theme's declared value? + if (window.innerHeight) { + var vSize = window.innerHeight; + var hSize = window.innerWidth; + } else if (document.documentElement.clientHeight) { + var vSize = document.documentElement.clientHeight; + var hSize = document.documentElement.clientWidth; + } else if (document.body.clientHeight) { + var vSize = document.body.clientHeight; + var hSize = document.body.clientWidth; + } else { + var vSize = 700; // assuming 1024x768, minus chrome and such + var hSize = 1024; // these do not account for kiosk mode or Opera Show + } + var newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale)); + fontSize(newSize + 'px'); + if (isGe) { // hack to counter incremental reflow bugs + var obj = document.getElementsByTagName('body')[0]; + obj.style.display = 'none'; + obj.style.display = 'block'; + } +} + +function fontSize(value) { + if (!(s5ss = document.getElementById('s5ss'))) { + if (!document.createStyleSheet) { + document.getElementsByTagName('head')[0].appendChild(s5ss = document.createElement('style')); + s5ss.setAttribute('media','screen, projection'); + s5ss.setAttribute('id','s5ss'); + } else { + document.createStyleSheet(); + document.s5ss = document.styleSheets[document.styleSheets.length - 1]; + } + } + if (!(document.s5ss && document.s5ss.addRule)) { + while (s5ss.lastChild) s5ss.removeChild(s5ss.lastChild); + s5ss.appendChild(document.createTextNode('html {font-size: ' + value + ' !important;}')); + } else { + document.s5ss.addRule('html','font-size: ' + value + ' !important;'); + } +} + +function notOperaFix() { + slideCSS = document.getElementById('slideProj').href; + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + slides.setAttribute('media','screen'); + outline.disabled = true; + if (isGe) { + slides.setAttribute('href','null'); // Gecko fix + slides.setAttribute('href',slideCSS); // Gecko fix + } + if (isIE && document.styleSheets && document.styleSheets[0]) { + document.styleSheets[0].addRule('img', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('div', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('.slide', 'behavior: url(ui/default/iepngfix.htc)'); + } +} + +function getIncrementals(obj) { + var incrementals = new Array(); + if (!obj) + return incrementals; + var children = obj.childNodes; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (hasClass(child, 'incremental')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'incremental'); + for (var j = 0; j < child.childNodes.length; j++) { + if (child.childNodes[j].nodeType == 1) { + addClass(child.childNodes[j], 'incremental'); + } + } + } else { + incrementals[incrementals.length] = child; + removeClass(child,'incremental'); + } + } + if (hasClass(child, 'show-first')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'show-first'); + if (child.childNodes[isGe].nodeType == 1) { + removeClass(child.childNodes[isGe], 'incremental'); + } + } else { + incrementals[incrementals.length] = child; + } + } + incrementals = incrementals.concat(getIncrementals(child)); + } + return incrementals; +} + +function createIncrementals() { + var incrementals = new Array(); + for (var i = 0; i < smax; i++) { + incrementals[i] = getIncrementals(document.getElementById('slide'+i)); + } + return incrementals; +} + +function defaultCheck() { + var allMetas = document.getElementsByTagName('meta'); + for (var i = 0; i< allMetas.length; i++) { + if (allMetas[i].name == 'defaultView') { + defaultView = allMetas[i].content; + } + if (allMetas[i].name == 'controlVis') { + controlVis = allMetas[i].content; + } + } +} + +// Key trap fix, new function body for trap() +function trap(e) { + if (!e) { + e = event; + e.which = e.keyCode; + } + try { + modifierKey = e.ctrlKey || e.altKey || e.metaKey; + } + catch(e) { + modifierKey = false; + } + return modifierKey || e.which == 0; +} + +function noteLabel() { // Gives notes id's to match parent slides + var notes = GetElementsWithClassName('div','notes'); + for (var i = 0; i < notes.length; i++) { + var note = notes[i]; + var id = 'note' + note.parentNode.id.substring(5); + note.setAttribute('id',id); + } + resetElapsedSlide(); + resetRemainingTime(); + window.setInterval('updateElaspedTime()', 1000); +} + +function createNotesWindow() { // creates a window for our notes + if (!s5NotesWindow || s5NotesWindow.closed) { // Create the window if it doesn't exist + s5NotesWindowLoaded = false; + // Note: Safari has a tendency to ignore window options preferring to default to the settings of the parent window, grr. + s5NotesWindow = window.open('ui/s5-notes.html', 's5NotesWindow', 'top=0,left=0'); + } + if (s5NotesWindowLoaded) { // Load the current note if the Note HTML has loaded + loadNote(); + } else { // Keep trying... + window.setTimeout('createNotesWindow()', 50); + } +} + +function loadNote() { +// Loads a note into the note window + var notes = nextNotes = '<em class="disclaimer">There are no notes for this slide.</em>'; + if (document.getElementById('note' + snum)) { + notes = document.getElementById('note' + snum).innerHTML; + } + if (document.getElementById('note' + (snum + 1))) { + nextNotes = document.getElementById('note' + (snum + 1)).innerHTML; + } + + var jl = document.getElementById('jumplist'); + var slideTitle = jl.options[jl.selectedIndex].text.replace(/^\d+\s+:\s+/, '') + ((jl.selectedIndex) ? ' (' + jl.selectedIndex + '/' + (smax - 1) + ')' : ''); + if (incrementals[snum].length > 0) { +// alert('howdy'); + slideTitle += ' <small>[' + incpos + '/' + incrementals[snum].length + ']</small>'; + } + if (jl.selectedIndex < smax - 1) { + var nextTitle = jl.options[jl.selectedIndex + 1].text.replace(/^\d+\s+:\s+/, '') + ((jl.selectedIndex + 1) ? ' (' + (jl.selectedIndex + 1) + '/' + (smax - 1) + ')' : ''); + } else { + var nextTitle = '[end of slide show]'; + } + + if (s5NotesWindow && !s5NotesWindow.closed && s5NotesWindow.document) { + s5NotesWindow.document.getElementById('slide').innerHTML = slideTitle; + s5NotesWindow.document.getElementById('notes').innerHTML = notes; + s5NotesWindow.document.getElementById('next').innerHTML = nextTitle; + s5NotesWindow.document.getElementById('nextnotes').innerHTML = nextNotes; + } + resetElapsedSlide(); +} + +function minimizeTimer(id) { + var obj = s5NotesWindow.document.getElementById(id); + if (hasClass(obj,'collapsed')) { + removeClass(obj,'collapsed'); + } else { + addClass(obj,'collapsed'); + } +} + +function resetElapsedTime() { + presentationStart = new Date(); + slideStart = new Date(); + updateElaspedTime(); +} + +function resetElapsedSlide() { + if (snum != previousSlide) { + slideStart = new Date(); + previousSlide = snum; + updateElaspedTime(); + } +} + +function updateElaspedTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var now = new Date(); + var ep = s5NotesWindow.document.getElementById('elapsed-presentation'); + var es = s5NotesWindow.document.getElementById('elapsed-slide'); + ep.innerHTML = formatTime(now.valueOf() - presentationStart.valueOf()); + es.innerHTML = formatTime(now.valueOf() - slideStart.valueOf()); +} + +function resetRemainingTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var startField = s5NotesWindow.document.getElementById('startFrom'); + startFrom = readTime(startField.value); + countdown.remaining = startFrom * 60000; // convert to msecs + countdown.start = new Date().valueOf(); + countdown.end = countdown.start + countdown.remaining; + var tl = s5NotesWindow.document.getElementById('timeLeft'); + var timeLeft = formatTime(countdown.remaining); + tl.innerHTML = timeLeft; +} + +function updateRemainingTime() { + if (!s5NotesWindowLoaded || !s5NotesWindow || s5NotesWindow.closed) return; + var tl = s5NotesWindow.document.getElementById('timeLeft'); + var now = new Date(); + if (countdown.state == 'run') { + countdown.remaining = countdown.end - now; + } + tl.style.color = ''; + tl.style.backgroundColor = ''; + if (countdown.remaining >= 0) { + var timeLeft = formatTime(countdown.remaining); + removeClass(tl,'overtime'); + if (countdown.remaining < 300000) { + tl.style.color = 'rgb(' + (255-Math.round(countdown.remaining/2000)) + ',0,0)'; + tl.style.backgroundColor = 'rgb(255,255,' + (Math.round(countdown.remaining/2000)) + ')'; + } + } else { + var timeLeft = '-' + formatTime(-countdown.remaining); + addClass(tl,'overtime'); + } + tl.innerHTML = timeLeft; +} + +function toggleRemainingTime() { + if (countdown.state == 'pause') countdown.state = 'run'; else countdown.state = 'pause'; + if (countdown.state == 'pause') { + window.clearInterval(countdown.timer); + } + if (countdown.state == 'run') { + countdown.start = new Date().valueOf(); + countdown.end = countdown.start + countdown.remaining; + countdown.timer = window.setInterval('updateRemainingTime()', 1000); + } +} + +function alterRemainingTime(amt) { + var change = amt * 60000; // convert to msecs + countdown.end += change; + countdown.remaining += change; + updateRemainingTime(); +} + +function formatTime(msecs) { + var time = new Date(msecs); + + var hrs = time.getUTCHours() + ((time.getUTCDate() -1) * 24); // I doubt anyone will spend more than 24 hours on a presentation or single slide but just in case... + hrs = (hrs < 10) ? '0'+hrs : hrs; + if (hrs == 'NaN' || isNaN(hrs)) hrs = '--'; + + var min = time.getUTCMinutes(); + min = (min < 10) ? '0'+min : min; + if (min == 'NaN' || isNaN(min)) min = '--'; + + var sec = time.getUTCSeconds(); + sec = (sec < 10) ? '0'+sec : sec; + if (sec == 'NaN' || isNaN(sec)) sec = '--'; + + return hrs + ':' + min + ':' + sec; +} + +function readTime(val) { + var sregex = /:/; + var matches = sregex.exec(val); + if (matches == null) { + return val; + } else { + var times = val.split(':'); + var hours = parseInt(times[0]); + var mins = parseInt(times[1]); + var total = (hours * 60) + mins; + return total; + } +} + +function windowChange() { + fontScale(); +} + +function startup() { + defaultCheck(); + createControls(); // hallvord + slideLabel(); + incrementals = createIncrementals(); + noteLabel(); // [SI:060104] must follow slideLabel() + loadNote(); + fixLinks(); + externalLinks(); + fontScale(); + if (!isOp) notOperaFix(); + slideJump(); + if (defaultView == 'outline') { + toggle(); + } + document.onkeyup = keys; + document.onkeypress = trap; + document.onclick = clicker; +} + +window.onload = startup; +window.onresize = function(){setTimeout('windowChange()',5);} \ No newline at end of file diff --git a/PTPW_2008/ui/s5-notes.html b/PTPW_2008/ui/s5-notes.html new file mode 100644 index 0000000..5c6c4ca --- /dev/null +++ b/PTPW_2008/ui/s5-notes.html @@ -0,0 +1,64 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<!-- Do not edit this document! The system will likely break if you do. --> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Notes</title> +<link rel="stylesheet" href="default/notes.css" type="text/css" /> +<script type="text/javascript"> +// <![CDATA[ + document.onkeyup = opener.keys; + document.onkeypress = opener.trap; + document.onclick = opener.clicker; +// ]]> +</script> +</head> + +<body onload="opener.s5NotesWindowLoaded=true;" onunload="opener.s5NotesWindowLoaded=false;"> + + +<div class="timers" id="elapsed"> +<h1> +<a href="#" onclick="opener.minimizeTimer('elapsed'); return false;">Elapsed Time</a> +</h1> +<ul> +<li> +<h2>Presentation</h2> +<span class="clock" id="elapsed-presentation">00:00:00</span> +</li> +<li> +<h2>Current Slide</h2> +<span class="clock" id="elapsed-slide">00:00:00</span> +</li> +</ul> +<div class="controls"> +<a href="#reset-elapsed" onclick="opener.resetElapsedTime(); return false;" title="Reset Elapsed Time">|←</a> +</div> +</div> + +<div class="timers" id="remaining"> +<h1> +<a href="#" onclick="opener.minimizeTimer('remaining'); return false;">Remaining Time</a> +</h1> +<p> +<a href="#subtract-remaining" class="control" id="minus" onclick="opener.alterRemainingTime('-5'); return false;" title="Subtract 5 Minutes">-</a> +<span class="clock" id="timeLeft">00:00:00</span> +<a href="#add-remaining" class="control" id="plus" onclick="opener.alterRemainingTime('5'); return false;" title="Add 5 Minutes">+</a> +</p> +<div class="controls"> +<form action="#" onsubmit="opener.resetRemainingTime(); return false;"> +<input type="text" class="text" id="startFrom" value="0" size="4" maxlength="4" /> +<a href="#toggle-remaining" onclick="opener.toggleRemainingTime(); return false;" title="Pause/Run Remaining Time">||</a> +<a href="#reset-remaining" onclick="opener.resetRemainingTime(); return false;" title="Reset Remaining Time">|←</a> +</form> +</div> +</div> + +<h2 id="slide">...</h2> +<div id="notes"></div> + +<h2 id="next">...</h2> +<div id="nextnotes"></div> + +</body> +</html> diff --git a/beijing-perl-workshop-2008-moose.pdf b/beijing-perl-workshop-2008-moose.pdf new file mode 100644 index 0000000..4f45a38 Binary files /dev/null and b/beijing-perl-workshop-2008-moose.pdf differ diff --git a/css/style.css b/css/style.css new file mode 100644 index 0000000..ceb0228 --- /dev/null +++ b/css/style.css @@ -0,0 +1,79 @@ + +BODY { + font-family: Helvetica, Arial; + color: #FFFFFF; + margin: 0px; + font-size: 10pt; +} + +LI { + font-size: 10pt; + width: 80%; +} + +P { + font-size: 10pt; +} + +A { + font-size: 10pt; + color: #FFFFFF; +} + +A:hover { + color: #000000; +} + +#content { + padding-top: 0px; + padding-left: 30px; + padding-right: 20px; +} + +.description { + font-size: 12pt; +} + +.description a { + font-size: 12pt; +} + +.root_list { + list-style: none; + margin-left: -40; + line-height: 2.5em; +} + +.sub_list { + list-style: circle; + margin-left: 0; + line-height: 1em; + display: block; +} + +.list_header { + font-size: 18pt; + font-weight: bold; + color: #FFFFFF; + text-decoration: none; +} + +.list_sub_header { + list-style: none; + font-size: 14pt; + font-weight: bold; + line-height: 1.5em; + color: #FFFFFF; +} + +#line { + height: 1px; + background: #FFFFFF; +} + +.copyright { + font-size: 9pt; + color: #AB9974; + text-align: center; +} + diff --git a/images/a_moose.gif b/images/a_moose.gif new file mode 100644 index 0000000..d3e67b2 Binary files /dev/null and b/images/a_moose.gif differ diff --git a/images/bg.gif b/images/bg.gif new file mode 100644 index 0000000..0a11b7d Binary files /dev/null and b/images/bg.gif differ diff --git a/images/bookshelf.jpg b/images/bookshelf.jpg new file mode 100644 index 0000000..fd2e090 Binary files /dev/null and b/images/bookshelf.jpg differ diff --git a/images/bottom_left.jpg b/images/bottom_left.jpg new file mode 100644 index 0000000..cd32354 Binary files /dev/null and b/images/bottom_left.jpg differ diff --git a/images/bottom_right.jpg b/images/bottom_right.jpg new file mode 100644 index 0000000..8a9368e Binary files /dev/null and b/images/bottom_right.jpg differ diff --git a/images/class_mop_model.jpg b/images/class_mop_model.jpg new file mode 100644 index 0000000..6c017cb Binary files /dev/null and b/images/class_mop_model.jpg differ diff --git a/images/header.gif b/images/header.gif new file mode 100644 index 0000000..4911b0e Binary files /dev/null and b/images/header.gif differ diff --git a/images/header.jpg b/images/header.jpg new file mode 100644 index 0000000..66212a7 Binary files /dev/null and b/images/header.jpg differ diff --git a/images/logo.gif b/images/logo.gif new file mode 100644 index 0000000..8e976dc Binary files /dev/null and b/images/logo.gif differ diff --git a/images/moose-book.jpg b/images/moose-book.jpg new file mode 100644 index 0000000..08ae75b Binary files /dev/null and b/images/moose-book.jpg differ diff --git a/images/moose.gif b/images/moose.gif new file mode 100644 index 0000000..ae92c04 Binary files /dev/null and b/images/moose.gif differ diff --git a/images/mullets.jpg b/images/mullets.jpg new file mode 100644 index 0000000..8b7e09c Binary files /dev/null and b/images/mullets.jpg differ diff --git a/images/subtitle.gif b/images/subtitle.gif new file mode 100644 index 0000000..14ad0f9 Binary files /dev/null and b/images/subtitle.gif differ diff --git a/images/top_left.jpg b/images/top_left.jpg new file mode 100644 index 0000000..164f4cc Binary files /dev/null and b/images/top_left.jpg differ diff --git a/images/top_right.jpg b/images/top_right.jpg new file mode 100644 index 0000000..19c5ecf Binary files /dev/null and b/images/top_right.jpg differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..f8343f8 --- /dev/null +++ b/index.html @@ -0,0 +1,176 @@ +<html> +<head> +<title>Moose - A postmodern object system for Perl 5</title> +<link rel="stylesheet" href="css/style.css" type="text/css" /> +<script language="javascript"> +function show_section (section_name) { + var el = document.getElementById(section_name); + if (el.style.display == 'none') { + el.style.display = 'block'; + } + else { + el.style.display = 'none'; + } +} +</script> +</head> +<body bgcolor="#EDDBB4" topmargin="0" leftmargin="0"> + +<table cellspacing='0' cellpadding='0' border='0' align='center' width="600"> +<tr> +<td align="center"><img src="images/header.jpg" /></td> +</tr> +<tr> +<td bgcolor="#AB9974"> +<table width="100%" cellspacing='0' cellpadding='0' border='0'><tr> + <td><img src="images/top_left.jpg" alt="" width="21" height="21" border="0" /></td> + <td align="right"><img src="images/top_right.jpg" alt="" width="21" height="21" border="0" /></td> +</tr></table> + +<div id='content'> +<p class='description'> +Moose is a <a target="_blank" href="http://www.perl.com/pub/a/1999/03/pm.html">postmodern +object system</a> for Perl 5 that takes the tedium out of writing object-oriented Perl. +It borrows all the best features from Perl 6, CLOS (LISP), Smalltalk, Java, BETA, OCaml, +Ruby and more, while still keeping true to its Perl 5 roots. +</p> +<p class='description'> +Moose is <i>100% production ready</i> and in heavy use in a number of systems and growing every day. +Try it today! +</p> +<p> +<ul class="root_list"> + + <li><a class='list_header' onfocus='this.blur()' href='javascript:void(0)' onclick='show_section("download")'>Download</a></li> + <ul class="sub_list" id="download"> + <li class="list_sub_header">CPAN</li> + <ul> + <li><a target='_blank' href='http://search.cpan.org/dist/Moose/'>Moose</a></li> + <li><a target='_blank' href='http://search.cpan.org/dist/Task-Moose/'>Task::Moose</a> - A collection of excellent Moose extensions</li> + <li><a target='_blank' href='http://search.cpan.org/dist/Class-MOP/'>Class::MOP</a> - The underlying meta object protocol on which Moose is built</li> + <li><a target='_blank' href='http://search.cpan.org/search?query=MooseX&mode=all'>MooseX::*</a> - The Moose extensions</li> + <li><a target="_blank" href='http://cpants.perl.org/dist/used_by/Moose'>CPAN Modules which use Moose</a></li> + </ul> + <li class="list_sub_header">SVN</li> + <ul> + <li><a target='_blank' href='http://code2.0beta.co.uk/moose/svn/'>repository URL</li> + <li><a target='_blank' href='http://code2.0beta.co.uk/moose/svnweb/index.cgi/moose/'>SVN::Web view</a></li> + </ul> + </ul> + + <li><a class='list_header' onfocus='this.blur()' href='javascript:void(0)' onclick='show_section("support")'>Support</a></li> + <ul class="sub_list" id="support"> + <li>#moose on irc.perl.org</li> + <li>Subscribe to <a href="mailto:moose-subscribe@perl.org">moose@perl.org</a>, or read the <a target="_blank" href="http://news.gmane.org/gmane.comp.lang.perl.moose">gmane archive</a></li> + <li><a target="_blank" href='http://code2.0beta.co.uk/moose/svn/Moose-TM_bundle/trunk/'>Moose TextMate Bundle</a></li> + <li><a target="_blank" href='http://users.ox.ac.uk/~oliver/data/files/moose-quick-ref.pdf'>Moose Quick-Ref card</a></li> + </ul> + + <li><a class='list_header' onfocus='this.blur()' href='javascript:void(0)' onclick='show_section("articles")'>Articles</a></li> + <ul class="sub_list" id="articles"> + + <li><a target="_blank" href="http://broadcast.oreilly.com/2008/11/beginners-introduction-to-obje.html">chomatic suggests Moose and Mouse in his Beginners Introduction to Object-Oriented Programming with Perl article</a></li> + <li><a target="_blank" href="http://hanekomu.at/blog/articles/20080924-1137-dissecting_the_moose.html">Marcel (hanekomu) Grünauer is writing a series of blog posts as he explores Moose</a></li> + <li><a target="_blank" href="http://www.slideshare.net/Tim.Bunce/perl-myths-200802-with-notes/">Tim Bunce's excellent Perl Myths talk gives a shout out to Moose</a></li> + <li><a target="_blank" href="http://trombik.mine.nu/~cherry/w/index.php/2008/03/22/1202/oop-with-moose">trombik writes an introduction to Moose in Japanese</a></li> + <li><a target="_blank" href='http://draegtun.wordpress.com/2008/03/12/doodling-with-moose-part-1/'>Barry Walsh does an excellent comparison of Moose and Ruby (specifically the Doodle module)</a></li> + <li><a target="_blank" href='http://blog.jrock.us/articles/Myth:%20Moose%20is%20an%20unnecessary%20dependency.pod'>Jonathan Rockway discusses why Moose is a dependency worth having</a></li> + <li><a target="_blank" href='http://avatraxiom.livejournal.com/70947.html'>Max Kanat-Alexander (of Bugzilla fame) has some nice things to say about Moose</a></li> + <li><a target="_blank" href='http://www.perl.com/pub/a/2007/12/06/soto-11.html?page=3'>Larry mentioned Moose in this years State of the Onion speech</a></li> + <li>Matt Trout (of DBIx::Class and Catalyst fame) wrote a nice series of articles on writing a REPL for Perl using Moose.</li> + <ul> + <li><a target="_blank" href='http://chainsawblues.vox.com/library/post/a-perl-read-excute-print-loop-repl.html'>Writing a perl read-eval-print loop (REPL) - part 1</a></li> + <li><a target="_blank" href='http://chainsawblues.vox.com/library/post/writing-a-perl-read-eval-print-loop-repl---part-2.html'>Writing a perl REPL part 2 - a history plugin</a></li> + <li><a target="_blank" href='http://chainsawblues.vox.com/library/post/writing-a-perl-repl-part-3---lexical-environments.html'>Writing a perl REPL part 3 - lexical environments</a></li> + <li><a target="_blank" href='http://chainsawblues.vox.com/library/post/develrepl-part-4---script-options-rc-files-profiles-and-packaging.html'>Devel::REPL part 4 - script options, rc files and profiles</a></li> + </ul> + <li><a target="_blank" href='http://foo-magazin.de/#d18'>$foo Perl Magazine Winter 2007 has a Moose article</a></li> + <li>Randal Schwartz wrote a series of articles on Moose for Linux Magazine</li> + <ul> + <li><a target='_blank' href='http://www.stonehenge.com/merlyn/LinuxMag/col94.html'>The Moose is Flying (part 1) (LinuxMag)</a></li> + <li><a target='_blank' href='http://www.stonehenge.com/merlyn/LinuxMag/col95.html'>The Moose is Flying (part 2) (LinuxMag)</a></li> + </ul> + <li><a target='_blank' href='http://www.oreillynet.com/onlamp/blog/2006/06/cpan_module_review_classmop.html'>Class::MOP Review (OnLAMP)</a></li> + + </ul> + + <li><a class='list_header' onfocus='this.blur()' href='javascript:void(0)' onclick='show_section("presentations")'>Presentations</a></li> + <ul class="sub_list" id="presentations"> + + <li class="list_sub_header">2008 Conferences</li> + <ul> + <li><a target='_blank' href='beijing-perl-workshop-2008-moose.pdf'>Moose talk from Beijing Perl Workshop by sunnavy</a></li> + <li><a target='_blank' href='PPW-2008/moose.xul'>Moose talk from PPW 2008 by Stevan Little</a></li> + <li><a target='_blank' href='PPW-2008/moose-manager.xul'>Managers Guide to Moose talk from PPW 2008 by Stevan Little</a></li> + <li><a target='_blank' href='oscon/moose.xul'>Moose talk from OSCON 2008 by Stevan Little</a></li> + <li><a target='_blank' href='http://www.iinteractive.com/moose/Moose_YAPC_Asia_2008/practical_moose.html'>Nordic Perl Workshop 2008 talk by Yuval Kogman</a></li> + <li><a target='_blank' href='http://www.iinteractive.com/moose/Moose_YAPC_Asia_2008/practical_moose.html'>Nordic Perl Workshop 2008 talk by Yuval Kogman</a></li> + <li><a target='_blank' href='http://conferences.yapcasia.org/ya2008/talk/1017'>YAPC::Asia::2008 talk by Yuval Kogman</a> (slides + video)</li> + </ul> + + <li class="list_sub_header">2007 Conferences</li> + <ul> + <li><a target='_blank' href='ppw_roles_talk/roles.xul'>PPW 2007 - Horizontal Reuse with Moose::Role talk (by Stevan Little)</a></li> + <li><a target='_blank' href='ppw_moose_slides/start.html'>PPW 2007 - Moose talk (by Stevan Little)</a></li> + <li><a target='_blank' href='object_meta_programming_slides/slides/start.html'>YAPC::EU 2007 - Object Meta Programming talk (by Yuval Kogman)</a></li> + <li><a target='_blank' href='yapc_eu_2007_slides/start.html'>YAPC::EU 2007 - Moose talk (by Stevan Little)</a></li> + </ul> + + <li class="list_sub_header">2006 Conferences</li> + <ul> + <li><a target='_blank' href='http://utsl.gen.nz/talks/moose/start.html'>OSDC Melboure 2006 Moose talk (by Sam Vilain)</a></li> + <li><a target='_blank' href='slides/start.html'>YAPC::NA 2006 Moose talk (by Stevan Little)</a></li> + </ul> + + <li class="list_sub_header">Perl Mongers Groups</li> + <ul> + <li><a target="_blank" href="http://www.slideshare.net/dtreder/moose-527243">Doug Treder gave his Moose talk at the SPUG (Seattle Perl Users Group)</a></li> + <li><a target='_blank' href='http://www.slideshare.net/hakobe/moose'>Moose presenation at Kansai.pm by hakobe</a></li> + <li><a target='_blank' href='moose_120308.xul'>PDX.pm March 12, 2008 - Moose by Ben Hengst</a> (<a target='_blank' href='http://pdxpm.podasp.com/archive.html'>podcast</a>)</li> + <li><a target='_blank' href='http://chris.prather.org/talks/moose-intro-mpls/'>Minneapolis Perl Mongers - An Intro to Moose (by Chris Prather)</a> + <li><a target='_blank' href='http://houston.pm.org/talks/2007talks/0704Talk/slides/start.html'>Houston.pm 2007 Moose talk (by Robert Boone)</a></li> + <li><a target='_blank' href='perl_ny_seminar_slides/start.html'>Perl Seminar NY - Moose talk (by Stevan Little)</a></li> + </ul> + + </ul> + + <li><a class='list_header' onfocus='this.blur()' href='javascript:void(0)' onclick='show_section("misc")'>Misc.</a></li> + <ul class="sub_list" id="misc"> + + <li><a target="_blank" href='http://www.ohloh.net/projects/moose'>Moose on ohloh</a></li> + <li><a target='_blank' href='http://flickr.com/search/?w=all&q=moose+yapcna2006&m=tags'>Moose@YAPC on Flickr</a></li> + <li><a target='_blank' href='http://www.perlmonks.org/index.pl?node_id=610130'>Moose Poetry on PerlMonks</a></li> + <li><a target="_blank" href='images/class_mop_model.jpg'>Class::MOP object model diagram</a></li> + + </ul> +</ul> +</p> +<br/> +<br/> +</div> + +<table width="100%" cellspacing='0' cellpadding='0' border='0'><tr> + <td><img src="images/bottom_left.jpg" alt="" width="21" height="21" border="0" /></td> + <td align="right"><img src="images/bottom_right.jpg" alt="" width="21" height="21" border="0" /></td> +</tr></table> + +</td> +</tr> +<tr> +<td> + <br/> + <p class='copyright'> + Copyright © 2006 - 2008 Infinity Interactive + <br/><br/> + This library is free software; you can redistribute it <br/> + and/or modify it under the same terms as Perl itself. + </p> + <br/> + <br/> + <br/> +</td> +</tr> +</table> +</body> +</html> + diff --git a/index.old.html b/index.old.html new file mode 100644 index 0000000..af543c6 --- /dev/null +++ b/index.old.html @@ -0,0 +1,215 @@ +<html> +<head> +<title>Moose - A postmodern object system for Perl 5</title> +<script language="javascript"> +function show_section (section_name) { + var el = document.getElementById(section_name); + if (!el.style.display || el.style.display == 'block') { + el.style.display = 'none'; + } + else { + el.style.display = 'block'; + } +} + +var all_sections = ['download', 'support', 'articles', 'presentations', 'misc']; + +function toggle_all_sections () { + for (var i = 0; i < all_sections.length; i++) { + show_section(all_sections[i]); + } +} + +</script> +<style type="text/css"> + +BODY { + font-family: Helvetica, Arial; + color: #006666; + font-size: 10pt; +} + +LI { + font-size: 10pt; + width: 90%; +} + +P { + font-size: 10pt; +} + +A { + font-size: 10pt; + color: #006666; +} + +A:hover { + color: #003333; +} + +#logo { + position: absolute; + top: -5px; + left: 0px; +} + +#content { + background: #DCEEEE; + padding-left: 20px; + padding-right: 20px; +} + +.root_list { + list-style: none; + margin-left: -40; + line-height: 2.5em; +} + +.sub_list { + list-style: circle; + margin-left: 0; + line-height: 1.2em; + display: block; +} + +.list_header { + font-size: 18pt; + font-weight: bold; + color: #006666; + text-decoration: none; +} + +.list_sub_header { + list-style: none; + font-size: 12pt; + font-weight: bold; + color: #006666; +} + +#line { + height: 1px; + background: #339999; + position: relative; + top: -10px; +} + +.copyright { + font-size: 8pt; + color: #006666; + position: relative; + top: 15px; + margin-left: 110px; +} + +</style> +</head> +<body bgcolor="#ffffff" topmargin="0" leftmargin="0" onload="toggle_all_sections()"> +<div id='logo'> +<table cellspacing='0' cellpadding='0' width='100%' border='0'> +<tr> +<td background="images/logo.gif"><img src="images/spacer.gif" height="274" width="1" /></td> +</tr> +</table> +<table cellspacing='0' cellpadding='0' border='0'> +<tr> +<td><img src="images/spacer.gif" height="1" width="100" /></td> +<td valign="top" bgcolor="#DCEEEE" width="500"> +<div id='content'> +<p class='description'> +Moose is a <a target="_blank" href="http://www.perl.com/pub/a/1999/03/pm.html">postmodern +object system</a> for Perl 5 that takes the tedium out of writing object-oriented Perl. +It borrows all the best features from Perl 6, CLOS (LISP), Smalltalk, Java, BETA, OCaml, +Ruby and more, while still keeping true to its Perl 5 roots. +</p> +<p class='description'> +Moose is <i>100% production ready</i> and in heavy use in a number of systems and growing every day. +Try it today! +</p> +<p> + <ul class="root_list"> + <li><a class='list_header' onfocus='this.blur()' href='javascript:void(0)' onclick='show_section("download")'>Download</a></li> + <ul class="sub_list" id="download"> + <li class="list_sub_header">CPAN</li> + <ul> + <li><a target='_blank' href='http://search.cpan.org/~stevan/Moose/'>Moose</a></li> + <li><a target='_blank' href='http://search.cpan.org/~stevan/Class-MOP/'>Class::MOP</a></li> + <li><a target='_blank' href='http://search.cpan.org/search?query=MooseX&mode=all'>MooseX::*</a></li> + <li><a target='_blank' href='http://search.cpan.org/~stevan/Task-Moose/'>Task::Moose</a></li> + </ul> + <li class="list_sub_header">SVN</li> + <ul> + <li><a target='_blank' href='http://code2.0beta.co.uk/moose/svn/'>repository URL</li> + <li><a target='_blank' href='http://code2.0beta.co.uk/moose/svnweb/index.cgi/moose/'>SVN::Web view</a></li> + </ul> + </ul> + <li><a class='list_header' onfocus='this.blur()' href='javascript:void(0)' onclick='show_section("support")'>Support</a></li> + <ul class="sub_list" id="support"> + <li>#moose on irc.perl.org</li> + <li>Subscribe to <a href="mailto:moose-subscribe@perl.org">moose@perl.org</a>, or read the <a target="_blank" href="http://news.gmane.org/gmane.comp.lang.perl.moose">gmane archive</a></li> + <li><a target="_blank" href='http://code2.0beta.co.uk/moose/svn/Moose-TM_bundle/trunk/'>Moose TextMate Bundle</a></li> + <li><a target="_blank" href='http://users.ox.ac.uk/~oliver/data/files/moose-quick-ref.pdf'>Moose Quick-Ref card</a></li> + </ul> + <li><a class='list_header' onfocus='this.blur()' href='javascript:void(0)' onclick='show_section("articles")'>Articles</a></li> + <ul class="sub_list" id="articles"> + <li><a target='_blank' href='http://www.oreillynet.com/onlamp/blog/2006/06/cpan_module_review_classmop.html'>Class::MOP Review (OnLAMP)</a></li> + <li><a target='_blank' href='http://www.stonehenge.com/merlyn/LinuxMag/col94.html'>The Moose is Flying (part 1) (LinuxMag)</a></li> + <li><a target='_blank' href='http://www.stonehenge.com/merlyn/LinuxMag/col95.html'>The Moose is Flying (part 2) (LinuxMag)</a></li> + <li><a target="_blank" href='http://foo-magazin.de/#d18'>$foo Perl Magazine Winter 2007 has a Moose article</a></li> + <li>Matt Trout (of DBIx::Class and Catalyst fame) wrote a nice series of articles on writing a REPL for Perl using Moose.</li> + <ul> + <li><a target="_blank" href='http://chainsawblues.vox.com/library/post/a-perl-read-excute-print-loop-repl.html'>Writing a perl read-eval-print loop (REPL) - part 1</a></li> + <li><a target="_blank" href='http://chainsawblues.vox.com/library/post/writing-a-perl-read-eval-print-loop-repl---part-2.html'>Writing a perl REPL part 2 - a history plugin</a></li> + <li><a target="_blank" href='http://chainsawblues.vox.com/library/post/writing-a-perl-repl-part-3---lexical-environments.html'>Writing a perl REPL part 3 - lexical environments</a></li> + <li><a target="_blank" href='http://chainsawblues.vox.com/library/post/develrepl-part-4---script-options-rc-files-profiles-and-packaging.html'>Devel::REPL part 4 - script options, rc files and profiles</a></li> + </ul> + <li><a target="_blank" href='http://www.perl.com/pub/a/2007/12/06/soto-11.html?page=3'>Larry mentioned Moose in this years State of the Onion speech</a></li> + <li><a target="_blank" href='http://avatraxiom.livejournal.com/70947.html'>Max Kanat-Alexander (of Bugzilla fame) has some nice things to say about Moose</a></li> + <li><a target="_blank" href='http://blog.jrock.us/articles/Myth:%20Moose%20is%20an%20unnecessary%20dependency.pod'>Jonathan Rockway discusses why Moose is a dependency worth having</a></li> + <li><a target="_blank" href='http://draegtun.wordpress.com/2008/03/12/doodling-with-moose-part-1/'>Barry Walsh does an excellent comparison of Moose and Ruby (specifically the Doodle module)</a></li> + <li><a target="_blank" href="http://trombik.mine.nu/~cherry/w/index.php/2008/03/22/1202/oop-with-moose">trombik writes an introduction to Moose in Japanese</a></li> + <li><a target="_blank" href="http://www.slideshare.net/Tim.Bunce/perl-myths-200802-with-notes/">Tim Bunce's excellent Perl Myths talk gives a shout out to Moose</a></li> + </ul> + <li><a class='list_header' onfocus='this.blur()' href='javascript:void(0)' onclick='show_section("presentations")'>Presentations</a></li> + <ul class="sub_list" id="presentations"> + <li><a target='_blank' href='slides/start.html'>YAPC::NA 2006 Moose talk (by Stevan Little)</a></li> + <li><a target='_blank' href='http://utsl.gen.nz/talks/moose/start.html'>OSDC Melboure 2006 Moose talk (by Sam Vilain)</a></li> + <li><a target='_blank' href='http://houston.pm.org/talks/2007talks/0704Talk/slides/start.html'>Houston.pm 2007 Moose talk (by Robert Boone)</a></li> + <li><a target='_blank' href='perl_ny_seminar_slides/start.html'>Perl Seminar NY - Moose talk (by Stevan Little)</a></li> + <li><a target='_blank' href='http://chris.prather.org/talks/moose-intro-mpls/'>Minneapolis Perl Mongers - An Intro to Moose (by Chris Prather)</a> + <li><a target='_blank' href='yapc_eu_2007_slides/start.html'>YAPC::EU 2007 - Moose talk (by Stevan Little)</a></li> + <li><a target='_blank' href='object_meta_programming_slides/slides/start.html'>YAPC::EU 2007 - Object Meta Programming talk (by Yuval Kogman)</a></li> + <li><a target='_blank' href='ppw_moose_slides/start.html'>PPW 2007 - Moose talk (by Stevan Little)</a></li> + <li><a target='_blank' href='ppw_roles_talk/roles.xul'>PPW 2007 - Horizontal Reuse with Moose::Role talk (by Stevan Little)</a></li> + <li><a target='_blank' href='moose_120308.xul'>PDX.pm March 12, 2008 - Moose by Ben Hengst</a> (<a target='_blank' href='http://pdxpm.podasp.com/archive.html'>podcast</a>)</li> + <li><a target='_blank' href='http://conferences.yapcasia.org/ya2008/talk/1017'>YAPC::Asia::2008 talk by Yuval Kogman</a> (slides + video)</li> + <li><a target='_blank' href='http://www.iinteractive.com/moose/Moose_YAPC_Asia_2008/practical_moose.html'>Nordic Perl Workshop 2008 talk by Yuval Kogman</a></li> + <li><a target='_blank' href='http://www.slideshare.net/hakobe/moose'>Moose presenation at Kansai.pm by hakobe</a></li> + </ul> + <li><a class='list_header' onfocus='this.blur()' href='javascript:void(0)' onclick='show_section("misc")'>Misc.</a></li> + <ul class="sub_list" id="misc"> + <li><a target="_blank" href='http://www.ohloh.net/projects/moose'>Moose on ohloh</a></li> + <li><a target='_blank' href='http://flickr.com/search/?w=all&q=moose+yapcna2006&m=tags'>Moose@YAPC on Flickr</a></li> + <li><a target='_blank' href='http://www.perlmonks.org/index.pl?node_id=610130'>Moose Poetry on PerlMonks</a></li> + <li><a target="_blank" href='images/class_mop_model.jpg'>Class::MOP object model diagram</a></li> + </ul> + </ul> +</p> +<br/> +<br/> +</div> +</td> +</tr> +</table> +<div id="line" /> +<p class='copyright'> +Copyright © 2006 - 2008 Infinity Interactive +<br/><br/> +This library is free software; you can redistribute it <br/> +and/or modify it under the same terms as Perl itself. +</p> +<br/> +<br/> +<br/> +</div> +</body> +</html> diff --git a/index.old2.html b/index.old2.html new file mode 100644 index 0000000..6b11a7e --- /dev/null +++ b/index.old2.html @@ -0,0 +1,210 @@ +<html> +<head> +<title>Moose - A postmodern object system for Perl 5</title> +<script language="javascript"> +function show_section (section_name) { + var el = document.getElementById(section_name); + if (el.style.display == 'none') { + el.style.display = 'block'; + } + else { + el.style.display = 'none'; + } +} +</script> +<style type="text/css"> + +BODY { + font-family: Helvetica, Arial; + color: #FFFFFF; + margin: 0px; + font-size: 10pt; +} + +LI { + font-size: 10pt; + width: 80%; +} + +P { + font-size: 10pt; +} + +A { + font-size: 10pt; + color: #FFFFFF; +} + +A:hover { + color: #000000; +} + +#content { + padding-top: 10px; + padding-left: 30px; + padding-right: 30px; +} + +.description { + font-size: 12pt; +} + +.description a { + font-size: 12pt; +} + +.root_list { + list-style: none; + margin-left: -40; + line-height: 2.5em; +} + +.sub_list { + list-style: circle; + margin-left: 0; + line-height: 1em; + display: block; +} + +.list_header { + font-size: 18pt; + font-weight: bold; + color: #FFFFFF; + text-decoration: none; +} + +.list_sub_header { + list-style: none; + font-size: 14pt; + font-weight: bold; + color: #FFFFFF; +} + +#line { + height: 1px; + background: #FFFFFF; +} + +.copyright { + font-size: 9pt; + color: #FFFFFF; + padding-left: 30px; +} + +</style> +</head> +<body bgcolor="#ffffff" topmargin="0" leftmargin="0"> + +<table cellspacing='0' cellpadding='0' border='0' align='center' width="700"> +<tr> +<td><img src="images/header.gif" /></td> +</tr> +<tr> +<td align="center" bgcolor="#660000" height="60"><img src="images/subtitle.gif" /></td> +</tr> +<tr> +<td bgcolor="#848E90"> + <div id='content'> + <p class='description'> + Moose is a <a target="_blank" href="http://www.perl.com/pub/a/1999/03/pm.html">postmodern + object system</a> for Perl 5 that takes the tedium out of writing object-oriented Perl. + It borrows all the best features from Perl 6, CLOS (LISP), Smalltalk, Java, BETA, OCaml, + Ruby and more, while still keeping true to its Perl 5 roots. + </p> + <p class='description'> + Moose is <i>100% production ready</i> and in heavy use in a number of systems and growing every day. + Try it today! + </p> + <p> +<ul class="root_list"> +<li><a class='list_header' onfocus='this.blur()' href='javascript:void(0)' onclick='show_section("download")'>Download</a></li> +<ul class="sub_list" id="download"> + <li class="list_sub_header">CPAN</li> + <ul> + <li><a target='_blank' href='http://search.cpan.org/~stevan/Moose/'>Moose</a></li> + <li><a target='_blank' href='http://search.cpan.org/~stevan/Class-MOP/'>Class::MOP</a></li> + <li><a target='_blank' href='http://search.cpan.org/search?query=MooseX&mode=all'>MooseX::*</a></li> + <li><a target='_blank' href='http://search.cpan.org/~stevan/Task-Moose/'>Task::Moose</a></li> + </ul> + <li class="list_sub_header">SVN</li> + <ul> + <li><a target='_blank' href='http://code2.0beta.co.uk/moose/svn/'>repository URL</li> + <li><a target='_blank' href='http://code2.0beta.co.uk/moose/svnweb/index.cgi/moose/'>SVN::Web view</a></li> + </ul> +</ul> +<li><a class='list_header' onfocus='this.blur()' href='javascript:void(0)' onclick='show_section("support")'>Support</a></li> +<ul class="sub_list" id="support"> + <li>#moose on irc.perl.org</li> + <li>Subscribe to <a href="mailto:moose-subscribe@perl.org">moose@perl.org</a>, or read the <a target="_blank" href="http://news.gmane.org/gmane.comp.lang.perl.moose">gmane archive</a></li> + <li><a target="_blank" href='http://code2.0beta.co.uk/moose/svn/Moose-TM_bundle/trunk/'>Moose TextMate Bundle</a></li> + <li><a target="_blank" href='http://users.ox.ac.uk/~oliver/data/files/moose-quick-ref.pdf'>Moose Quick-Ref card</a></li> +</ul> +<li><a class='list_header' onfocus='this.blur()' href='javascript:void(0)' onclick='show_section("articles")'>Articles</a></li> +<ul class="sub_list" id="articles"> + <li><a target='_blank' href='http://www.oreillynet.com/onlamp/blog/2006/06/cpan_module_review_classmop.html'>Class::MOP Review (OnLAMP)</a></li> +<li><a target='_blank' href='http://www.stonehenge.com/merlyn/LinuxMag/col94.html'>The Moose is Flying (part 1) (LinuxMag)</a></li> +<li><a target='_blank' href='http://www.stonehenge.com/merlyn/LinuxMag/col95.html'>The Moose is Flying (part 2) (LinuxMag)</a></li> +<li><a target="_blank" href='http://foo-magazin.de/#d18'>$foo Perl Magazine Winter 2007 has a Moose article</a></li> +<li>Matt Trout (of DBIx::Class and Catalyst fame) wrote a nice series of articles on writing a REPL for Perl using Moose.</li> +<ul> + <li><a target="_blank" href='http://chainsawblues.vox.com/library/post/a-perl-read-excute-print-loop-repl.html'>Writing a perl read-eval-print loop (REPL) - part 1</a></li> + <li><a target="_blank" href='http://chainsawblues.vox.com/library/post/writing-a-perl-read-eval-print-loop-repl---part-2.html'>Writing a perl REPL part 2 - a history plugin</a></li> + <li><a target="_blank" href='http://chainsawblues.vox.com/library/post/writing-a-perl-repl-part-3---lexical-environments.html'>Writing a perl REPL part 3 - lexical environments</a></li> + <li><a target="_blank" href='http://chainsawblues.vox.com/library/post/develrepl-part-4---script-options-rc-files-profiles-and-packaging.html'>Devel::REPL part 4 - script options, rc files and profiles</a></li> +</ul> +<li><a target="_blank" href='http://www.perl.com/pub/a/2007/12/06/soto-11.html?page=3'>Larry mentioned Moose in this years State of the Onion speech</a></li> +<li><a target="_blank" href='http://avatraxiom.livejournal.com/70947.html'>Max Kanat-Alexander (of Bugzilla fame) has some nice things to say about Moose</a></li> +<li><a target="_blank" href='http://blog.jrock.us/articles/Myth:%20Moose%20is%20an%20unnecessary%20dependency.pod'>Jonathan Rockway discusses why Moose is a dependency worth having</a></li> +<li><a target="_blank" href='http://draegtun.wordpress.com/2008/03/12/doodling-with-moose-part-1/'>Barry Walsh does an excellent comparison of Moose and Ruby (specifically the Doodle module)</a></li> +<li><a target="_blank" href="http://trombik.mine.nu/~cherry/w/index.php/2008/03/22/1202/oop-with-moose">trombik writes an introduction to Moose in Japanese</a></li> +<li><a target="_blank" href="http://www.slideshare.net/Tim.Bunce/perl-myths-200802-with-notes/">Tim Bunce's excellent Perl Myths talk gives a shout out to Moose</a></li> + </ul> + <li><a class='list_header' onfocus='this.blur()' href='javascript:void(0)' onclick='show_section("presentations")'>Presentations</a></li> + <ul class="sub_list" id="presentations"> + <li><a target='_blank' href='slides/start.html'>YAPC::NA 2006 Moose talk (by Stevan Little)</a></li> + <li><a target='_blank' href='http://utsl.gen.nz/talks/moose/start.html'>OSDC Melboure 2006 Moose talk (by Sam Vilain)</a></li> + <li><a target='_blank' href='http://houston.pm.org/talks/2007talks/0704Talk/slides/start.html'>Houston.pm 2007 Moose talk (by Robert Boone)</a></li> + <li><a target='_blank' href='perl_ny_seminar_slides/start.html'>Perl Seminar NY - Moose talk (by Stevan Little)</a></li> + <li><a target='_blank' href='http://chris.prather.org/talks/moose-intro-mpls/'>Minneapolis Perl Mongers - An Intro to Moose (by Chris Prather)</a> + <li><a target='_blank' href='yapc_eu_2007_slides/start.html'>YAPC::EU 2007 - Moose talk (by Stevan Little)</a></li> + <li><a target='_blank' href='object_meta_programming_slides/slides/start.html'>YAPC::EU 2007 - Object Meta Programming talk (by Yuval Kogman)</a></li> + <li><a target='_blank' href='ppw_moose_slides/start.html'>PPW 2007 - Moose talk (by Stevan Little)</a></li> + <li><a target='_blank' href='ppw_roles_talk/roles.xul'>PPW 2007 - Horizontal Reuse with Moose::Role talk (by Stevan Little)</a></li> + <li><a target='_blank' href='moose_120308.xul'>PDX.pm March 12, 2008 - Moose by Ben Hengst</a> (<a target='_blank' href='http://pdxpm.podasp.com/archive.html'>podcast</a>)</li> + <li><a target='_blank' href='http://conferences.yapcasia.org/ya2008/talk/1017'>YAPC::Asia::2008 talk by Yuval Kogman</a> (slides + video)</li> + <li><a target='_blank' href='http://www.iinteractive.com/moose/Moose_YAPC_Asia_2008/practical_moose.html'>Nordic Perl Workshop 2008 talk by Yuval Kogman</a></li> + <li><a target='_blank' href='http://www.slideshare.net/hakobe/moose'>Moose presenation at Kansai.pm by hakobe</a></li> + <li><a target="_blank" href="http://www.slideshare.net/dtreder/moose-527243">Doug Treder gave his Moose talk at the SPUG (Seattle Perl Users Group)</a></li> + <li><a target='_blank' href='oscon/moose.xul'>Moose talk from OSCON 2008 by Stevan Little</a></li> + </ul> + <li><a class='list_header' onfocus='this.blur()' href='javascript:void(0)' onclick='show_section("misc")'>Misc.</a></li> + <ul class="sub_list" id="misc"> + <li><a target="_blank" href='http://www.ohloh.net/projects/moose'>Moose on ohloh</a></li> + <li><a target='_blank' href='http://flickr.com/search/?w=all&q=moose+yapcna2006&m=tags'>Moose@YAPC on Flickr</a></li> + <li><a target='_blank' href='http://www.perlmonks.org/index.pl?node_id=610130'>Moose Poetry on PerlMonks</a></li> + <li><a target="_blank" href='images/class_mop_model.jpg'>Class::MOP object model diagram</a></li> + </ul> +</ul> + </p> + <br/> + <br/> + </div> +</td> +</tr> +<tr> +<td bgcolor="#848E90"> + <div id="line"></div> + <p class='copyright'> + Copyright © 2006 - 2008 Infinity Interactive + <br/><br/> + This library is free software; you can redistribute it <br/> + and/or modify it under the same terms as Perl itself. + </p> + <br/> + <br/> + <br/> +</td> +</tr> +</table> +</body> +</html> diff --git a/moose2.jpg b/moose2.jpg new file mode 100644 index 0000000..9ae5d86 Binary files /dev/null and b/moose2.jpg differ diff --git a/moose_120308.xul b/moose_120308.xul new file mode 100644 index 0000000..8ad839a --- /dev/null +++ b/moose_120308.xul @@ -0,0 +1,4058 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 髿©ã¡ã½ãããªãã¬ã¼ã³ãã¼ã« in XUL ãªã¿ã¼ã³ãº + made by Piro + http://piro.sakura.ne.jp/ + + based on + 髿©ã¡ã½ãããªãã¬ã¼ã³ä½æãã¼ã« ver.2 made by mala + http://la.ma.la/blog/diary_200504080545.htm + ãããã¡ã½ãããªãã¬ã¼ã³ä½æãã¼ã« made by mala + http://la.ma.la/blog/diary_200505310749.htm +--> + +<!-- ***** BEGIN LICENSE BLOCK ***** + - Version: MPL 1.1 + - + - The contents of this file are subject to the Mozilla Public License Version + - 1.1 (the "License"); you may not use this file except in compliance with + - the License. You may obtain a copy of the License at + - http://www.mozilla.org/MPL/ + - + - Software distributed under the License is distributed on an "AS IS" basis, + - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + - for the specific language governing rights and limitations under the + - License. + - + - The Original Code is the Takahashi-Method-based Presentation Tool + - in XUL/Returns. + - + - The Initial Developer of the Original Code is SHIMODA Hiroshi. + - Portions created by the Initial Developer are Copyright (C) 2005-2007 + - the Initial Developer. All Rights Reserved. + - + - Contributor(s): SHIMODA Hiroshi <piro@p.club.ne.jp> + - dynamis <dynamis@mozilla-japan.org> + - matobaa <matobaa@lily.freemail.ne.jp> + - + - ***** END LICENSE BLOCK ***** --> + +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<?xml-stylesheet href="#builtinStyle" type="text/css"?> + +<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + id="presentation" + xmlns:html="http://www.w3.org/1999/xhtml" + orient="vertical" + onkeypress="Presentation.onKeyPress(event);"> + +<!-- Built-in Content --> +<html:textarea id="builtinCode" style="visibility: collapse"> +TITLE::Moose in the wild +GLOBAL-SIZE::9 +riding +wild +Moose + +---- +%%%%EM:Moose%%%%? + +---- +hype: + +---- +'postmodern' +object +system +for Perl 5 +<!-- +theres an explanation on the cpan page... It's a ref to Larry talking about perl as a postmodern language... let's move on. +--> + +---- +reality: + +---- +'academically' +correct +p5 OO +<!-- +by 'borrowing' features +from other OO systems +- Lisp/CLOS +- Perl6 +- ... ect +- I do not really know these that well so I can not really speak to there cribbed features +--> + +---- +so what? +<!-- +%%%%IMG src="http://bp2.blogger.com/_dH0q9hvpVHg/R86WXUE5b2I/AAAAAAAABh4/N9A5fc5KPnI/s320/thumb.jpg" height='*' width='*' %%%% +--> + +---- +my concept +of OO was +~off~ +<!-- +For me the biggest thing was to strictly wrap my head on how OO was ~meant~ to be. +I have an art school background, I missed out on all the CS OO classes. +I had been thinking of OO backwards +--> + +---- +package as a +collection of subs +with access to +common data +<!-- +My pre-moose days had a really hard time with OO. I understood the basics +like a $car has $wheels, ect. But things were very fuzzy in my head. +It's not really wrong, per say, but it's just not a very clear way to see the world. +Basically my OO world view said that $car $wheels were completely different from $bike $wheels +--> + +---- +moose changed +all that for me +<!-- +Moose really flipped things for me. +It forced me to think of objects as attributes and subs that modify them. +--> + +---- +build +objects +by attributes +<!-- +It made me focus on the $wheels as the thing that defines the $car or the $bike. +It's easy to talk about but, but for me, it was a completely different way to think about my code. +--> + + +---- +different? +how? +<!-- +a quick blow thru on what features you will be hearing more about +--> + + +---- +%%%%PRE: +use strict; +use warnings; +%%%% +included +by default +<!-- +first, simple things, like why should some one opt-in for the proper way to do something? +--> + +---- +%%%%PRE: +sub new {} +%%%% +built-in +<!-- +ever get tired of writing the same 7 lines of code, now you don't have to. +--> + +---- +free +accessors +<!-- +once you define an attribute, why not have a getter/setter built for you? +--> + +---- +types +<!-- +Extend the basic perl data types to be much more specific +--> + +---- +roles +<!-- +Hello eye opeining experence. +--> + +---- +... ehh, not convinced +I'd have to see it in action. +<!-- +don't worry it took me a while to wrap my head around all of this stuff too +--> + +---- +what does Moose look like? +<!-- +let's look at some code +--> + +---- +let's define +a simple +example: +<!-- +really simple example, but it will illustrate the general overview. +--> + +---- +describe +a moose +(the animal) + +---- +moose +have +names + +---- +if no name +is given +default to +'Bullwinkle' + +---- +%%%%PRE: +my $bullwinkle = + Animal::Moose->new; +print $bullwinkle->name; + # 'Bullwinkle' + +my $skippy = + Animal::Moose->new( name => 'Skippy' ) +print $skippy->name; + # 'Skippy' +%%%% +<!-- +yup thats what we want, now let's take a look at what Animal::Moose looks like. +--> + +---- +pre-Moose: +%%%%PRE: +package Animal::Moose; +use strict; +use warnings; + +sub new { + my ($class, %opts) = @_; + my $self = { + name => $opts{name} || 'Bullwinkle', + }; + return bless $self, $class; +} + +sub name { + my ($self, $new_name) = @_; + if ( defined $new_name ) { + $self->{name} = $new_name; + } + return $self->{name}; +} +1; +%%%% +<!-- +any questions? +--> + +---- +Moose: +%%%%PRE: +package Animal::Moose; +use Moose; + +has name => ( + is => 'rw', + isa => 'Str', + default => 'Bullwinkle', +); +1; +%%%% +<!-- +see no constructor, no strict, no warnings +if you want show the test +--> + +---- +what is +this 'has'? +<!-- +ok So there you have it... Moose in the... err... code. +So, what is this 'has' thing? Moose runs with the +theory that an object is a collection of attributes. +A moose has a name, thus name is an attribute. +--> + +---- +all about +attributes + +---- +standard format: +%%%%PRE: +has "attribute name" => ( + #attribute definition +); +%%%% +<!-- +an attribute has a name, and it has to define something in some manner. +Here are the definitions that I use the most: +I think that these first three are required. +--> + +---- +access level +%%%%PRE: +is => 'rw', +is => 'ro', +%%%% +<!-- +if you need something to be updated, then it's 'rw'. +If it will never changed once set, it's 'ro'. +really this just specifies what accessors are built for you. +--> + +---- +specify type +%%%%PRE: +isa => 'Str', +isa => 'Int', +isa => 'ArrayRef', +isa => 'HashRef', +isa => 'CGI::Simple', +%%%% +<!-- +let's moose know what type of thing to expect to be here +we'll get in to types a bit more later +--> + +---- +need a default? +%%%%PRE: +default => 'string', +default => 12, +default => sub{ [] }, +default => sub{ {} }, +%%%% +<!-- +scalars can just be specified any thing else needs to be wrapped in a sub {} +--> + +---- +required attribute +%%%%PRE: +required => 1, +%%%% +<!-- +If this attribute is not specified on construction then die +--> + +---- +'optional' attribute +%%%%PRE: +lazy => 1, +%%%% +<!-- +I use this mostly as a timing safety net, IE if one attribute needs another to be built, then make the second one lazy. +Lazy attributes get built right be fore they are used, so this is also a really good way to keep your code 'lite' by +setting things up so that you only use what you really need. +--> + +---- +%%%% there's more | http://search.cpan.org/~stevan/Moose-0.38/lib/Moose.pm %%%% +<!-- + +--> + +---- +why types +are cool? + +---- +built-in +assertions +<!-- +Moose's type structure is basically a built-in assertion for the content of an attribute. +--> +---- +advantage? +they make my code die! +<!-- +This is super handy as Moose is making sure that you know what your dealing with, +you do not have to have everything check to make sure that $input_data is going to be > 0 or what ever. +At first this was really annoying for me. As I was porting my instal run of Search things would always die. +it was another symptom of bad code, Again Moose is forcing me to think about what I really want, and staying on task. +--> + +---- +my options? +%%%%PRE: + Any + Item + Bool + Maybe[`a] + Undef + Defined + Value + Num + Int + Str + ClassName + Ref + ScalarRef + ArrayRef[`a] + HashRef[`a] + CodeRef + RegexpRef + GlobRef + FileHandle + Object + Role +%%%% +%%%% more info on types | http://search.cpan.org/~stevan/Moose-0.38/lib/Moose/Util/TypeConstraints.pm %%%% +<!-- +There are many types that Moose provides by default, mostly there an extension of the existing perl data objects. +--> + +---- +... they're missing one ... +<!-- +but theres more... You can write your own. +--> + +---- +... so make your own ... +<!-- +Here are some examples from work, ignore the role bit for now. +--> + +---- +%%%%PRE: +package PowellsData::Types::Web; +use Moose::Role; +use Moose::Util::TypeConstraints; + +type 'WebObject' + => where { + ref($_) =~ + m/^(Apache2::Request|CGI::Simple)$/ + } + => message { + sprintf( + '(%s) needs to be an Apache2::Request + object or a CGI::Simple object and + it is a %s', + $_, + ref($_) + ) } + ; +%%%% +<!-- +OK so this is from the Search code... There are a many ways to access this code... many are web based, let's specify that the object that holds our CGI session is of the right type and not just some weird chunk of data. +So as you can see, it's very much an assertion... is this thing the right type. ( I forget why I'm using ref vs isa there might be a reason, there might not be). +A type has a {where} block that returns 0|1, if one were good, if 0 bail, +you can also specify a {message} if you would like to gussy up your error log with more helpful errors. +--> +---- +... you can also +extend types +via subtypes. + +---- +%%%%PRE: +package PowellsData::Types::SQL; +use Moose::Role; +use Moose::Util::TypeConstraints; + +subtype 'SQL_Select' + => as 'Str' + => where { + $_ =~ m/\bSELECT\b.+\bFROM\b/i + }; + +subtype 'SQL_Insert' + => as 'Str' + => where { + $_ =~ + m/\bINSERT\b.+(?:\bINTO\b)?.+\b(?:VALUES|SET|SELECT)\b/i + }; + +subtype 'SQL_Update' + => as 'Str' + => where { + $_ =~ m/\bUPDATE\b.+\bSET\b/i + }; + +subtype 'SQL_Delete' + => as 'Str' + => where { + $_ =~ m/\bDELETE\b.+\bFROM\b/i }; + +subtype 'SQL' + => as q{SQL_Select|SQL_Insert|SQL_Update|SQL_Delete} ; +%%%% +<!-- +In this example, I just built out some regexes that sit on top of the string type. +So if you were to pass in an arrayref for example, these would die long before the regex were to be checked. +Things to note here: +- subtypes just extend an existing type (as) +- where is the same, something that returns (0|1) +- you can extend any other defined type/subtype and even group them (SQL) +--> + +---- +so roles? + +---- +how to eat a moose + +---- +... small pieces + +---- +roles ~ includes +<!-- +Roles are another thing that blew my mind. At it's most basic you can think of a role as +a include in to the current file. +--> + +---- +usage (theory): +1) abstract the common +<!-- +Before we really jump to some example, theres basically two +ways that I find my self using roles. The first is as +an abstarction layer to something very common. +--> + +---- +example: +%%%%PRE: +package PowellsData::Setup::Database; +use Moose::Role; +use DBHost; + +sub d; +has d => ( is => 'rw', + isa => 'DBI::db', + required => 1, + default => sub{ my $d = _dbiconnect('current'); + $d->{mysql_auto_reconnect} = 1; + $d->do("SET NAMES utf8"); + return $d; + } + ); + + + +1; +%%%% +<!-- +So this basically sets up a database handle for us. It's an abstraction of +DBHost, a Powells rapper around DBI that manages what server to use and +what user:password to use. This layer does some minor set up on top of that. +We check the type, we are saying that this is required and default will build +one for us if there was not passed in at construction. +Things to note: +- use Moose::Role is the only thing that has changed from a 'Moose' Object. +- this sub hack... +--> + +---- +now in our code just say: +%%%%PRE: +package My::Bad::DB::Example; +use Moose; + +with q{PowellsData::Setup::Database}; + +sub run_query { + my ($self, $query) = @_; + return $self->d->do($query); +} +%%%% +<!-- +this one line now gives me an attribute 'd' that hast to be a 'DBI::db', +everything gets set up for us, it's all in the role. So now I never have to +remember specifics, I just get a DB handle. +it's like I had written all of that code in-line. +--> + +---- +usage (theory): +2) big idea as small chunks +<!-- +the other way that I often find my self using roles is to really +lean on on that 'include' nature. Because the code ends up as though +its one big file, then I take large files and 'break-them-up'. +It's got it's pros and cons, First why I like this: +--> + +---- +%%%%EM:pro:%%%% +write only +what you need +<!-- +In that set up my DB example, we only had to write only the part +about setting up the DB handle. +--> + +---- +%%%%PRE: +package PowellsData::Setup::Database; +use Moose::Role; +use DBHost; + +sub d; +has d => ( is => 'rw', + isa => 'DBI::db', + required => 1, + default => sub{ my $d = _dbiconnect('current'); + $d->{mysql_auto_reconnect} = 1; + $d->do("SET NAMES utf8"); + return $d; + } + ); + + + +1; +%%%% +<!-- +Search is web based, but in this code we don't care, we can focus just on one +simple part of a very complex problem. +--> + +---- +%%%%EM:con:%%%% +lost context +<!-- +with roles you just get stuff for 'free', it's almost like magic. Santa just showed up and you +got a DB handle. ~Woo~. +--> + +---- +%%%%PRE: +with q{PowellsData::Setup::Database}; +%%%% +vs. +%%%%PRE: +use Some::Other::Magic::DB::Manager q{d}; +%%%% +<!-- +when you set up a role next to the use qw{import} way of things, you can maintain context +you are stating the origin of things. Theres so many times that ack has saved me time because +I have completely lost track where method or attribute is. +--> + +---- +%%%%EM:pro:%%%% +group logical actions +<!-- +If I take advantage of the Roles as includes then I can take that section of code +that does that one thing and pull it off to it's own file, even if it's only used +once. +--> + +---- +%%%%PRE: +package Search::Runtime::FPSearch::Section; +use Moose; +use Carp::Assert::More; + +with qw{ + Search::Runtime::Common + PowellsData::Setup::Database + PowellsData::Tools::String +}; + + +sub find { + my ( $self, $needle) = @_; + if ( $self->_has_valid_value($needle) ) { + my $needles = $self->array_of_words( lc( $needle ) ); + my $query = _query($needles); + my $r = $self->d->selectall_arrayref($query, { Slice => {} }, @$needles, @$need +les); + my $score_limit = scalar( @$needles); + + if ( scalar( @$r ) > 0 ) { + #we have resutls + my $out = []; + foreach my $s ( @$r ) { + if ( $s->{score} >= $score_limit ) { + push @$out, {$s->{name} => $s->{link}}; + } + } + return $out; + } + } + return undef; +} +sub _query { + my ($needles) = @_; + assert_listref($needles); + return sprintf( q{ + ( + SELECT DISTINCT X.MAJORSec as name, + CONCAT( 'psection/',X.HTML ) AS link, + X.score, + X.type + FROM ( + SELECT C.MAJORSec, + C.MINORSec, + count(SWC.word_id) AS score, + SWC.type, + C.HTML, + C.sectionkey + FROM Sections.section_word_category SWC + JOIN Sections.category C + ON (SWC.category_id = C.id) + JOIN Sections.section_words SW + ON (SWC.word_id = SW.id) + WHERE SW.word IN (%s) + AND C.MAJORSec NOT LIKE '%%Reader eBook%%' + AND C.MAJORSec NOT LIKE '%%sale%%' + AND C.MAJORSec != '$7 or Less' + AND C.MAJORSec != 'At the Movies' + AND C.MAJORSec != 'New Arrivals' + AND C.MAJORSec != 'Coming Soon!' + AND SWC.type = 'major' + GROUP BY C.id + ORDER BY score DESC + ) AS X + ) + UNION + ( + SELECT CONCAT( Y.MAJORSec, ' - ', Y.MINORSec ) as name, + CONCAT( 'subsecti on/', Y.sectionkey, '.html' ) AS link, + Y.score, + Y.type + FROM ( + SELECT C.MAJORSec, + C.MINORSec, + count(SWC.word_id) AS score, + SWC.type, + C.HTML, + C.sectionkey + FROM Sections.section_word_category SWC + JOIN Sections.category C + ON (SWC.category_id = C.id) + JOIN Sections.section_words SW + ON (SWC.word_id = SW.id) + WHERE SW.word IN (%s) + AND C.MAJORSec NOT LIKE '%%Reader eBook%%' + AND C.MAJORSec NOT LIKE '%%sale%%' + AND C.MAJORSec != '$7 or Less' + AND C.MAJORSec != 'At the Movies' + AND C.MAJORSec != 'New Arrivals' + AND C.MAJORSec != 'Coming Soon!' + AND SWC.type = 'minor' + GROUP BY C.id + ORDER BY score DESC + ) AS Y + + ) + ORDER BY type = 'major' DESC , score DESC + }, + _soq(@$needles), + _soq(@$needles), + ); +} + + +1; +%%%% +<!-- +I don't know if this is readable but what is going on here is a section search. I take in +a $needle and then build up a query based on that $needle and try and find it in the DB. +This code only does one specific thing, So I pulled it out. It could have become it's own object +but it really doesn't need to hold on to any thing, it just needs a DB handle and a needle, this +a quick handy way to keep things grouped by logical tasks. +--> + +---- +%%%%EM:con:%%%% +things get +messy fast +<!-- +As cool as this is, you really need to be careful, things can get really messy really fast. +Here let's just take a quick gander at the dir for Search: +--> + +---- +%%%%PRE: +benh@noodleboy:~/svn/lib_common/dev/Search$ tree . +. +|-- CompleteResults.pm +|-- CompleteResults_distance.pm +|-- Core +| |-- Actions +| | |-- Pages.pm +| | `-- Results.pm +| |-- Actions.pm +| |-- CompleteResults +| | |-- Common.pm +| | |-- LimitedQuery.pm +| | |-- OLDQuery.pm +| | |-- OrderBy.pm +| | |-- Query.pm +| | `-- Restrictions.pm +| |-- CompleteResults.pm +| `-- Shortcut.pm +|-- Core.pm +|-- DB +| |-- Current +| | |-- NoStem.pm +| | |-- PublisherKw.pm +| | |-- PublisherKwOld.pm +| | |-- Search.pm +| | |-- SearchCacheClasses.pm +| | |-- SearchCacheCounter.pm +| | |-- SearchCacheMeta.pm +| | |-- SearchCacheParams.pm +| | |-- SearchCacheResults.pm +| | |-- SearchCacheSections.pm +| | |-- SearchKw.pm +| | |-- SearchKwOld.pm +| | |-- SearchOld.pm +| | |-- SearchTitle.pm +| | |-- SearchTitleOld.pm +| | |-- SectionsKw.pm +| | |-- SectionsKwOld.pm +| | |-- Stock.pm +| | |-- StockOld.pm +| | |-- ZqDb.pm +| | |-- ZqKw.pm +| | `-- ZqTitle.pm +| |-- Current.pm +| `-- Profiler.pm +|-- DB.pm +|-- Debug +| `-- Stopwatch.pm +|-- Debug.pm +|-- Runtime +| |-- Attr.pm +| |-- Common.pm +| |-- Cookies.pm +| |-- Defaults.pm +| |-- FPSearch +| | |-- Author.pm +| | |-- Help.pm +| | `-- Section.pm +| |-- FPSearch.pm +| |-- Internal.pm +| |-- Lookup.pm +| |-- Promote.pm +| |-- Spelling.pm +| |-- Tracking.pm +| |-- Translate.pm +| |-- Values +| | |-- Clean.pm +| | `-- Organize.pm +| |-- Values.pm +| `-- Websearch.pm +|-- Runtime.pm +|-- Test +| |-- pound.pl +| `-- runsearch_lite.pl +|-- Test.pm +`-- playground.pl +%%%%} +<!-- +Lets see what is really an object in all of this... +- Runtime +- Runtime::Default +- Core + +Runtime is called from Search Core, it extends Default, but everything else is a role, it is just included. +I've tried to keep things organized, but roles are like kudzu. So just like most things, with great power comes great responsibly. +This is one of the biggest reasons I've been in some level of constant refactoring of this code base. +--> + +---- +%%%%EM:pro:%%%% +delegate code +<!-- +Because there actions in separate files it's really handy to be able to hand out parts of the puzzle +to other people and then just come back with a big working object. It's a dream that I have at work, +so far not much has come of it. +--> + +---- +%%%%EM:con:%%%% +moose roles +are moose only +<!-- +Moose roles are only use-able via moose. You can write mini-object thats collect your roles, +It's not ~hard~ to get around, just need to mention it though. Also to note, Moose is not the only +way to implement 'roles', check cpan for 'traits' or 'mix-ins'. There all kinda the same thing +--> + +---- +there's a lot more to roles +%%%% CookBook Example | http://search.cpan.org/~stevan/Moose-0.38/lib/Moose/Cookbook/Recipe6.pod %%%% + +---- +<!-- +how we doing on time? +--> + +---- +kinda-FAQ +<!-- +** possible filler if needed ** +--> + +---- +how to extend a Moose? +<!-- +let's see how am I doing on time... cause I can just skip this if I'm over +--> + +---- +It's easy: +%%%%PRE: +extends q{object}; +%%%% +vs +%%%%PRE: +use base q{object}; +%%%%% +<!-- +Basically does the same thing but makes sure that all the Moose stuff stays in the right place +in the @ISA stack. Also I have not played with it, but extends will take an array of parents +and should handle any weird multiple inheritance juju for you. +--> + +---- +with out new, +how can I +have something +run on creation? +<!-- +I still have not completely wrapped my head around what bits of Moose are compile time +and what happens at run time. Theres so many layers to things. +There are often times that you will find your self missing that constructor. +just need something to be run at creation time? +--> + +---- +%%%%PRE: +sub BUILD { + #... code to be run on create +}; +%%%% + +---- +wow free lunch? +cost? +<!-- +sadly no, this is not a free lunch. There is a hit on performance, I have not done any +testing, no hard number. Though I have not really noticed any significant hit. Though +this is mostly sidelined as Search runs in mod_perl so things only get built once. +There are all sorts of warnings all over the place about not using Moose for a +simple CGI.pm application. +--> + + +---- +<!-- +step #{number} +Things that I'm still learning +- meta, it all just perl +- coerce best uses. +- triggers, almost a method modifier +- method modification events + - before + - around + - after +- unimport ( 'no moose', when to use? ) + - mostly just a way to clean up things + - %%%% namespace::clean | http://search.cpan.org/~phaylon/namespace-clean-0.08/lib/namespace/clean.pm %%%% + - insure that there are no funky issues down stream +- super? +- override, makes sense just have not run in to a need to use +- inner +- augment +- Moose specific testing + - mostly how to test roles by them self? + - %%%% Test::Moose | http://search.cpan.org/~stevan/Moose-0.38/lib/Test/Moose.pm %%%% + - %%%% Test::Moose::MockObjectCompile | http://search.cpan.org/~zaphar/Test-Moose-MockObjectCompile-0.2.1/lib/Test/Moose/MockObjectCompile.pm %%%% +--> + + +<!-- + * a perl object system + * meta syntax for object/class declaration + * simple example + * not *that* weird +* Ride the Moose (code in "the real world") + * Constructors for free + * BUILD + * under the hood - the meta() method + * getters and setters + * example + * possible name space collisions + * 'rw' vs 'ro' + * timing issues ( lazy => 1 ) + * strict types + * things die if they are wrong, just like they should (assertion) + * roles + * less code to test +* Love the Moose (techniques and practices) + * composition / modularization / encapsulation + * layout of logical file structure with roles + * easier team workflow / merging + * QA notes +--> + +---- +thanks to Stevan Little +and the whole moose crew #moose +<!-- +including eric +--> + +---- +Thanks for putting up with my yammering + +---- +More info: +- %%%% CPAN | http://search.cpan.org/~stevan/Moose-0.38/ %%%% +- %%%% Cookbook | http://search.cpan.org/~stevan/Moose-0.38/lib/Moose/Cookbook.pod %%%% +- %%%% Moose Site | http://www.iinteractive.com/moose/ %%%% +- IRC: irc.perl.org #moose + +---- +-end- + + +</html:textarea> + +<!-- Built-in Style --> +<html:style id="builtinStyle" type="text/css" style="visibility: collapse"> +<![CDATA[ +@namespace url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul); +@namespace html url(http:/www.w3.org/1999/xhtml); + +#canvas { + background: white !important; + color: black !important; + font-family: + "Florencesans Black" + "futura" + "ã´ã·ãã¯MB101U" + "ãã¥ã¼ã»ã¶ã³ã-EB" + "ã»ã¶ã³ã-EB" + "DHP極太ã´ã·ãã¯ä½" + "DFP極太ã´ã·ãã¯ä½" + "DHPGothic UB" + "DFPGothic UB" + "DHPç¹å¤ªã´ã·ãã¯ä½" + "DFPç¹å¤ªã´ã·ãã¯ä½" + "DHPGothic EB" + "DFPGothic EB" + "ã»ã¤ãã¤ãµã©ã´UB-P" + "AR Pã´ã·ãã¯ä½ S" + "Arphic PGothic SuperBold JIS" +/* "Arial Black"*/ + "DFç¹å¤ªã´ã·ãã¯ä½" + "DFGothic EB" + "ã»ã¤ãã¤ãµã©ã´UB" + "AR ã´ã·ãã¯ä½ S" + "Arphic Gothic SuperBold JIS" + "HGPåµè±è§ï½ºï¾ï½¼ï½¯ï½¸UB" + "HGPSoeiKakugothicUB" + "HGSåµè±è§ï½ºï¾ï½¼ï½¯ï½¸UB" + "HGåµè±è§ï½ºï¾ï½¼ï½¯ï½¸UB" + "HGSoeiKakugothicUB" + "å°å¡ã´ã·ã㯠Std H" + "ã¢ãã¤ã´ã·ã㯠6" + "ãã©ã®ãè§ã´ Std W8" + sans-serif !important; +} + +.em-text { + color: red !important; + font-size: 120%; +} + +.link-text { + color: blue !important; + text-decoration: underline !important; +} +.link-text:hover { + color: #3366FF !important; +} +.link-text:active { + color: red !important; +} + +.preformatted-text.block { + border: 1px dashed gray; + padding: 0.3em; + margin: 0.3em; + font-size: 80%; +} + +.monta-label { + background-color: white; + background-repeat: no-repeat; +/* background-image: url("./monta-label.png");*/ +} + + + +#canvas column, +#canvas row { + border: 1px solid gray; +} + +#canvas grid .special { + background: #CFCFCF; +} + + + + + +#header, +#footer { + color: #666; +} + + +#indicatorBar { + color: #BFBFBF; + background: black; +} + +progressmeter { + margin: 0; + padding: 0; +} +progressmeter, +progressmeter .progress-bar, +progressmeter .progress-remainder { + -moz-appearance: none; + background: transparent; + border: none; + outline: none; + min-height: 0; +} +#remainingTimeIndicator .progress-bar { + background: #333333; +} +#remainingPageIndicator .progress-bar { + background: #444444; +} + + +#plainTextBox { + background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wYGCSMfVbRtUAAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJTVDvZCVuAAAAGElEQVR42mNkYGCoZyACMDEQCUYVUkchANsIAJN3G7QXAAAAAElFTkSuQmCC'); +} + +#plainTextField { + font-family: monospace; + font-size: medium; + color: black; + background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wYGCTURrpT1gAAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJTVDvZCVuAAAAGUlEQVR42mP8////fgYiABMDkWBUIXUUAgAEGgPQ5w4kBAAAAABJRU5ErkJggg=='); + border: 2px solid gray; + border-color: black white white black; + -moz-appearance: none; +} + + +/* Eva Mode */ + +#canvas[eva="true"] { + background: black !important; + color: white !important; + font-family: + "ãªã¥ã¦ãã³U-KL" + "ãªã¥ã¦ãã³H-KL" + "ããã£ã¹-EB" + "RFãã¡ã¤ã³-ME" + "DHP極太ææä½" + "DFP極太ææä½" + "DHPMincho UB" + "DFPMincho UB" + "AR Pææä½U" + "Arphic PMincho Ultra JIS" + "ARææä½U" + "Arphic Mincho Ultra JIS" + "HGPå¹³æææä½W9" + "HGPHeiseiMinchotaiW9" + "HGSå¹³æææä½W9" + "HGSHeiseiMinchotaiW9" + "HGå¹³æææä½W9" + "HGHeiseiMinchotaiW9" + "ãã©ã®ãææ Pro W6" + serif !important; +} +#canvas[eva="true"] .em-text { + color: red !important; +/* color: green !important;*/ +} +#canvas[eva="true"] .link-text { + color: red !important; + text-decoration: none !important; +} +#canvas[eva="true"] .link-text:hover { + color: pink !important; +} +#canvas[eva="true"] .link-text:active { + color: orange !important; +} + +#canvas[eva="true"] #header, +#canvas[eva="true"] #footer { + color: #AAA; +} + + +#canvas[eva="true"] .monta-label { + background-color: black; +} + + + + + +.stroke-dot { + background: red; + width: 3px; + height: 3px; +} + + + + + + + + +/* System:: DO NOT CHANGE FOLLOWING LINES!! */ + + +#canvas * { + cursor: pointer !important; +} + +#canvas image { + width: auto; + height: auto; +} +#canvas[rendering="true"] image { + display: none; +} + +#canvas[rendering="true"] *, +#canvas[rendering="true"] .text-link { + color: inherit !important; +} + +#canvas[rendering="true"] #contentBox { + visibility: hidden; +} + + + + + + +.preformatted-text { + font-family: -moz-fixed !important; + white-space: pre !important; +} + + + +.raw { + font-family: sans-serif !important; + font-size: medium !important; +} +#canvas .raw * { + cursor: default !important; +} + + + + + +tabbox, tabpanels, tabpanel { + margin: 0; + padding: 0; +} + + +.dropmarker-button > image { + display: none !important; +} +.dropmarker-button > label { + width: 0 !important; + overflow: hidden !important; +} + +#pages-list-button { + min-width: 0; +} +#pages-list-button > label { + display: none; +} +#pages-list-button menupopup { + max-width: 20em; +} +#pages-list-button menuitem image { + max-width: 32px; + max-height: 32px; +} + + + + +#headerBox, +#footerBox { + margin: 1em; +} + + +#indicatorBar, +#indicatorBar hbox, +#nextPage { + -moz-box-align: center; + -moz-box-pack: center; +} + + + +.monta-label { + padding: 0.05em; + margin: -0.05em; +} +.monta-label[monta-hidden="true"], +.monta-label[monta-hidden="progress"] { + background-position: -100px 0; +} +.monta-label[monta-hidden="progress"] { + background-color: transparent; +} +.monta-label[monta-hidden="false"] { + background: transparent !important; +} + + + +#canvas row description { + border: 1px solid transparent; + white-space: pre; +} + + + +#canvasToolbar { + position: relative; + z-index: 1000; +} + +#sourceEditField, +#pageEditFields textbox { + font-family: -moz-fixed !important; + font-size: medium; +} + +#pageEditFields { + overflow: auto; +} +#pageEditFields textbox { + height: 6em; +} + + + + +#stroke-canvas-box { + position: relative; + display: block; +} +#stroke-canvas-box, +#stroke-canvas-box *|canvas { + line-height: 1; +} + +.stroke-dot { + position: absolute; + display: block; + z-index: 100; +} + + + +.monta-label { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABQAAAAUACAYAAAAY5P/3AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1QUfBjYDWiVT+AAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJTVDvZCVuAAAgAElEQVR42uzdeZSlaV3Y8d/73q2Wrl6nl+nu6W56FgZmAWZGmAEHRzAwgiCoyQnGLEY9UQIxMdEsmggy6FGDRo2gh+ACoiEuIYqjRE9OohEhCAYM6rAIOMywDExv1VV1t/fJH7eqq25XVXd1d1V13Wc+n3PmVPWtXs787v3re57n/RXBVfXTr3/1zs898qmfevSRh7/pge98yScObK+uNxUAAAAA1kvdCK6O33jz92/7zMOf/N6H/uy93/Ppz54qX3bfk0P8AwAAAGC9CYBXwc/+0KvveO8f/9FPf+rhR+7udKs4uHcqXvHCWwwGAAAAgHUnAG6i3/yFB1qf+sRDP/zhP/3jV3/h8bNlv0pRFBFf/7ybo9WsGRAAAAAA604A3CT/5Y3/8rkf+D//+8c++elH7pzr9CKliJRSHD+0M57/zGMGBAAAAMCGEAA3wRt/4Fv+5R/94f/6/i+enB7v96tz8a8oinj5V95sQAAAAABsGAFwA/3Wz7/m+J9/+P3v+uAHP/CUwam/FCliEAAj4ti1O+LZtx82KAAAAAA2jAC4Ad711tcX0ycfe9V7/uD3/v3nvjTdXDj1V1VpEAFTiqpKccv1e6MozAsAAACAjSMArrN3/txrd3/yY3/+E3/50EPfNDvXnY9+sez0X7NRxsvuu8nAAAAAANhQAuA6+qWf+O5nPPTh9/zOX/31Y/t7/Wo++KVIsSQCzn89vG9H7N4+bmgAAAAAbKjSCNbHW//9K1/zFx96zwc++fBj+6uUImJp8Bt8v/S1pzzpGkMDAAAAYMM5AXiF3v3LP1x/+K8+8o4Pf+iDX3d2trvkpN98/Iu07Ppvo17G136F678AAAAAbDwB8Ao8+LYH9n/8I+9/8OOffPiOTq8/fN03lp8AXPh6cO/22LtrwgABAAAA2HAC4GV68Bdf++y/+L/v+fWHP/vFA/1+WnLFd/gE4OC14WcAHj+00wABAAAA2BQC4GV411v+zT/40/f9z5/54smZ1mDL73kn/SJWvf6bUoo7bj5giAAAAABsCgHwEvz3X/mR2pc+//Br/897//B7p2c65677VvMn/qolJ/0GYTBiMRAOXms1a/Gcp11nmAAAAABsCgFwjd799h/a8cgn/+I/fezjH/2GTre/wrP9Lr78I6UUu6bGoyjMEwAAAIDNIQCuwYNvfd0Nn/7oB3/jUw8/eluvVy1Z9jEIfBGxbPlHxPLlHxERO6daBgoAAADAphEAL+K/veX7nvOJj7z3tz772Mld/X61GPpWOvWX0qqbfxdeK0vH/wAAAADYPKURrO7X3/Td3/yJj7zvf37usZO7hsPeKrEvLrz8I0WKwv1fAAAAADaRE4Cr+NWfevWPf+zPP/CdZ2c7RcT5YW/+im/EkuvAgz93fhQ8/zUAAAAA2EwC4Ar+y3/4R//1Y3/5/17W7vaGT/ANnQC8wAKQZd8vxkMAAAAA2EwC4BLv/uUfbj7+yJ//0cc++tBd3V61esy74LbfpctAlsdDF4ABAAAA2EwC4LzfffsP7XnsU3/6J5/+zOeO9avBtd6qGoS9qlq85lulpV/nv68G3w++xpLvz3stJUtAAAAAANhUAmBE/O4vPXD883/1J+975HOPX7M07EUsv/q7/LWF5/wNnwaMWPkZgVXlGjAAAAAAm+cJHwAffOtr73z0Y+//X194/Mzkqs/0W7L8Y/G6bzrvum9a4dmAy/++mbmeTx0AAAAAm6Z8Iv/P//Yv/LsXPPLR97/nsRPz8W/+9fPDXsSVL/9YeCbgbLvrUwcAAADApnnCBsB3v+21L3r04x948OSZ2ebFY97yn0fEsuUfEcuXf0QM/9kzMx2fOgAAAAA2zRMyAP7e23/g/oc/+v53nj7brq0c+87f6rvCdd9YLRSmVV4bfD8tAAIAAACwiZ5wAfB//Ocf/PKHH3r/b54+O9dYfnJveGHHJS0AGXpmYKxw/Xfwd0/PdqLT7fvkAQAAALApak+k/9nf++XXP+MzD733faem52pVGmzkTee+pqiqpd/P/yylWNgMXKUlr1WDsDf4Ov9nl/x88PuX/939foprdk3Ezcf2+PQBAAAAsOGeMCcAf+etr7vlsx9/35+cmm4vnuA7b0HH6td81/KMwFU2/8byZwS+988e8ckDAAAAYFM8IQLgg2/9gad+6dMf+L+nptvlYthLcTnLP1Z/RmCs+RmBn3r0pE8eAAAAAJsi+wD4u2973dNOPPyhPzk1PVe/pGf6LVn+EbGWZwSmC/99S0Lg46fnfPIAAAAA2BRZB8B3v/31N5/4zIf/4NSZs+OLCzrSqgs6hk7wDZ0AjDWeGExrulo8PdOJ9/0/14ABAAAA2HjZBsB3v/31R088/OE/PHVmevvysJfWGPbO3+57obC3UjxcORRWKcWbfu2DPn0AAAAAbLh6jv9Tv/O2H9x18jMf+uDpM2d2nx/fIpbHucFrKy3sGD65d8E/u+Jrq10tDs8BBAAAAGBTZBcA3/XW10+cefRPHz59ZmaySosn9qpqcM134evCSbyU0vzXQairqvmfVbHCa8On+Ib+7LJ/I4aeIdhs1GK81Yjbb9wXTz66Jw7tm/LpAwAAAGDDZRUA3/WLD+ye+/yH/vr09Mzk6td8L3L1d8nyj7U9I3D4ynBERL1Wxo5trdizczy+8q6jsW28Gc9+2uEYa9Z94gAAAADYVNkUqXf94gO7Ol/6yz87Mz07uXrYW//lHxERZRlxaN+OmJpoxlfedTR2bGvFnU+51qcLAAAAgKsuiwD4m7/wQLNz4q/+x+nTpw5W6ULP71vluXyX+IzAiIhaWcaxg9vj6IEd8axbD8ZtN+yLsix8ogAAAADYUrIIgL3Tf/3u6dNffPqFNu+ufIovVtjqu8KpwPlfl0URRw5ujxuv2x1fdsvBOHbtjmg2aj5FAAAAAGxZIx8A3/kfv+O3p088et/SBR0rh71YNexdKBQWRRF7to/Fk4/uiec/81js2TER4y3P8gMAAABgNIx0yXrnm77zjTOPf/pFi9d+h8NexMpLOi58FXjwtVYr444b98W9zzgSB/ZMxraJpk8LAAAAACNnZAPgb7zpu//x3ImPf8fg5N/FFnZcaNvv8CnBWq2I++46Fs99xpHYPtnyXD8AAAAARtpIBsDf+Nl/fX//5EP/sV+lqOajXrUk7FXVIOwNvg7/vFoSARevDaeYHBts8H3O06+LmugHAAAAQCZGLgD+2s9+3/Xp1F882Ouni2zyHT79t/y1wYuT44Pw98xbDka9VvpEAAAAAJCVkQqA73jT915bnP7on3V7VbH8uu9q13zPv+47OBVYlkXceGR3vOg5N8SeHeM+CQAAAABkaWQC4Dt+5t82GrOf/sN+1Rsffm5fWr7VN5Yv/1h66u/wvu3xvC87FscP7fQJAAAAACBrIxMA63Of/f2qe/b6qhr8+sKbfJdeBV58rVGvxXOedjiedeuhaNRd9wUAAAAgfyMRAH/tJ1/5y0X7C89dXOCRVtn0u3yr7+CViFtv2Bv3Pv1I7No+5l0HAAAA4AljywfAd/zkP/1X9e4jr+ilpdd7Y/l131gpCg7i3313Ho1n3XooCst9AQAAAHiC2dIB8O0/8c9fMtb76x/sV2vd9rv090XUa2V84/23xL7dk95pAAAAAJ6QtuyZuLf/1L86sK37iUerKhVVlaJfpVj42q+qGH6tin4/RZVS9PtVVCnF/t3b4hvvv8U7DAAAAMAT2pY8AfgLP/4vpsbbn/xYlFEMX/tdfuLv/OcBRkRcf3hXvPS5N3l3AQAAAHjC25IBcFtx4t2NWtrWr5ZGvrUt/7j52DXxwnuOe2cBAAAAILZgAPzPP/4dbx6Lx++pzn+mX8TQVt+Vln/cfuO+uO/Oo95VAAAAAJi3pQLgL/2Hf/Y3p4pHv7Wq0nlbflc59Tf/fZVS3PWUg3HP7Ye8owAAAACwxJZZAvJzb/jn+/eWn3mkLKN2/kKPfn944cfSZSC9XhX33H447rj5gHcTAAAAAM6zZU4A7kiPfqReK2r9auHabxpa/hER550KHATB++46Grcc3+udBAAAAIAVbIkA+Ctv+NZ3TTbP7ulXg2u+1ZJlH9XCa9X5r0V81TOfFDce2e1dBAAAAIBVXPUA+LYf+yfftrv52IsXA995z/uLxeUfi6cCU7zg7uNx7OAO7yAAAAAAXEDtav7jP/+G77rhmvpn/3tZFkWVIhaWf1TVIPxVVcyfBkxRzcfBbq+K+599fRy9VvwDAAAAgIspr9Y//JY3/ItyV/n59zbqtWLh1F/E+ScAh1/r9vrx/GceiyMHtnvnAAAAAGANrloA3FacfHBbK/YMXfdNy5d/LFz/7VcpnnXrobj+8C7vGgAAAACs0VUJgD//o6/6e3vGZl+Y5vf7LjzXb2HLb8TwScB+P8XNx/bE7Tfu844BAAAAwCW4KgFwZ/GFNxdFnLf0Y/n135QGzwA8fmhnPPv2w94tAAAAALhEmx4A3/Kjr75/+2SjWZ0X+gbLP9K55R8LpwLHmvV47h1HvFMAAAAAcBk2PQBurz77zojF03/V0DMA09B/vX4Vf/OrnuJdAgAAAIDLtKkB8M0/8p3Hd29vtRaf8zd89Xfw2uD0X7vTj1e88BbvEAAAAABcgU0NgM3O536/KIr5ZR9p2fKPha2/c+1evODuJ0WzUfMOAQAAAMAV2NQAuGsiHVu+8GN4+Ue314+7bzsUB/dOeXcAAAAA4AptWgD8mR985b2T441i+Fl/g58tnAbs91Nct3973Hxsj3cGAAAAANbBpgXAsd4X3rF4/TeWX/9NKc7MdGz8BQAAAIB1tGkBcPe28trl234Xr//Otfvxjfdb+gEAAAAA62lTAuAbH/j2F0+ON6JKi8s/qmpw+q+qUlQpxeH9UzEx1vCOAAAAAMA62pQAONb93NsjYujE3+KvU0zPdOO+O496NwAAAABgnW1KALxmR3PHald/u70qvubeG7wTAAAAALABNjwAvvF13/atk+ONVZd/nJyei2t2TngnAAAAAGADbHgAHO8/9mMRgxN/g6+LJwCrlOKe2w57FwAAAABgg2x4ANw11Zhadv03Bt+fOD0Xt9+4z7sAAAAAABtkQwPgTz/wyqeseP13/gTg/t2T3gEAAAAA2EAbewJw9vO/WhZFLF8AkuLMTCe+5t4bvQMAAAAAsIE2NABua3ZvrhbCX0RU1eLyj+mZThSFNwAAAAAANtKGBsAd21q1heu+5y//eMHdx00fAAAAADbYhgXAn3jNt71ocryx4vKPU9PtuOG6XaYPAAAAABtswwJgrf2FN0bE0PKPhV+fne2YPAAAAABsgg0LgBON/uHlyz8G13/vu/OoyQMAAADAJtiwADg12awtPfW39PrvbTfsM3kAAAAA2AQbEgB/8nWvak2ON4eu/y6cADw93TZ1AAAAANgkGxIAezOPvaVWFpFSiqpK57YAVynFvc+4ztQBAAAAYJNsSACs90+/ZOj0Xwwi4Knpdtz5lGtNHQAAAAA2yYYEwG1jtamI4au/g+f/zZk4AAAAAGyiDQmAU5PN4lz8m1/+kSLizpud/gMAAACAzbTuAfBHv/dbbpocby5b/nFquh33PuOIiQMAAADAJlr/E4Dtx99cxGL8i/nvHz81G0Vh4AAAAACwmdY9ADbSzDMHp/+Gr//edsM+0wYAAACATbbuAXBqsjGWUoqqGpwArKoUp6fb8YK7j5s2AAAAAGyydQ2Ab/j+by+2TzaXnf774knXfwEAAADgaljXANjrzL50YqwRaf7hf4MFICkmxuomDQAAAABXwboGwGrmCz8SEec2/6aUot9P8dKvuMmkAQAAAOAqWNcAOFbrHz//+u+JM3Nx3f7tJg0AAAAAV8G6BsCpyUY9pTR0AvDUdNuUAQAAAOAqWdcAuHNq7Fz4WwiBrUbNlAEAAADgKlm37RwPfNff+v5WI6JaOAEYEf0qxTd81c2mDAAAAABXyfqdAGw//qqlV3+rKsXjp2bj8D7P/wMAAACAq2XdAuBEK3YvXf4RMVgAAgAAAABcPesWAHdsGyuXngBMKaJRL00YAAAAAK6idSl0D3zPN+/eua0VEYvxr0opvvKuoyYMAAAAAFfRugTA3uzJ19Tr5bnrvylFTM904q6nHDRhAAAAALiK1iUApu6Zlwxf/01x4vRcFIUBAwAAAMDVtC4BsEy9AwvhL81vADkz0zZdAAAAALjK1iUAjrXKVkpx7vpvioiJsYbpAgAAAMBVti4BcGKsUaSUoqoGpwCrKsUL7j5uugAAAABwla1LAJwcawyd/jt9th133HzAdAEAAADgKrviAPia7/q7O7dNNCPNP/wvpRSPn5o1WQAAAADYAq44APbmTn9frSyWbACOmJ7tmCwAAAAAbAHrEQBfvvT6b0opJsebJgsAAAAAW8AVB8Ba9A4OTv6lcycAX/Sc600WAAAAALaAKw6AzUbRWjz9F3Fyei6efpMFIAAAAACwFVxxAJwYaxQLz/+rqhRfOjkbRWGwAAAAALAVXHEAXNgAPDgFmCwAAQAAAIAt5IoC4L959Sumtk+2zi3/iIjYPtkyVQAAAADYIq4oAPbmznxfrSzOnQCsqhQvfe6NpgoAAAAAW8QVBsDTX7ew/CNFihOn5+JpN+03VQAAAADYIq4oABapeygizp0AfOzkjIkCAAAAwBZyRQGw2SjGzi0ASSnOznZNFAAAAAC2kCsKgBNjjaKqUqQYRMCdUxaAAAAAAMBWckUBcHK8MX/6b3AC8Hl3HTNRAAAAANhCrigAbhtvzp/+S3F2rhvPveOIiQIAAADAFnLZAfB7vv0bbhpvLZ4A/NLJWdMEAAAAgC3msgNgZ+7MqyMWNgCnODk9Z5oAAAAAsMVcdgDsts/elyJFRESKiHanb5oAAAAAsMVcdgCsep3DSxeAbJ9smiYAAAAAbDGXHQDLIk0uXP9NKeI5T7vONAEAAABgi7nsANioF/WUIqqUYrbdja+590bTBAAAAIAt5rIDYKtRKxZO/z12YiaKwjABAAAAYKu57AA43mpEisHz/06eaZskAAAAAGxBlx0At000I6XBFuC5Ts8kAQAAAGALuqwA+N3f8bdaUxPNWNgCPN6qmyQAAAAAbEGXFQDbs9N/t14vBxuAI8VNR3abJAAAAABsQZcXAGdO/+2FBSBVleJl9z3ZJAEAAABgC7qsANjvzj01pYgUKU5Nt+PQvimTBAAAAIAt6LICYNXv7Vo4AXji9JwpAgAAAMAWdVkBsF4vmoMFICnOzHRMEQAAAAC2qMsKgK1GvUwxOAHY6fZNEQAAAAC2qMsKgGOtWiycAKzVClMEAAAAgC3qsgLg5FgzUkqRIuK6/dtNEQAAAAC2qMsKgFOTzXMnAF9w93FTBAAAAIAt6pID4D/55pfePt6qR0opZuZ68WVPPWiKAAAAALBFXXIAnJs59U9TikgRceL0bBQeAQgAAAAAW9YlB8DO3Nl7UkqRUorTZzsmCAAAAABb2CUHwKrfvTZFREoRc52eCQIAAADAFnbJAbCINLlwAhAAAAAA2NouOQA2G7XaYANwxDU7x00QAAAAALawSw6ArUatiIhIkeKe2w6bIAAAAABsYZccACfGGpFSim6vihd/+Q0mCAAAAABb2CUHwMnxRlQpxYnTc9Fs1EwQAAAAALawSwqAr/6HL5+YHG9GShGnptumBwAAAABb3CUFwM7smW+vlUWkFDEz1zU9AAAAANjiLikAtmfPvCxFipRS9KvK9AAAAABgi7u0E4DtuRtTGny/fbJlegAAAACwxV3aEpDU35lSREoRt16/1/QAAAAAYIu7pABYK4vmwvXfr3/ezaYHAAAAAFvcJQXAZqNWphQxPdOJfbsnTQ8AAAAAtrhLCoDjrXqkSHFmpmNyAAAAADACLikATow1YuEEIAAAAACw9V1SAJwcb0RKKeY6PZMDAAAAgBGw5gD4j/7OV9/datYjpYiqSiYHAAAAACNgzQFwbubUqyIiUkox1qqbHAAAAACMgDUHwM7czDNTSpEi4tDeKZMDAAAAgBGw5gDY73UPpDQ4AfisWw+ZHAAAAACMgEtYAlKNpZSi16/i/mdfb3IAAAAAMALWHABrZVlLEXF6uhONemlyAAAAADAC1lzy6rWyTCnF9GzH1AAAAABgRKw9ANbLSClitt01NQAAAAAYEWsOgK1GLVJK0e70TQ0AAAAARsSaA2CzUYvBFmBDAwAAAIBRseYAON6qR4oU4626qQEAAADAiFhTAHzl339pq9WsR0oR1+ycMDUAAAAAGBFrCoCduZmvK4qIlFLcdsNeUwMAAACAEbGmADg3O/3ilCKqKsVXPetJpgYAAAAAI2JtJwDbs7emlGKu04vr9m83NQAAAAAYEWsKgL1e70BKEWdnuyYGAAAAACNkTQGw3+tNRUTMzAmAAAAAADBKyrX9ttRcuAIMAAAAAIyONQXAWq2spYjodCsTAwAAAIARsqYAWK8VRVUl0wIAAACAEbPGAFhGSinqtdLEAAAAAGCErKnoNRu1SCliz45xEwMAAACAEbKmANhq1CNFipuO7jYxAAAAABghawuAzVpERNx351ETAwAAAIARctEA+K2vuH+q1axFt1fF02/ab2IAAAAAMEIuGgA77dlXREScne1GWRYmBgAAAAAj5KIBcHZm+m+kFDEz1zUtAAAAABgxFw2A3U77qSmlmG33TAsAAAAARszFA2C3szeliE63b1oAAAAAMGIuGgCrfjWRUkS/X5kWAAAAAIyYiwbAFKmRIkWjXjMtAAAAABgxFw2ARUQtpYgd21qmBQAAAAAj5uIBsCjKlFIcO7jDtAAAAABgxFw0ANZqRZFSxLNvP2xaAAAAADBiLh4AyzL6VRXPf+aTTAsAAAAARsxFA2CjXsbMXDca9dK0AAAAAGDEXLTq1WuDAAgAAAAAjJ41BcC5dt+kAAAAAGAErekKcLvbMykAAAAAGEEXDIDf8oqvLhv1WlRVMikAAAAAGEEXDICddvvOsiyiLAuTAgAAAIARdJEAOPuilFJsG2+aFAAAAACMoAsGwPbc7DNSijhyYIdJAQAAAMAIuvAJwE77WIoUdz31WpMCAAAAgBF0wQDY7Xb3VlWK+5993KQAAAAAYARdMAD2+/1tc51e7N4+blIAAAAAMIIuGACrqmrNzPVMCQAAAABGVHmRn9fm2gIgAAAAAIyqiwbAdlcABAAAAIBRdcEAWKsV0etVpgQAAAAAI+qCAbAsiqIoClMCAAAAgBFVv9APa7UyarXSlAAAAABgRF04AJZFTI43TAkAAAAARtQFj/c16rXYu2vSlAAAAABgRF0wANZrZTzp4E5TAgAAAIARdZEAWMQznrzflAAAAABgRK0aAP/Oy5+3u1Yr41m3HjIlAAAAABhRqy4BmZud+dqy17cEBAAAAABG2KoBsN2evbfs900IAAAAAEbYqgGw027fWIYACAAAAACjbPUA2OlcWysrEwIAAACAEbZqAOx2ezurmgEBAAAAwChbNQBWqRpPPQMCAAAAgFG2egCskvW/AAAAADDiytV+kFKqFYUBAQAAAMAoWzUAlmVR1GulCQEAAADACFs9ABZFMTHmFjAAAAAAjLJVA2BRROzaPmZCAAAAADDCVg2A9VoZh/ZOmRAAAAAAjLBVA2CtVsaTj+4xIQAAAAAYYRc8AXj3bYdMCAAAAABG2AWfAXjbDftMCAAAAABG2IoB8OtfdG+Z0iACAgAAAACja8UA2O91n9PrV6YDAAAAACNuxQDYac/d3+31TQcAAAAARtyKAXBubvb2TtcJQAAAAAAYdSsGwHa7fcwVYAAAAAAYfSsGwF6/v6cvAAIAAADAyFsxAHa7vclkNgAAAAAw8lbeAlxVrVpZmA4AAAAAjLgVA2BVpXqrWTMdAAAAABhx5WqvT441TQcAAAAARtxqATB2To2ZDgAAAACMuBUDYFFEsXfXhOkAAAAAwIhbJQAWceTAdtMBAAAAgBG3YgAsiyJuPLLbdAAAAABgxK0cAMsibr9hn+kAAAAAwIhbdQmIE4AAAAAAMPpWDIApJZMBAAAAgAysEgANBgAAAABy4AQgAAAAAGRs5QBoLgAAAACQhWUB8GtfcM/RqpIAAQAAACAHywJgpz333H5VmQwAAAAAZGBZAGx32rf3+04AAgAAAEAOVjgB2LnBEhAAAAAAyMOyANjtdg/KfwAAAACQh+UBsNfbXRaFyQAAAABABpYFwF6vN1WrCYAAAAAAkIPlAbBfjTXrNZMBAAAAgAwsC4D9ftUcH6ubDAAAAABkYHkArKr61ETLZAAAAAAgA8sCYFWl8pqd4yYDAAAAABkoV3rt2mu2mQwAAAAAZGClABjHD+0yGQAAAADIwEoBsLjl+r0mAwAAAAAZWPEE4NNv2m8yAAAAAJCBFQPgjm22AAMAAABADpYFwJQMBQAAAABysTwAhgIIAAAAALkojQAAAAAA8uUKMAAAAABkbIUAqAACAAAAQC6cAAQAAACAjHkGIAAAAABkbCgAvvyrv7zpBCAAAAAA5GMoAHba7acXhaEAAAAAQC6GA2CnfVutpgACAAAAQC7OC4CdJzfqNVMBAAAAgEwMBcBut3t4rFk3FQAAAADIxHkBsLd/aqJpKgAAAACQieErwN3u7l3bx0wFAAAAADIxFAD7/f7Uvt2TpgIAAAAAmThvCUhv4rr9200FAAAAADIxfAKwSq0nH91jKgAAAACQiaEA2Ov3m3fcfMBUAAAAACATQwEwpVS76chuUwEAAACATAwFwKIoUlkWpgIAAAAAmRgKgGVRJCMBAAAAgHwMB8BSAAQAAACAnAwFwHqtNBEAAAAAyMh5AbDmBCAAAAAAZGQoANZqrgADAAAAQE5cAQYAAACAjA0Vv2ajZiIAAAAAkJHzA6ArwAAAAACQkeEAWK8VRgIAAFntdjgAAB7ISURBVAAA+RgKgGOtuokAAAAAQEaGAuB4q+EEIAAAAABk5LwAWBcAAQAAACAjQwFw20SzNBIAAAAAyMdQ8Jscr9eMBAAAAADyMRwAx5oCIAAAAABk5FwAfMnfuKe5a3tLAAQAAACAjJwLgJ1O+2k3HdltCQgAAAAAZGQxALbbT7vthn0mAgAAAAAZORcAU0oHDu6dMhEAAAAAyMi5ANhq1scLF4ABAAAAICvnAmCjXmsaBwAAAADk5VwAbDZqDeMAAAAAgLwsDYBOAAIAAABAZpwABAAAAICMnQuAZVk4AQgAAAAAmbEEBAAAAAAydi4A1mtl3TgAAAAAIC9LA6BnAAIAAABAZs4FwFpZCIAAAAAAkJlzAbCI1DIOAAAAAMjL4gnAWuEZgAAAAACQGc8ABAAAAICMeQYgAAAAAGRsyTMAQwAEAAAAgMycC4BlKQACAAAAQG4WA2AhAAIAAABAbpZsARYAAQAAACA3iwGwsAQEAAAAAHJzLgCmVAmAAAAAAJCZpVuA68YBAAAAAHnxDEAAAAAAyFi55BsBEAAAAAAys3gFuHAFGAAAAAByU0ZEvPC+u8brNQEQAAAAAHJTRkT0ut3brr1mqjAOAAAAAMhLGRHR7XZvu/7wTtMAAAAAgMzMB8DOjTcd3WMaAAAAAJCZMiKiiJiammiaBgAAAABkpoyIqNdr6h8AAAAAZKiMiGjWaw2jAAAAAID8lIMvacIoAAAAACA/ZUREStWkUQAAAABAfuZPAMaYUQAAAABAfsqIiKqqBEAAAAAAyNBCAGwZBQAAAADkRwAEAAAAgIzNLwFJTaMAAAAAgPwsBMCGUQAAAABAfsqIiH5VOQEIAAAAABkanACsomYUAAAAAJCfMiKi1+/XjQIAAAAA8jO/BTg5AQgAAAAAGVpYAiIAAgAAAECGBicAUyqNAgAAAADyM38FuHICEAAAAAAyVEZElGVhEgAAAACQoTIiola6AQwAAAAAOSojIuo1ARAAAAAAcjQ4ASgAAgAAAECW5k8AFh4CCAAAAAAZmg+AlgADAAAAQI7KiIhG3RVgAAAAAMjRwhIQV4ABAAAAIEPzJwBdAQYAAACAHC1cAXYCEAAAAAAyNB8AbQEGAAAAgBwtXAEWAAEAAAAgQ2VERLMhAAIAAABAjsqIiFZTAAQAAACAHNVf/PxnFa3GIAQCAAAAAHkpU0r7pyabJgEAAAAAGSp7vd7ea3aOmwQAAAAAZKjs9Xr79u6aNAkAAAAAyFDZ7/f3HdgjAAIAAABAjsqq6l9zcO+USQAAAABAhsp+v9p13f7tJgEAAAAAGSrr9bIcb9VNAgAAAAAyVI41m11jAAAAAIA8leNjAiAAAAAA5KqcGG/1jAEAAAAA8lROTrScAAQAAACATJXbt00KgAAAAACQqXLn9klXgAEAAAAgU+XunducAAQAAACATJX7rtnZMQYAAAAAyFO5d88OJwABAAAAIFPlkUP7BEAAAAAAyFR5cP/uvjEAAAAAQJ7KLzx2YtIYAAAAACBP5ee/eGKbMQAAAABAnspTp6cFQAAAAADIVHnq9PSEMQAAAABAnsqzM3OeAQgAAAAAmSpn5+bGjQEAAAAA8lTOzrYFQAAAAADIVNnudMeMAQAAAADyVHY63ZYxAAAAAECeynanIwACAAAAQKbKbrcnAAIAAABApsputy8AAgAAAECmym6v1zQGAAAAAMhT2el2BUAAAAAAyFTZ7fUFQAAAAADIVNnr9uvGAAAAAAB5Knt9ARAAAAAAclX2KwEQAAAAAHJV9vtJAAQAAACATJX9fiUAAgAAAECmyn7VrxkDAAAAAOSp7PUqARAAAAAAMlVWKZXGAAAAAAB5Kvv9SgAEAAAAgEyV3W7fEhAAAAAAyFTZ7vacAAQAAACATJWdri3AAAAAAJCrstvrOwEIAAAAAJkqU0qmAAAAAACZKmu1mgIIAAAAAJkqy6IwBQAAAADIVFmrCYAAAAAAkKuyVpauAAMAAABApsq6E4AAAAAAkK2yVitNAQAAAAAyVdZrrgADAAAAQK7KuhOAAAAAAJAtARAAAAAAMiYAAgAAAEDGyka95hmAAAAAAJCpsl53AhAAAAAAcuUKMAAAAABkrGw4AQgAAAAA2SqbzZopAAAAAECmykZdAAQAAACAXJVNARAAAAAAslU2GwIgAAAAAOSqbDXrpgAAAAAAmXICEAAAAAAyVtZrpSkAAAAAQKbKsaYTgAAAAACQq7LVrBfGAAAAAAB5KscsAQEAAACAbJVjLScAAQAAACBX5XjLCUAAAAAAyFU51mw4AQgAAAAAmSqbjVIABAAAAIBMlWO2AAMAAABAtsrxMQEQAAAAAHJVTox5BiAAAAAA5KqcaNVKYwAAAACAPJXjLVeAAQAAACBX5eR4wwlAAAAAAMhUOdZ0BRgAAAAAciX+AQAAAEDGBEAAAAAAyJgACAAAAAAZEwABAAAAIGMCIAAAAABkTAAEAAAAgIwJgAAAAACQMQEQAAAAADImAAIAAABAxgRAAAAAAMiYAAgAAAAAGRMAAQAAACBjAiAAAAAAZEwABAAAAICMCYAAAAAAkDEBEAAAAAAyJgACAAAAQMYEQAAAAADImAAIAAAAABkTAAEAAAAgYwIgAAAAAGRMAAQAAACAjAmAAAAAAJAxARAAAAAAMiYAAgAAAEDGBEAAAAAAyJgACAAAAAAZEwABAAAAIGMCIAAAAABkTAAEAAAAgIwJgAAAAACQMQEQAAAAADImAAIAAABAxgRAAAAAAMiYAAgAAAAAGRMAAQAAACBjAiAAAAAAZEwABAAAAICMCYAAAAAAkDEBEAAAAAAyJgACAAAAQMYEQAAAAADImAAIAAAAABkTAAEAAAAgYwIgAAAAAGRMAAQAAACAjAmAAAAAAJAxARAAAAAAMiYAAgAAAEDGBEAAAAAAyJgACAAAAAAZEwABAAAAIGMCIAAAAABkTAAEAAAAgIwJgAAAAACQMQEQAAAAADImAAIAAABAxgRAAAAAAMiYAAgAAAAAGRMAAQAAACBjAiAAAAAAZEwABAAAAICMCYAAAAAAkDEBEAAAAAAyJgACAAAAQMYEQAAAAADImAAIAAAAABkTAAEAAAAgYwIgAAAAAGRMAAQAAACAjAmAAAAAAJAxARAAAAAAMiYAAgAAAEDGBEAAAAAAyJgACAAAAAAZEwABAAAAIGMCIAAAAABkTAAEAAAAgIwJgAAAAACQMQEQAAAAADImAAIAAABAxgRAAAAAAMiYAAgAAAAAGRMAAQAAACBjAiAAAAAAZEwABAAAAICMCYAAAAAAkDEBEAAAAAAyJgACAAAAQMYEQAAAAADImAAIAAAAABkTAAEAAAAgYwIgAAAAAGRMAAQAAACAjAmAAAAAAJAxARAAAAAAMiYAAgAAAEDGBEAAAAAAyJgACAAAAAAZEwABAAAAIGMCIAAAAABkTAAEAAAAgIwJgAAAAACQMQEQAAAAADImAAIAAABAxgRAAAAAAMiYAAgAAAAAGRMAAQAAACBjAiAAwP9v185REAigIArCd4nFVDAQvP/VxAWZQcV7PKqO0OGjAQAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBs3svnZwYAAAAAaJrbYxEAAQAAACBqbs/1awYAAAAAaJr7ywMQAAAAAKrm/lqtAAAAAABRsyzr3gwAAAAA0DS77WzMAAAAAABNcz0frQAAAAAAUXM5HawAAAAAAFFjAgAAAADoEgABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwgRAAAAAAAgTAAEAAAAgTAAEAAAAgDABEAAAAADCBEAAAAAACBMAAQAAACBMAAQAAACAMAEQAAAAAMIEQAAAAAAIEwABAAAAIEwABAAAAIAwARAAAAAAwv60rDzN2YM6WgAAAABJRU5ErkJggg=="); +} + +]]> +</html:style> + +<!-- Interface --> + +<deck flex="1" id="deck"> + +<vbox flex="1"> + <toolbox id="canvasToolbar"> + <toolbar> + <toolbarbutton oncommand="Presentation.home()" label="|<<" + observes="canBack"/> + <toolbarbutton oncommand="Presentation.back()" label="<" + observes="canBack"/> + <toolbarbutton oncommand="Presentation.forward()" label=">" + observes="canForward"/> + <toolbarbutton oncommand="Presentation.end()" label=">>|" + observes="canForward"/> + <toolbarseparator/> + <hbox align="center"> + <textbox id="current_page" size="4" + oninput="if (this.value) Presentation.showPage(parseInt(this.value)-1);"/> + <toolbarbutton id="pages-list-button" + type="menu" + label="Select Page" + tooltiptext="Select Page" + class="dropmarker-button"> + <menupopup id="pages-list" + onpopupshowing="if (event.target == this) Presentation.preventToShowHideToolbar = true;" + onpopuphiding="if (event.target == this) Presentation.preventToShowHideToolbar = false;" + oncommand="Presentation.showPage(parseInt(event.target.value));"/> + </toolbarbutton> + <description value="/"/> + <description id="max_page"/> + </hbox> + <toolbarseparator/> + <vbox flex="2"> + <spacer flex="1"/> + <scrollbar id="scroller" + align="center" orient="horizontal" + oncommand="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));" + onclick="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));" + onmousedown="Presentation.onScrollerDragStart();" + onmousemove="Presentation.onScrollerDragMove();" + onmouseup="Presentation.onScrollerDragDrop();"/> + <spacer flex="1"/> + </vbox> + <toolbarseparator/> + <toolbarbutton label="Pen" + id="penButton" + type="checkbox" + autoCheck="false" + oncommand="StrokablePresentationService.toggleCheck();"/> + <spacer flex="1"/> + <toolbarbutton id="func-menu-button" + type="menu" + label="Function"> + <menupopup + onpopupshowing="if (event.target == this) { Presentation.preventToShowHideToolbar = true; Presentation.updateTimerItem(); }" + onpopuphiding="if (event.target == this) Presentation.preventToShowHideToolbar = false;"> + <menuitem id="timerItem" + label="Set Timer" + label-normal="Set Timer" + label-active="Reset Timer (rest %smin)" + oncommand="Presentation.setTimer();" /> + <menuseparator/> + <menuitem label="Start Auto-Cruise" + id="autoButton" + type="checkbox" + autoCheck="false" + oncommand="Presentation.toggleAutoCruiseMode();" /> + <menu id="auto-interval-button" + label="Change Interval"> + <menupopup id="auto-interval-list" + onpopupshowing="(this.getElementsByAttribute('value', Presentation.autoCruiseInterval)[0] || this.lastChild).setAttribute('checked', true);" + oncommand="Presentation.changeAutoCruiseInterval(parseInt(event.target.value));"> + <menuitem type="radio" radiogroup="autocruise-interval" + label="1 sec" value="1000"/> + <menuitem type="radio" radiogroup="autocruise-interval" + label="2 sec" value="2000"/> + <menuitem type="radio" radiogroup="autocruise-interval" + label="3 sec" value="3000"/> + <menuitem type="radio" radiogroup="autocruise-interval" + label="4 sec" value="4000"/> + <menuitem type="radio" radiogroup="autocruise-interval" + label="5 sec" value="5000"/> + <menuseparator/> + <menuitem type="radio" radiogroup="autocruise-interval" + label="1 min" value="60000"/> + <menuitem type="radio" radiogroup="autocruise-interval" + label="2 min" value="120000"/> + <menuitem type="radio" radiogroup="autocruise-interval" + label="3 min" value="180000"/> + <menuitem type="radio" radiogroup="autocruise-interval" + label="4 min" value="240000"/> + <menuitem type="radio" radiogroup="autocruise-interval" + label="5 min" value="300000"/> + <menuseparator/> + <menuitem type="radio" radiogroup="autocruise-interval" + label="Custom" + oncommand=" + var current = Presentation.autoCruiseInterval; + var val = parseInt(prompt('input interval (sec)', parseInt(current/1000))); + if (isNaN(val)) { + event.preventBubble(); + return; + } + else + val = val * 1000; + this.value = val; + "/> + </menupopup> + </menu> + <menuseparator/> + <menuitem oncommand="Presentation.print();" label="Print"/> + <menu id="auto-interval-button" + label="Thumbnail Format"> + <menupopup + onpopupshowing="(this.getElementsByAttribute('value', Presentation.imageType)[0] || this.firstChild).setAttribute('checked', true);" + oncommand="Presentation.imageType = event.target.value;"> + <menuitem type="radio" radiogroup="print-image-type" + label="PNG" value="png"/> + <menuitem type="radio" radiogroup="print-image-type" + label="JPEG (50%)" value="jpeg"/> + </menupopup> + </menu> + <menuseparator/> + <menuitem id="showPlainText" label="View Source" + key="key_plainText" + oncommand="Presentation.showPlainText();"/> + <menuseparator/> + <menuitem id="toggleEva" label="Eva Mode" + key="key_toggleEvaMode" + type="checkbox" + autoCheck="false" + oncommand="Presentation.toggleEvaMode();"/> + </menupopup> + </toolbarbutton> + <toolbarseparator/> + <toolbarbutton label="Edit" + oncommand="Presentation.toggleEditMode();"/> + <toolbarbutton oncommand="Presentation.reload();" label="Reload"/> + </toolbar> + </toolbox> + <vbox flex="1" id="canvas"> + <stack flex="1"> + <vbox flex="1"> + <hbox id="headerBox" flex="1"> + <label id="header"/> + <spacer flex="1"/> + <vbox> + <image id="logo"/> + <spacer flex="1"/> + </vbox> + </hbox> + <spacer flex="19"/> + <hbox id="footerBox" flex="1"> + <spacer flex="1"/> + <label id="footer"/> + </hbox> + </vbox> + <vbox id="canvasMain" + flex="1" + onmouseup="Presentation.handleEvent(event);" + onmousedown="Presentation.handleEvent(event);" + onmousemove="Presentation.handleEvent(event);" + onclick="Presentation.onPresentationClick(event);"> + <spacer flex="1"/> + <hbox flex="1" id="contentBox"> + <spacer flex="1"/> + <vbox id="content"/> + <spacer flex="1"/> + </hbox> + <spacer flex="1"/> + </vbox> + <vbox id="plainTextBox" + hidden="true" + flex="1" + onclick="Presentation.hidePlainText();" + align="center" + pack="center"> + <textbox id="plainTextField" multiline="true" + onkeypress="if (event.keyCode == event.DOM_VK_ESCAPE) Presentation.hidePlainText();" + onclick="event.stopPropagation();"/> + </vbox> + </stack> + </vbox> + <hbox id="indicatorBar" + onclick="Presentation.onIndicatorBarClick(event);"> + <stack flex="1"> + <vbox> + <progressmeter id="remainingPageIndicator" + type="determined" value="0" + flex="1"/> + <progressmeter id="remainingTimeIndicator" + type="determined" value="0" + flex="1" + collapsed="true"/> + </vbox> + <hbox flex="1"> + <label value="Next:"/> + <description id="nextPage" flex="1" crop="end"/> + </hbox> + </stack> + </hbox> +</vbox> + +<vbox flex="1" id="edit"> + <toolbox> + <toolbar> + <menubar flex="1"> + <menu label="File"> + <menupopup> + <menuitem label="Save" + key="key_save" + oncommand="Presentation.output()"/> + <menuitem label="Reload" + key="key_reload" + oncommand="Presentation.reload()"/> + </menupopup> + </menu> + <menu label="Insert"> + <menupopup> + <menuitem label="New Page" + key="key_insert_newpage" + oncommand="Presentation.insert('page')"/> + <menuseparator/> + <menuitem label="Header" + oncommand="Presentation.insert('header')"/> + <menuitem label="Footer" + oncommand="Presentation.insert('footer')"/> + <menuseparator/> + <menuitem label="Link" + oncommand="Presentation.insert('link')"/> + <menuitem label="Emphasis" + oncommand="Presentation.insert('em')"/> + <menuitem label="Preformatted" + oncommand="Presentation.insert('pre')"/> + <menuitem label="Monta" + oncommand="Presentation.insert('monta')"/> + <menuitem label="Image" + oncommand="Presentation.insert('img')"/> + </menupopup> + </menu> + </menubar> + <toolbarseparator/> + <toolbarbutton label="View" + oncommand="Presentation.toggleEditMode();"/> + <toolbarbutton oncommand="Presentation.reload();" label="Reload"/> + </toolbar> + </toolbox> + <tabbox id="editTabBox" flex="1"> + <tabs onselect="Presentation.toggleEditStyle(event);"> + <tab label="Page Edit" id="editTab-pages"/> + <tab label="Source" id="editTab-source"/> + </tabs> + <tabpanels flex="1"> + <scrollbox id="pageEditFields" + orient="vertical" + flex="1"/> + <textbox id="sourceEditField" + flex="1" + multiline="true" + oninput="Presentation.onEditSource()"/> + </tabpanels> + </tabbox> +</vbox> + +</deck> + +<data style="visibility: collapse;"> + <hbox id="pageEditBoxTemplate"> + <textbox multiline="true" + class="page-edit-box-main" + flex="1" + oninput="Presentation.onEditPage(Number(this.parentNode.parentNode.id.match(/\d+/)))"/> + <vbox> + <toolbarbutton label="Ã" + oncommand="Presentation.removePage(Number(this.parentNode.parentNode.id.match(/\d+/)));"/> + </vbox> + </hbox> +</data> + +<broadcasterset> + <broadcaster id="canBack"/> + <broadcaster id="canForward"/> +</broadcasterset> + +<commandset> + <command id="cmd_forward" + oncommand="if (Presentation.isPresentationMode) Presentation.forward();"/> + <command id="cmd_forwardStep" + oncommand="if (Presentation.isPresentationMode) Presentation.forwardStep();"/> + <command id="cmd_back" + oncommand="if (Presentation.isPresentationMode) Presentation.back();"/> + <command id="cmd_home" + oncommand="if (Presentation.isPresentationMode) Presentation.home();"/> + <command id="cmd_end" + oncommand="if (Presentation.isPresentationMode) Presentation.end();"/> +</commandset> + +<keyset> + <key keycode="VK_ENTER" command="cmd_forwardStep"/> + <key keycode="VK_RETURN" command="cmd_forwardStep"/> + <key keycode="VK_PAGE_DOWN" command="cmd_forwardStep"/> + <key keycode="VK_RIGHT" command="cmd_forwardStep"/> + <key keycode="VK_DOWN" command="cmd_forwardStep"/> + <!--key keycode="VK_BACK_SPACE" command="cmd_back"/--> + <key keycode="VK_PAGE_UP" command="cmd_back"/> + <key keycode="VK_UP" command="cmd_back"/> + <key keycode="VK_LEFT" command="cmd_back"/> + <key keycode="VK_HOME" command="cmd_home"/> + <key keycode="VK_END" command="cmd_end"/> + + <key id="key_insert_newpage" + key="n" modifiers="accel" oncommand="Presentation.insert('page');"/> + + <key id="key_save" + key="s" modifiers="accel" oncommand="Presentation.output();"/> + <key id="key_reload" + key="r" modifiers="accel" oncommand="Presentation.reload();"/> + <key id="key_reload" + key="p" modifiers="accel" oncommand="Presentation.print();"/> + + <key id="key_toggleEditMode" + key="e" modifiers="accel" oncommand="Presentation.toggleEditMode();"/> + <key id="key_toggleEvaMode" + key="e" modifiers="accel,shift" oncommand="Presentation.toggleEvaMode();"/> + + <key id="key_plainText" + key="u" modifiers="accel" oncommand="Presentation.showPlainText();"/> + <key keycode="VK_ESCAPE" oncommand="Presentation.hidePlainText();"/> +</keyset> + +<!-- Implementation --> +<script type="application/x-javascript; e4x=1"><![CDATA[ + +const XULNS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'; +const XHTMLNS = 'http://www.w3.org/1999/xhtml'; + +var Presentation = { + + baseSize : 9, + montaLabelImage : 'monta-label.png', + + //phraseOpenParen : '[', + //phraseCloseParen : ']', + phraseOpenParen : '%%', + phraseCloseParen : '%%', + makePhraseRegExp : function(aPattern, aFlags) + { + return new RegExp( + aPattern.replace(/%o(pen)?/gi, '\\'+this.phraseOpenParen) + .replace(/%c(lose)?/gi, '\\'+this.phraseCloseParen), + aFlags + ); + }, + + dragStartDelta : 8, + + imageType : 'jpeg', + + EDIT_BOX_ID_PREFIX : 'editPageBox-', + + initialized : false, + + preventToShowHideToolbar : false, + + showMontaKeywordTimeout : 100, + autoCruiseInterval : 2000, + timerUpdatingInterval : 30000, + + cachedContents : [], + sourceData : [], + + init : function(option){ + if (this.initialized) { + this.startPresentation(); + return; + } + this.initialized = true; + + + this._offset = 0; + this.canvas = document.getElementById('canvas'); + this.canvasMain = document.getElementById('canvasMain'); + this.content = document.getElementById('content'); + this.header = document.getElementById('header'); + this.footer = document.getElementById('footer'); + this.logo = document.getElementById('logo'); + this.next = document.getElementById('nextPage'); + + this.indicatorBar = document.getElementById('indicatorBar'); + this.remainder = document.getElementById('remainingPageIndicator'); + this.timer = document.getElementById('remainingTimeIndicator'); + + this.list = document.getElementById('pages-list'); + this.source = document.getElementById('sourceEditField'); + this.pages = document.getElementById('pageEditFields'); + this.deck = document.getElementById('deck'); + this.scroller = document.getElementById('scroller'); + + this.toolbar = document.getElementById('canvasToolbar'); + this.toolbarHeight = this.toolbar.boxObject.height; + this.isToolbarHidden = true; + this.toolbar.setAttribute('style', 'margin-top:'+(0-this.toolbarHeight)+'px;margin-bottom:0px;'); + + this.preloadImage(this.montaLabelImage); + + window.addEventListener('resize', this, false); + window.addEventListener('contextmenu', this, false); + window.addEventListener('CanvasContentAdded', this, false); + + this.canvasMain.addEventListener('DOMMouseScroll', this, false); + this.indicatorBar.addEventListener('DOMMouseScroll', this, false); + + if(option){ + for(var i in option){this[i] = option[i]} + } + + this.cachedContents = []; + + if (this.readParameter()) { + this.startPresentation(); + } + + document.documentElement.focus(); + }, + +/* core */ + + startPresentation : function() + { + if (this.data.length) + document.title = this.data[0].title || this.data[0].header || this.data[0].text.join(' '); + + this.takahashi(); + }, + +/* rendering */ + + takahashi : function() { + this.isRendering = true; + + if (!this.data[this.offset]) { + this.offset = this.data.length-1; + } + document.getElementById("current_page").value = this.offset+1; + document.getElementById("max_page").value = this.data.length; + + this.scroller.setAttribute('maxpos', this.data.length-1); + this.scroller.setAttribute('curpos', this.offset); + + var broadcaster = document.getElementById('canBack'); + if (!this.offset) + broadcaster.setAttribute('disabled', true); + else + broadcaster.removeAttribute('disabled'); + + var broadcaster = document.getElementById('canForward'); + if (this.offset == this.data.length-1) + broadcaster.setAttribute('disabled', true); + else + broadcaster.removeAttribute('disabled'); + + this.canvas.setAttribute('rendering', true); + + + this.header.removeAttribute('style'); + this.footer.removeAttribute('style'); + this.content.removeAttribute('style'); + + this.clickableNodes = []; + + + if ('title' in this.data[this.offset]) + document.title = this.data[this.offset].title; + + this.header.setAttribute('style', 'font-size:10px;'); + this.header.value = this.data[this.offset].header; + this.footer.setAttribute('style', 'font-size:10px;'); + this.footer.value = this.data[this.offset].footer; + + var page = this.content.getAttribute('page'); + var range = document.createRange(); + range.selectNodeContents(this.content); + this.cachedContents[page] = !this.content.hasChildNodes() ? null : { + fragment : range.extractContents(), + offsetWidth : parseInt(this.content.getAttribute('offsetWidth')), + offsetHeight : parseInt(this.content.getAttribute('offsetHeight')) + }; + range.detach(); + + + if (this.data[this.offset].load) { + this.isRendering = false; + location.replace(location.href.split('?')[0] + '?'+this.data[this.offset].load); + return; + } + + var content = (this.offset in this.cachedContents && this.cachedContents[this.offset]) ? + this.cachedContents[this.offset] : + this.createContent(); + + this.content.setAttribute('style', 'font-size:10px;'); + this.content.setAttribute('page', this.offset); + this.content.setAttribute('offsetWidth', content.offsetWidth); + this.content.setAttribute('offsetHeight', content.offsetHeight); + + this.content.appendChild(content.fragment); + + this.clickableNodes.push(this.content); + + + this.fitHeaderFooterToCanvas(); + this.fitMainContentToCanvas(); + + + try { + var checkedItems = this.list.getElementsByAttribute('checked', 'true'); + max = checkedItems.length; + for (i = max-1; i > -1 ; i--) + checkedItems[i].removeAttribute('checked'); + } + catch(e) { + } + + this.list.getElementsByAttribute('value', this.offset)[0].setAttribute('checked', true); + + this.canvas.removeAttribute('rendering'); + this.isRendering = false; + this.setHash('page', 'page'+(this.offset+1)); + + this.next.value = (this.offset <= this.data.length-2) ? (this.data[this.offset+1].plain.join('') || this.data[this.offset+1].text.join('')).replace(/\s+/g, ' ') : '(no page)' ; + this.remainder.setAttribute('value', this.offset == 0 ? 0 : parseInt(((this.offset)/(this.data.length-1))*100)); + + var event = document.createEvent('Events'); + event.initEvent('PresentationRedraw', false, true); + this.canvas.dispatchEvent(event); + }, + + createContent : function() + { + var retVal = { + offsetWidth : 0, + offsetHeight : 0 + }; + var text = this.data[this.offset].text; + var line; + var newLine; + var uri; + var image_width; + var image_height; + var image_src; + + var labelId = 0; + var lineRegExp = this.makePhraseRegExp('^([^%O]+)?(%O%Oem:((.+?)(:em)?%C%C)?|%O%O(raw|encoded):((.+?)(:raw|:encoded)?%C%C)?|%O%Opre:((.+?)(:pre)?%C%C)?|%O%O\#[^:]+:((.+?)%C%C)?|%O%Oima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^%C]*%C%C|%O%O(([^\|]+)?\\||)([^%C]+)%C%C|%O([^%C]+)%C)(.+)?', 'i'); + + var emRegExp = this.makePhraseRegExp('^([^%O]+)?%O%Oem({([^}]*)})?:(.+?)()?%C%C', 'i'); + var emStartRegExp = this.makePhraseRegExp('^([^%O]+)?%O%Oem({([^}]*)})?:(.*)', 'i'); + var emEndRegExp = this.makePhraseRegExp('^(.*?)((:em)?%C%C)', 'i'); + + var preRegExp = this.makePhraseRegExp('^([^%O]+)?%O%Opre({([^}]*)})?:(.+?)(:pre)?%C%C', 'i'); + var preStartRegExp = this.makePhraseRegExp('^([^%O]+)?%O%Opre({([^}]*)})?:(.*)', 'i'); + var preEndRegExp = this.makePhraseRegExp('^(.*?)((:pre)?%C%C)', 'i'); + + var rawRegExp = this.makePhraseRegExp('^([^%O]+)?%O%O(raw|encoded)({([^}]*)})?:(.+?)(:raw|:encoded)?%C%C', 'i'); + var rawStartRegExp = this.makePhraseRegExp('^([^%O]+)?%O%O(raw|encoded)({([^}]*)})?:(.*)', 'i'); + var rawEndRegExp = this.makePhraseRegExp('^(.*?)((:raw|:encoded)?%C%C)', 'i'); + + var styleRegExp = this.makePhraseRegExp('^([^%O]+)?%O%O(#([^:{]*))?({([^}]*)})?:(.+?)%C%C', ''); + var styleStartRegExp = this.makePhraseRegExp('^([^%O]+)?%O%O(#([^:{]*))?({([^}]*)})?:(.*)', ''); + var styleEndRegExp = this.makePhraseRegExp('^(.*?)(%C%C)', ''); + + var imagesRegExp = this.makePhraseRegExp('^([^%O]+)?%O%Oima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^%C]*%C%C', 'i'); + + var linksRegExp = this.makePhraseRegExp('^([^%O]+)?%O%O(([^|]+)?\\||)([^%C]+)%C%C', ''); + + var montaRegExp = this.makePhraseRegExp('^([^%O]+)?%O([^%C]+)%C', ''); + + var inBlock = false, + blockClass = '', + blockStyle = '', + blockContents = []; + + var inGrid = false, + gridContents = null; + + var fragment = document.createDocumentFragment(); + + var lineBox; + for (var i = 0, max = text.length; i < max; i++) + { + lineBox = document.createElement('hbox'); + lineBox.setAttribute('align', 'center'); + lineBox.setAttribute('pack', this.data[this.offset].align); + + line = text[i]; + image_width = 0; + image_height = 0; + if (!line) line = ' '; + + if (inBlock) { + if (blockClass == 'raw' && + rawEndRegExp.test(line)) { + inBlock = false; + blockContents.push(RegExp.$1); + line = line.substring((RegExp.$1+RegExp.$2).length); + + eval('var xml = <hbox class="raw" style="blockStyle" onclick="event.stopPropagation();" onkeypress="event.stopPropagation();">'+blockContents.join('\n')+'</hbox>;'); + importNodeTreeWithDelay(importE4XNode(xml, document, XULNS), lineBox, XULNS); + + blockClass = ''; + blockStyle = ''; + blockContents = []; + } + else if (blockClass == 'preformatted-text' && + preEndRegExp.test(line)) { + inBlock = false; + blockContents.push(RegExp.$1); + line = line.substring((RegExp.$1+RegExp.$2).length); + + lineBox.appendChild(document.createElement('description')); + lineBox.lastChild.setAttribute('class', 'preformatted-text block'); + if (blockStyle) + lineBox.lastChild.setAttribute('style', blockStyle); + lineBox.lastChild.appendChild(document.createTextNode( + blockContents.join('\n') + .replace(/^[\r\n\s]+/, '') + .replace(/[\r\n\s]+$/, '') + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/>/g, '>') + .replace(/</g, '<') + )); + + blockClass = ''; + blockStyle = ''; + blockContents = []; + } + else if (emEndRegExp.test(line) || styleEndRegExp.test(line)) { + inBlock = false; + blockContents.push(RegExp.$1); + line = line.substring((RegExp.$1+RegExp.$2).length); + + lineBox.appendChild(document.createElement('vbox')); + lineBox.lastChild.setAttribute('class', blockClass+' block'); + if (blockStyle) + lineBox.lastChild.setAttribute('style', blockStyle); + lineBox.lastChild.setAttribute('align', this.data[this.offset].align); + blockContents = blockContents.join('\n') + .replace(/^[\r\n\s]+/, '') + .replace(/[\r\n\s]+$/, '') + .split('\n'); + for (var j = 0, jmax = blockContents.length; j < jmax; j++) + { + lineBox.lastChild.appendChild(document.createElement('description')); + lineBox.lastChild.lastChild.setAttribute('value', blockContents[j]); + } + + blockClass = ''; + blockStyle = ''; + blockContents = []; + } + else { + blockContents.push(line); + continue; + } + } + + if (line.indexOf('|') == 0) { + fragment.appendChild(lineBox); + + if (fragment.childNodes.length == 1 || + !fragment.childNodes[fragment.childNodes.length-2] || + !fragment.childNodes[fragment.childNodes.length-2].lastChild || + fragment.childNodes[fragment.childNodes.length-2].lastChild.localName != 'grid') { + fragment.lastChild.appendChild(document.createElement('grid')); + fragment.lastChild.lastChild.appendChild(document.createElement('columns')); + fragment.lastChild.lastChild.appendChild(document.createElement('rows')); + } + else { + fragment.removeChild(fragment.lastChild); + } + fragment.lastChild.lastChild.lastChild.appendChild(document.createElement('row')); + fragment.lastChild.lastChild.lastChild.lastChild.setAttribute('flex', 1); + + line = line.split('|'); + for (var j = 1, jmax = line.length; j < jmax; j++) + { + fragment.lastChild.lastChild.lastChild.lastChild.appendChild(document.createElement('vbox')); + fragment.lastChild.lastChild.lastChild.lastChild.lastChild.setAttribute('align', this.data[this.offset].align); + fragment.lastChild.lastChild.lastChild.lastChild.lastChild.setAttribute('pack', 'center'); + if (line[j].charAt(0) == '~') { + fragment.lastChild.lastChild.lastChild.lastChild.lastChild.setAttribute('class', 'special'); + line[j] = line[j].substring(1); + } + line[j] = line[j].split(/<br\s*\/>/g); + for (var k = 0, kmax = line[j].length; k < kmax; k++) + { + fragment.lastChild.lastChild.lastChild.lastChild.lastChild.appendChild(document.createElement('description')); + fragment.lastChild.lastChild.lastChild.lastChild.lastChild.lastChild.appendChild(document.createTextNode(line[j][k].replace(/^\s+|\s+$/g, ''))); + } + if (fragment.lastChild.lastChild.firstChild.childNodes.length < j) { + fragment.lastChild.lastChild.firstChild.appendChild(document.createElement('column')); + fragment.lastChild.lastChild.firstChild.lastChild.setAttribute('flex', 1); + } + } + continue; + } + + + while (line.match(lineRegExp)) + { + if (RegExp.$1) { + lineBox.appendChild(document.createElement('description')); + lineBox.lastChild.setAttribute('value', RegExp.$1); + } + newLine = line.substring((RegExp.$1+RegExp.$2).length); + + // Raw Codes: Parsed as XML + if (rawRegExp.test(line)) { + eval('var xml = <hbox class="raw" style="'+RegExp.$4+'" onclick="event.stopPropagation();" onkeypress="event.stopPropagation();">'+RegExp.$5+'</hbox>;'); + importNodeTreeWithDelay(importE4XNode(xml, document, XULNS), lineBox, XULNS); + } + else if (rawStartRegExp.test(line)) { + inBlock = true; + blockClass = 'raw'; + blockStyle = RegExp.$4; + blockContents = [RegExp.$5]; + newLine = ''; + } + + // Preformatted Text + if (preRegExp.test(line)) { + lineBox.appendChild(document.createElement('description')); + if (RegExp.$3) + lineBox.lastChild.setAttribute('style', RegExp.$3); + lineBox.lastChild.setAttribute('value', RegExp.$4); + lineBox.lastChild.setAttribute('class', 'preformatted-text'); + } + else if (preStartRegExp.test(line)) { + inBlock = true; + blockClass = 'preformatted-text'; + blockStyle = RegExp.$3; + blockContents = [RegExp.$4]; + newLine = ''; + } + + // Emphasis + else if (emRegExp.test(line)) { + lineBox.appendChild(document.createElement('description')); + if (RegExp.$3) + lineBox.lastChild.setAttribute('style', RegExp.$3); + lineBox.lastChild.setAttribute('value', RegExp.$4); + lineBox.lastChild.setAttribute('class', 'em-text'); + } + else if (emStartRegExp.test(line)) { + inBlock = true; + blockClass = 'em-text'; + blockStyle = RegExp.$3; + blockContents = [RegExp.$4]; + newLine = ''; + } + + // User-defined Styles + else if (styleRegExp.test(line)) { + lineBox.appendChild(document.createElement('description')); + lineBox.lastChild.setAttribute('class', RegExp.$3); + if (RegExp.$5) + lineBox.lastChild.setAttribute('style', RegExp.$5); + lineBox.lastChild.setAttribute('value', RegExp.$6); + } + else if (styleStartRegExp.test(line)) { + inBlock = true; + blockClass = RegExp.$3; + blockStyle = RegExp.$5; + blockContents = [RegExp.$6]; + newLine = ''; + } + + // Images + else if (imagesRegExp.test(line)) { + lineBox.appendChild(document.createElement('image')); + image_src = RegExp.$2; + if (image_src.indexOf('http://') < 0 && + image_src.indexOf('https://') < 0 && + image_src.indexOf('data:') < 0) + image_src = this.dataFolder+image_src; + lineBox.lastChild.setAttribute('src', image_src); + lineBox.lastChild.setAttribute('width', parseInt(RegExp.$3 || '0')); + lineBox.lastChild.setAttribute('height', parseInt(RegExp.$4 || '0')); + image_width += parseInt(RegExp.$3 || '0'); + image_height = Math.max(image_height, parseInt(RegExp.$4 || '0')); + } + + // Links + else if (linksRegExp.test(line)) { + uri = RegExp.$4; + if (uri.indexOf('://') < 0) + uri = this.dataFolder+uri; + lineBox.appendChild(document.createElement('description')); + lineBox.lastChild.setAttribute('value', RegExp.$3 || RegExp.$4); + lineBox.lastChild.setAttribute('href', uri); + lineBox.lastChild.setAttribute('tooltiptext', uri); + lineBox.lastChild.setAttribute('statustext', uri); + lineBox.lastChild.setAttribute('class', 'link-text'); + + this.clickableNodes.push(lineBox.lastChild); + } + + // Monta + else if (montaRegExp.test(line)) { + lineBox.appendChild(document.createElement('stack')); + + lineBox.lastChild.appendChild(document.createElement('description')); + lineBox.lastChild.lastChild.setAttribute('value', RegExp.$2); + lineBox.lastChild.lastChild.setAttribute('class', 'monta-text'); + + lineBox.lastChild.appendChild(document.createElement('spacer')); + lineBox.lastChild.lastChild.setAttribute('flex', 1); + lineBox.lastChild.lastChild.setAttribute('class', 'monta-label'); + + lineBox.lastChild.lastChild.setAttribute('label-id', 'label-' + (++labelId)); + + lineBox.lastChild.lastChild.setAttribute('monta-hidden', 'true'); + + this.clickableNodes.push(lineBox.lastChild.lastChild); + } + + line = newLine; + } + + if (line) { + lineBox.appendChild(document.createElement('description')); + lineBox.lastChild.setAttribute('value', line); + } + + retVal.offsetWidth = Math.max(retVal.offsetWidth, image_width); + retVal.offsetHeight += image_height; + + if (lineBox.hasChildNodes()) + fragment.appendChild(lineBox); + } + + retVal.fragment = fragment; + return retVal; + }, + + fitToCanvas : function(aContent, aCanvas, aOffsetWidth, aOffsetHeight) + { + aContent.removeAttribute('style'); + aContent.setAttribute('style', 'font-size:10px;'); + + var grids = aContent.getElementsByTagName('grid'); + var gridsCount = grids.length; + + if (!aContent.boxObject.width) return; + + var canvas_w = aCanvas.boxObject.width; + var canvas_h = aCanvas.boxObject.height-aOffsetHeight; + + var content_w = aContent.boxObject.width; + var new_fs = Math.round((canvas_w/content_w) * this.data[this.offset].size); + aContent.setAttribute('style', 'font-size:'+ new_fs + "px"); + + for (var i = 0; i < gridsCount; i++) + { + grids[i].firstChild.lastChild.removeAttribute('flex', 1); + grids[i].firstChild.lastChild.setAttribute('flex', 1); + } + + if (aContent.boxObject.width < aOffsetWidth) { + content_w = aOffsetWidth; + new_fs = Math.round((canvas_w/content_w) * this.data[this.offset].size); + aContent.setAttribute('style', 'font-size:'+ new_fs + "px"); + + for (var i = 0; i < gridsCount; i++) + { + grids[i].firstChild.lastChild.removeAttribute('flex', 1); + grids[i].firstChild.lastChild.setAttribute('flex', 1); + } + } + + var content_h = aContent.boxObject.height; + if(content_h >= canvas_h){ + state='height'; + content_h = aContent.boxObject.height; + new_fs = Math.round((canvas_h/content_h) * new_fs); + aContent.setAttribute('style', 'font-size:'+ new_fs + "px"); + + for (var i = 0; i < gridsCount; i++) + { + grids[i].firstChild.lastChild.removeAttribute('flex', 1); + grids[i].firstChild.lastChild.setAttribute('flex', 1); + } + } + }, + + fitMainContentToCanvas : function() + { + this.fitToCanvas( + this.content, + this.canvas, + parseInt(this.content.getAttribute('offsetWidth')), + parseInt(this.content.getAttribute('offsetHeight')) + +this.header.boxObject.height + +this.footer.boxObject.height + ); + }, + + fitHeaderFooterToCanvas : function() + { + this.fitToCanvas(this.header, this.header.parentNode, 0, 0); + this.fitToCanvas(this.footer, this.footer.parentNode, 0, 0); + }, + + get offset(){ + return this._offset; + }, + set offset(aValue){ + this._offset = parseInt(aValue || 0); + document.documentElement.setAttribute('lastoffset', this.offset); + return this.offset; + }, + +/* data I/O */ + + setHash : function(aKey, aValue) + { + aKey = String(aKey).toLowerCase(); + var hashArray = String(location.hash).replace(/^#/, '').toLowerCase().split(','); + + for (var i = hashArray.length-1; i > -1; i--) + if (!hashArray[i] || hashArray[i].indexOf(aKey) == 0) + hashArray.splice(i, 1); + + if (aValue) hashArray.push(aValue); + hashArray.sort(); + + location.replace(location.href.replace(/#.*$/, '') + (hashArray.length ? '#' + hashArray.join(',') : '' )); + }, + + get data(){ + var codes = document.getElementById('builtinCode'); + if (!this._data) { + // mozilla splits very long text node into multiple text nodes whose length is less than 4096 bytes. + // so, we must concat all the text nodes. + this.source.value = ""; + this.sourceData = []; + for (var i = 0; i < codes.childNodes.length; i++) { + this.source.value += codes.childNodes[i].nodeValue; + } + + this._data = this.source.value.split(/----+/); + this.initData(); + } + if (codes) + codes.parentNode.removeChild(codes); + + return this._data; + }, + set data(aValue){ + this._data = aValue.split(/----+/); + this.initData(); + return this._data; + }, + + initData : function() + { + var range = document.createRange(); + + range.selectNodeContents(this.list); + range.deleteContents(); + + + this.sourceData = []; + + + var regexp = [ + /^[\r\n\s]+|[\r\n\s]+$/g, + /(\r\n|[\r\n])/g + ]; + + var title; + var titleRegExp = /^(TITLE::)([^\n]*)\n?/im; + var header = ''; + var headerRegExp = /^(HEADER::)([^\n]*)\n?/im; + var footer = ''; + var footerRegExp = /^(FOOTER::)([^\n]*)\n?/im; + var chapter = ''; + var chapterRegExp = /^(CHAPTER::)([^\n]*)\n?/im; + var lastChapter; + var alignGlobal = 'center'; + var align; + var alignRegExp = /^((GLOBAL-)?ALIGN::)(left|right|center|start|end)?\n?/im; + var size; + var sizeGlobal = 9; + var sizeRegExp = /^((GLOBAL-)?SIZE::)(\d+(\.\d+)?)\n?/im; + + var imageMatchResults; + var imagesRegExp = this.makePhraseRegExp('%O%Oima?ge? +src="[^"]+" +width="[0-9]+" +height="[0-9]+"[^%C]*%C%C', 'gi'); + var imagesRegExp2 = this.makePhraseRegExp('%O%Oima?ge? +src="([^"]+)"', 'i'); + var image_src; + + var plainTextRegExp = this.makePhraseRegExp('(%O%O\#[^:]+:(.+)%C%C|%O%OEM:(.+)(:EM)?%C%C|%O%OPRE:(.+)(:PRE)?%C%C|%O%Oima?ge? +src="[^"]*"[^%C]+%C%C|%O%O([^\\|%C]+)(\\|[^%C]+)?%C%C|%O([^%O]+)%C)', 'gi'); + + var hiddenRegExp = /^(HIDDEN|IGNORE)::true\n?/im; + + var loadRegExp = /^LOAD::(.+)\n?/im; + var timerRegExp = /^SET-TIMER::(\d+)(.*)\n?/im; + + var dataObj; + var i, j, + max = this._data.length; + var menuContents = document.createDocumentFragment(); + var popup; + + var dataPath; + for (i = 0; i < max; i++) + { + image_src = null; + align = null; + size = null; + dataPath = ''; + + this._data[i] = this._data[i] + .replace(regexp[0], '') + .replace(regexp[1], '\n'); + + this.sourceData[i] = this._data[i]; + + if (loadRegExp.test(this._data[i])) { + this._data[i] = this._data[i].replace(loadRegExp, ''); + dataPath = RegExp.$1; + } + + if (timerRegExp.test(this._data[i])) { + this._data[i] = this._data[i].replace(timerRegExp, ''); + window.setTimeout(function(aSelf, aTime, aUnit) { + if (!aSelf.timerTimer) { + switch(aUnit) + { + case 's': + case 'sec': + case 'sec.': + case 'second': + case 'seconds': + aTime = aTime / 60; + break; + + case 'h': + case 'hour': + case 'hours': + aTime = aTime * 60; + break; + + default: + break; + } + aSelf.setTimer(aTime); + } + }, 100, this, parseInt(RegExp.$1), (RegExp.$2 || '').toLowerCase()); + } + + if (hiddenRegExp.test(this._data[i])) { + this._data.splice(i, 1); + max--; + i--; + continue; + } + + while (titleRegExp.test(this._data[i])) { + this._data[i] = this._data[i].replace(titleRegExp, ''); + if (String(RegExp.$1).toUpperCase() == 'TITLE::') + title = RegExp.$2 || '' ; + } + + while (headerRegExp.test(this._data[i])) { + this._data[i] = this._data[i].replace(headerRegExp, ''); + if (String(RegExp.$1).toUpperCase() == 'HEADER::') + header = RegExp.$2 || '' ; + } + + while (footerRegExp.test(this._data[i])) { + this._data[i] = this._data[i].replace(footerRegExp, ''); + if (String(RegExp.$1).toUpperCase() == 'FOOTER::') + footer = RegExp.$2 || '' ; + } + + while (chapterRegExp.test(this._data[i])) { + this._data[i] = this._data[i].replace(chapterRegExp, ''); + if (String(RegExp.$1).toUpperCase() == 'CHAPTER::') + chapter = RegExp.$2 || '' ; + } + + while (alignRegExp.test(this._data[i])) { + this._data[i] = this._data[i].replace(alignRegExp, ''); + + align = (RegExp.$3 || '').toLowerCase(); + if (align == 'left') + align = 'start'; + else if (align == 'right') + align = 'end'; + + if (String(RegExp.$1).toUpperCase() == 'GLOBAL-ALIGN::') { + alignGlobal = align; + align = null; + } + } + + while (sizeRegExp.test(this._data[i])) { + this._data[i] = this._data[i].replace(sizeRegExp, ''); + size = Math.max(0, Number(RegExp.$3 || this.baseSize)); + if (String(RegExp.$1).toUpperCase() == 'GLOBAL-SIZE::') { + sizeGlobal = size; + size = null; + } + } + + imageMatchResults = this._data[i].match(imagesRegExp); + if (imageMatchResults) { + for (j = imageMatchResults.length-1; j > -1; j--) + image_src = this.preloadImage(imageMatchResults[j].match(imagesRegExp2)[1]); + } + + this._data[i] = { + load : dataPath, + header : header, + footer : footer, + text : this._data[i].split('\n'), + image : image_src, + align : align || alignGlobal, + size : size || sizeGlobal + }; + this._data[i].plain = this._data[i].text + .join('\n') + .replace(plainTextRegExp, '$2$3$5$7$9') + .split('\n'); + if (title !== void(0)) + this._data[i].title = title; + + this._data[i].chapter = chapter || title || ''; + if (lastChapter === void(0) || + lastChapter != this._data[i].chapter) { + lastChapter = this._data[i].chapter; + + if (popup && popup.childNodes.length == 1) { + menuContents.removeChild(menuContents.lastChild); + menuContents.appendChild(popup.removeChild(popup.lastChild)); + } + + popup = document.createElement('menupopup'); + menuContents.appendChild(document.createElement('menu')); + menuContents.lastChild.setAttribute('label', this._data[i].chapter); + menuContents.lastChild.appendChild(popup); + } + + popup.appendChild(document.createElement('menuitem')); + popup.lastChild.setAttribute('type', 'radio'); + popup.lastChild.setAttribute('radiogroup', 'pages'); + popup.lastChild.setAttribute('label', (i+1)+': '+( + (this._data[i].plain.join('') || this._data[i].text.join(' ')).replace(/\s+/g, ' ') + )); + popup.lastChild.setAttribute('value', i); + +// if (image_src) { +// popup.lastChild.setAttribute('image', image_src); +// popup.lastChild.setAttribute('class', 'menuitem-iconic'); +// } + } + + if (menuContents.childNodes.length == 1) { + range.selectNodeContents(menuContents.firstChild.firstChild); + menuContents = range.extractContents(); + } + this.list.appendChild(menuContents); + + range.detach(); + + + this.shownMontaLabels = []; + }, + + get dataPath(){ + if (!this._dataPath) + this.dataPath = String(location.href).replace(/#.+$/, ''); + return this._dataPath; + }, + set dataPath(aValue){ + var oldDataPath = this._dataPath; + this._dataPath = aValue; + if (oldDataPath != aValue) { + this._dataFolder = this._dataPath.split('?')[0].replace(/[^\/]+$/, ''); + } + return this._dataPath; + }, + + get dataFolder(){ + if (!this._dataFolder) + this.dataPath = this.dataPath; + return this._dataFolder; + }, + set dataFolder(aValue){ + this._dataFolder = aValue; + return this._dataFolder; + }, + + loadData : function(aPath) + { + this.dataPath = aPath; + var request = new XMLHttpRequest(); + request.open('GET', aPath); + request.onload = function() { + Presentation.data = request.responseText; + Presentation.init(); + }; + request.send(null); + }, + + readParameter : function() { + if (location.search || location.hash) { + var param = location.search.replace(/^\?/, ''); + + if (location.hash.match(/page([0-9]+)/i) || + param.match(/page=([0-9]+)/i)) + this.offset = parseInt(RegExp.$1)-1; + + if (location.hash.match(/edit/i) || + param.match(/edit=(1|true|yes)/i)) { + window.setTimeout('Presentation.toggleEditMode();', 0); + } + + if (location.hash.match(/eva/i) || + param.match(/eva=(1|true|yes)/i)) + this.toggleEvaMode(); + + if (location.hash.match(/timer(\d+)\-(\d+)/i)) + this.setTimer(RegExp.$1, RegExp.$2); + + if (param.match(/(style|css)=([^&;]+)/i)) { + var style = unescape(RegExp.$2); + var pi = document.createProcessingInstruction('xml-stylesheet', 'href="'+style+'" type="text/css"'); + document.insertBefore(pi, document.documentElement); + } + + if (param.match(/data=([^&;]+)/i)) { + this.loadData(RegExp.$1); + return false; + } + } + return true; + }, + + preloadImage : function(aURI) + { + if (aURI in this.imageRequests) return; + + if (aURI.indexOf('http://') < 0 && + aURI.indexOf('https://') < 0) + aURI = this.dataFolder+aURI; + + this.imageRequests[aURI] = new XMLHttpRequest(); + try { + this.imageRequests[aURI].open('GET', aURI); + this.imageRequests[aURI].onload = function() { + Presentation.imageRequests[aURI] = null; + }; + this.imageRequests[aURI].send(null); + } + catch(e) { + this.imageRequests[aURI] = null; + } + return aURI; + }, + imageRequests : {}, + +/* commands */ + + reload : function() { + var file = String(location.href).replace(/#.+$/, ''); + if (this.dataPath != file) { + var path = this.dataPath; + var request = new XMLHttpRequest(); + request.open('GET', path); + request.onload = function() { + Presentation.data = request.responseText; + Presentation.init(); + + path = null; + request = null; + }; + request.send(null); + } + else + window.location.reload(); + }, + + forward : function(){ + if (!this.canForward) return; + this.offset++; + this.takahashi(); + }, + + forwardStep : function(){ + if (!this.canForward) return; + var monta = document.getElementsByAttribute('monta-hidden', 'true'); + if (monta && monta.length) { + this.showMontaKeyword(monta[0]); + } + else + this.forward(); + }, + + back : function(){ + if (!this.canBack) return; + this.offset--; + if(this.offset < 0){this.offset = 0} + this.takahashi(); + }, + + home : function(){ + if (!this.canMove) return; + this.offset = 0; + this.takahashi(); + }, + + end : function(){ + if (!this.canMove) return; + this.offset = this.data.length-1; + this.takahashi(); + }, + + showPage : function(aPageOffset){ + if (!this.canMove) return; + this.offset = aPageOffset ? aPageOffset : 0 ; + this.takahashi(); + }, + + toggleEditMode : function() + { + if (this.deck.selectedIndex == 1) { + if (document.getElementById('editTabBox').selectedTab.id == 'editTab-pages') { + this.source.value = this.sourceData.join('\n----\n'); + } + this.data = this.source.value; + this.cachedContents = []; + var range = document.createRange(); + range.selectNodeContents(this.content); + range.deleteContents(); + range.detach(); + this.init(); + } + else { + this.initEditPages(); + } + + this.deck.selectedIndex = this.deck.selectedIndex == 0 ? 1 : 0 ; + this.setHash('edit', this.deck.selectedIndex == 0 ? '' : 'edit' ); + }, + + toggleEvaMode : function() + { + var check = document.getElementById('toggleEva'); + if (this.canvas.getAttribute('eva') == 'true') { + this.canvas.removeAttribute('eva'); + this.logo.removeAttribute('eva'); + check.checked = false; + } + else { + this.canvas.setAttribute('eva', true); + this.logo.setAttribute('eva',true); + check.checked = true; + } + this.setHash('eva', check.checked ? 'eva' : '' ); + }, + +/* auto cruise */ + + toggleAutoCruiseMode : function() + { + var autoCruise = document.getElementById('autoButton'); + if(!autoCruise.checked) + this.startAutoCruise(); + else + autoCruise.checked = false; + }, + + startAutoCruise : function() + { + var autoCruise = document.getElementById('autoButton'); + autoCruise.checked = true; + + if (this.autoCruiseTimer) { + window.clearTimeout(this.autoCruiseTimer); + } + this.autoCruiseTimer = window.setTimeout(this.autoCruise, this.autoCruiseInterval); + }, + + changeAutoCruiseInterval : function(aInterval) + { + this.autoCruiseInterval = aInterval; + this.startAutoCruise(); + }, + + autoCruise : function() + { + var autoCruise = document.getElementById('autoButton'); + if (!autoCruise.checked) return; + + if (Presentation.offset == Presentation.data.length-1) { + if (Presentation.canMove) + Presentation.home(); + } + else { + if (Presentation.canForward) + Presentation.forwardStep(); + } + Presentation.autoCruiseTimer = window.setTimeout(arguments.callee, Presentation.autoCruiseInterval); + }, + autoCruiseTimer : null, + +/* timer */ + + resetTimer : function() + { + if (this.timerTimer) { + window.clearInterval(this.timerTimer); + this.timerTimer = null; + } + this.timer.setAttribute('value', 0); + this.timer.setAttribute('collapsed', true); + this.setHash('timer', ''); + }, + + setTimer : function(aStart, aEnd) + { + var now = (new Date()).getTime(); + if (aStart !== void(0) && aEnd === void(0)) { + var rest = Math.abs(aStart); + this.timerStart = now; + this.timerEnd = this.timerStart + (rest * 60000); + } + else if (aStart === void(0) && aEnd === void(0)) { + var rest = prompt('Remaining Time (minits)'); + if (rest == '') { + this.resetTimer(); + return; + } + else { + rest = Number(rest); + if (!rest || isNaN(rest)) return; + } + + rest = Math.abs(rest); + this.timerStart = now; + this.timerEnd = this.timerStart + (rest * 60000); + } + else { + aStart = Number(aStart); + aEnd = Number(aEnd); + if (isNaN(aStart) || isNaN(aEnd)) return; + + this.timerStart = Math.min(aStart, aEnd); + this.timerEnd = Math.max(aStart, aEnd); + + if (this.timerStart >= now || this.timerEnd <= now) return; + } + + this.resetTimer(); + + this.timer.removeAttribute('collapsed'); + this.setHash('timer', 'timer'+this.timerStart+'-'+this.timerEnd); + + if (now != this.timerStart) + this.updateTimer(this); + + this.timerTimer = window.setInterval(this.updateTimer, Math.min(this.timerUpdatingInterval, (this.timerEnd-this.timerStart)/(this.data.length*2)), this); + }, + + timerStart : 0, + timerEnd : 0, + timerTimer : null, + + updateTimer : function(aThis) + { + var now = (new Date()).getTime(); + if (now >= aThis.timerEnd) { + aThis.resetTimer(); + aThis.timer.setAttribute('value', 100); + aThis.timer.removeAttribute('collapsed'); + aThis.setHash('timer', ''); + } + else { + var value = parseInt(((now - aThis.timerStart) / (aThis.timerEnd - aThis.timerStart)) * 100); + aThis.timer.setAttribute('value', value); + } + }, + + updateTimerItem : function() + { + var item = document.getElementById('timerItem'); + if (this.timerTimer) { + item.setAttribute('label', item.getAttribute('label-active').replace(/%s/gi, Math.round((this.timerEnd - (new Date()).getTime()) / 60000))); + } + else { + item.setAttribute('label', item.getAttribute('label-normal')); + } + }, + +/* print */ + + print : function() + { + if (!this.canMove) { + alert('Please wait for a while, and retry later.'); + return; + } + + this.stopPrint(); + if (this.printWindow) { + this.printWindow.close(); + this.printWindow = null; + } + + if (!this.isToolbarHidden) + this.showHideToolbar(true); + + this.printWindow = window.open('output.htm', 'PresentationPrint', 'dependent=yes,hotkeys=yes,location=yes,menubar=yes,personalbar=yes,scrollbars=yes,status=yes,toolbar=yes'); + if (!this.printWindow) return; + + this.isPrinting = true; + + if (!this.printCanvas) + this.printCanvas = document.createElementNS(XHTMLNS, 'canvas'); + + this.printWindow.document.write('<html><head><title>'+document.title+'</title></head><body></body></html>'); + this.home(); + this.printTimer = window.setInterval(this.printCallback, 0, this); + }, + + printCallback : function(aThis) + { + if ( + !aThis.canMove + ) + return; + + var monta = document.getElementsByAttribute('monta-hidden', 'true'); + if (monta && monta.length) { + for (var i = monta.length-1; i > -1; i--) + aThis.showMontaKeyword(monta[i], true); + } + + var doc = aThis.printWindow.document; + var body = doc.getElementsByTagName('body')[0]; + var img = doc.createElement('img'); + + if ((aThis.offset+1) % 2 == 1) { + body.appendChild(doc.createElement('div')); +// body.lastChild.style.clear = 'both'; + } + var box = doc.createElement('div'); + box.appendChild(doc.createElement('div')); + box.lastChild.appendChild(document.createTextNode(aThis.offset+1)); + body.lastChild.appendChild(box); + + var w = window.innerWidth; + var h = window.innerHeight; + var canvasW = parseInt(w * aThis.printSize); + var canvasH = parseInt(h * aThis.printSize); + + aThis.printCanvas.width = canvasW; + aThis.printCanvas.height = canvasH; + aThis.printCanvas.style.border = 'black solid medium'; + + img.style.border = 'black solid medium'; + img.style.width = canvasW+'px'; + img.style.height = canvasH+'px'; + + box.style.margin = '1em'; + box.style.width = parseInt(w * aThis.printSize)+'px'; + box.style.cssFloat = ((aThis.offset+1) % 2 == 1) ? 'left' : 'right' ; + + try { + netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead'); + + var ctx = aThis.printCanvas.getContext('2d'); + ctx.clearRect(0, 0, canvasW, canvasH); + ctx.save(); + ctx.scale(aThis.printSize, aThis.printSize); + ctx.drawWindow(window, 0, 0, w, h, 'rgb(255,255,255)'); + ctx.restore(); + try { + if (aThis.imageType == 'jpeg') + img.src = aThis.printCanvas.toDataURL('image/jpeg', 'quality=50'); + else + img.src = aThis.printCanvas.toDataURL('image/png', 'transparency=none'); + + box.appendChild(img); + } + catch(e) { + box.appendChild(aThis.printCanvas.cloneNode(true)); + ctx = box.lastChild.getContext('2d'); + ctx.clearRect(0, 0, canvasW, canvasH); + ctx.save(); + ctx.scale(aThis.printSize, aThis.printSize); + ctx.drawWindow(window, 0, 0, w, h, 'rgb(255,255,255)'); + ctx.restore(); + } + } + catch(e) { + alert('Error: Failed to create a document for printing.\n\n------\n'+e); + aThis.stopPrint(); + return; + } + + if (aThis.offset == aThis.data.length-1) { + aThis.stopPrint(); + aThis.printWindow.focus(); + } + else { + aThis.forward(); + } + }, + + stopPrint : function() + { + window.clearInterval(this.printTimer); + this.printTimer = null; + this.isPrinting = false; + }, + + printSize : 0.4, + printTimer : null, + printWindow : null, + printCanvas : null, + +/* view source */ + + plainTextShown : false, + + get plainTextBox() + { + return document.getElementById('plainTextBox'); + }, + + get plainTextField() + { + return document.getElementById('plainTextField'); + }, + + showPlainText : function() + { + if (this.plainTextShown) return; + this.plainTextShown = true; + this.plainTextBox.removeAttribute('hidden'); + this.plainTextField.style.width = parseInt(this.canvas.boxObject.width * 0.8)+'px'; + this.plainTextField.style.height = parseInt(this.canvas.boxObject.height * 0.8)+'px'; + this.plainTextField.value = this.data[this.offset].text.join('\n').replace(/\u200b/g, ''); + this.plainTextField.select(); + this.plainTextField.focus(); + }, + + hidePlainText : function() + { + if (!this.plainTextShown) return; + this.plainTextShown = false; + this.plainTextBox.setAttribute('hidden', true); + this.plainTextField.value = ''; + this.plainTextField.blur(); + }, + +/* state */ + + get canMove() + { + return ( + this.isRendering || + importNodeTreeWithDelayTimers || + this.montaAnimating + ) ? false : true ; + }, + + get canBack() + { + return this.canMove; + }, + + get canForward() + { + return this.canMove; + }, + + get isPresentationMode(){ + return (this.deck.selectedIndex == 0); + }, + +/* event handling */ + + handleEvent : function(aEvent) + { + if (this.isPrinting) return; + + var node = aEvent.target; + var inRawContents = false; + do { + if (node.nodeType == Node.ELEMENT_NODE && + /\braw\b/i.test(node.getAttribute('class'))) { + inRawContents = true; + break; + } + + node = node.parentNode; + } + while (node.parentNode) + + + switch (aEvent.type) + { + default: + break; + + case 'resize': + this.takahashi(); // redrwa + break; + + case 'contextmenu': + aEvent.stopPropagation(); + aEvent.preventCapture(); + aEvent.preventDefault(); + aEvent.preventBubble(); + break; + + + case 'mouseup': + if (inRawContents) return; + this.dragStartX = -1; + this.dragStartY = -1; + if (this.indicatorBar.dragging) + this.onIndicatorBarDragEnd(aEvent); + break; + + case 'mousedown': + if (inRawContents) return; + if (this.dragStartX < 0) { + this.dragStartX = aEvent.clientX; + this.dragStartY = aEvent.clientY; + } + var box = this.indicatorBar.boxObject; + if (!(aEvent.screenX < box.screenX || + aEvent.screenY < box.screenY || + aEvent.screenX > box.screenX+box.width || + aEvent.screenY > box.screenY+box.height)) + this.onIndicatorBarDragStart(); + break; + + case 'mousemove': + if (inRawContents) return; + this.checkShowHideToolbar(aEvent); + if (this.indicatorBar.dragging) { + this.onIndicatorBarDragMove(aEvent); + return; + } + if (this.dragStartX > -1) { + if (Math.abs(this.dragStartX-aEvent.clientX) > Math.abs(this.dragStartDelta) || + Math.abs(this.dragStartY-aEvent.clientY) > Math.abs(this.dragStartDelta)) { + var event = document.createEvent('Events'); + event.initEvent('StartDragOnCanvas', false, true); + this.canvas.dispatchEvent(event); + } + } + break; + + case 'CanvasContentAdded': + if (this.fitToCanvasTimer) { + window.clearTimeout(this.fitToCanvasTimer); + this.fitToCanvasTimer = null; + } + this.fitToCanvasTimer = window.setTimeout('Presentation.fitMainContentToCanvas()', 100); + break; + + case 'DOMMouseScroll': + if ( + (aEvent.detail > 0 && this.scrollCounter < 0) || + (aEvent.detail < 0 && this.scrollCounter > 0) + ) + this.scrollCounter = 0; + + this.scrollCounter += aEvent.detail; + if (Math.abs(this.scrollCounter) >= this.scrollThreshold) { + if (aEvent.detail > 0) + Presentation.forwardStep(); + else + Presentation.back(); + + this.scrollCounter = 0; + } + break; + } + }, + + dragStartX : -1, + dragStartY : -1, + scrollCounter : 0, + scrollThreshold : 10, + + onKeyPress : function(aEvent) { + if (this.isPrinting) return; + + switch(aEvent.keyCode) + { + case aEvent.DOM_VK_BACK_SPACE: + if (this.isPresentationMode) { + aEvent.preventBubble(); + aEvent.preventDefault(); + Presentation.back(); + } + break; + default: + break; + } + }, + +/* actions on presentation */ + + onPresentationClick : function(aEvent) + { + if (this.isPrinting) { + if (confirm('Do you want printing operation to be stopped?')) { + this.stopPrint(); + } + return; + } + + if (!this.isToolbarHidden) + this.showHideToolbar(); + + switch(aEvent.button) + { + case 0: + switch (aEvent.target.getAttribute('class')) + { + case 'link-text': + var uri = aEvent.target.getAttribute('href'); + if (uri) { + window.open(uri); + return; + } + break; + + case 'monta-label': + if (aEvent.target.getAttribute('monta-hidden') == 'true') { + this.showMontaKeyword(aEvent.target); + aEvent.preventBubble(); + return; + } + + default: + break; + } + this.forward(); + document.documentElement.focus(); + break; + case 2: + this.back(); + document.documentElement.focus(); + break; + default: + break; + } + }, + +/* scrollbar */ + + onScrollerDragStart : function(){ + if (this.isPrinting) return; + + this.scroller.dragging = true; + }, + + onScrollerDragMove : function(){ + if (this.isPrinting) return; + + if (this.scroller.dragging) + this.showPage(parseInt(this.scroller.getAttribute('curpos'))); + }, + + onScrollerDragDrop : function(){ + if (this.isPrinting) return; + + this.onScrollerDragMove(); + this.scroller.dragging = false; + }, + +/* indicator bar */ + + onIndicatorBarClick : function(aEvent) + { + if (this.isPrinting) return; + + var bar = this.indicatorBar; + this.showPage(Math.round((aEvent.screenX - bar.boxObject.screenX) / bar.boxObject.width * this.data.length)); + }, + + onIndicatorBarDragStart : function() + { + if (this.isPrinting) return; + + this.indicatorBar.dragging = true; + }, + + onIndicatorBarDragMove : function(aEvent) + { + if (this.isPrinting) return; + + var bar = this.indicatorBar; + this.showPage(Math.round((aEvent.screenX - bar.boxObject.screenX) / bar.boxObject.width * this.data.length)); + }, + + onIndicatorBarDragEnd : function(aEvent) + { + if (this.isPrinting) return; + + this.onIndicatorBarDragMove(aEvent); + this.indicatorBar.dragging = false; + }, + + showMontaKeyword : function(aNode, aWithoutAnimation) { + if (aNode.getAttribute('monta-hidden') != 'true') return; + + if (aWithoutAnimation) { + aNode.setAttribute('monta-hidden', 'false'); + return; + } + + aNode.setAttribute('monta-hidden', 'progress'); + + this.montaAnimating = true; + + window.setTimeout(this.showMontaKeywordCallback, 0, { + position : -100, + node : aNode, + interval : this.showMontaKeywordTimeout/10 + }); + }, + + showMontaKeywordCallback : function(aInfo) { + if (aInfo.position >= aInfo.node.boxObject.width) { + aInfo.node.setAttribute('monta-hidden', 'false'); + Presentation.montaAnimating = false; + return; + } + + aInfo.position += (aInfo.node.boxObject.width/10); + aInfo.node.setAttribute('style', 'background-position: '+aInfo.position+'px 0 !important;'); + window.setTimeout(arguments.callee, aInfo.interval, aInfo); + }, + montaAnimating : false, + +/* toolbar animation */ + + onToolbarArea : false, + toolbarHeight : 0, + toolbarDelay : 300, + toolbarTimer : null, + isToolbarHidden : false, + + checkShowHideToolbar : function(aEvent) { + if (!this.scroller || this.scroller.dragging || this.preventToShowHideToolbar) return; + + this.onToolbarArea = (aEvent.clientY < this.toolbarHeight); + + if (this.isToolbarHidden == this.onToolbarArea) { + if (this.toolbarTimer) window.clearTimeout(this.toolbarTimer); + this.toolbarTimer = window.setTimeout('Presentation.checkShowHideToolbarCallback()', this.toolbarDelay); + } + }, + + checkShowHideToolbarCallback : function() { + if (this.isToolbarHidden == this.onToolbarArea) + this.showHideToolbar(); + }, + + showHideToolbar : function(aWithoutAnimation) + { + if (this.isPrinting) return; + + if (this.toolbarAnimationTimer) window.clearTimeout(this.toolbarAnimationTimer); + + this.toolbarAnimationInfo = { count : 0 }; + if (this.isToolbarHidden) { + this.toolbarAnimationInfo.start = 0; + this.toolbarAnimationInfo.end = this.toolbarHeight; + } + else { + this.toolbarAnimationInfo.start = this.toolbarHeight; + this.toolbarAnimationInfo.end = 0; + } + this.toolbarAnimationInfo.current = 0; + + this.toolbar.setAttribute('style', 'margin-top:'+(0-(this.toolbarHeight-this.toolbarAnimationInfo.start))+'px; margin-bottom:'+(0-this.toolbarAnimationInfo.start)+'px;'); + + if (aWithoutAnimation) { + this.toolbarAnimationInfo.current = this.toolbarHeight; + Presentation.animateToolbar(); + } + else { + this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps); + } + }, + + animateToolbar : function() + { + this.toolbarAnimationInfo.current += parseInt(this.toolbarHeight/this.toolbarAnimationSteps); + + var top, bottom; + if (this.toolbarAnimationInfo.start < this.toolbarAnimationInfo.end) { + top = this.toolbarHeight-this.toolbarAnimationInfo.current; + bottom = this.toolbarAnimationInfo.current; + } + else { + top = this.toolbarAnimationInfo.current; + bottom = this.toolbarHeight-this.toolbarAnimationInfo.current; + } + + top = Math.min(Math.max(top, 0), this.toolbarHeight); + bottom = Math.min(Math.max(bottom, 0), this.toolbarHeight); + + this.toolbar.setAttribute('style', 'margin-top:'+(0-top)+'px; margin-bottom:'+(0-bottom)+'px'); + + if (this.toolbarAnimationInfo.count < this.toolbarAnimationSteps) { + this.toolbarAnimationInfo.count++; + this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps); + } + else + this.isToolbarHidden = !this.isToolbarHidden; + }, + + toolbarAnimationDelay : 100, + toolbarAnimationSteps : 5, + toolbarAnimationInfo : null, + toolbarAnimationTimer : null, + +/* edit mode */ + + initEditPages : function() + { + var range = document.createRange(); + range.selectNodeContents(this.pages); + range.deleteContents(); + range.detach(); + + var editBox = document.getElementById('pageEditBoxTemplate'); + var contents = document.createDocumentFragment(); + for (var i = 0, maxi = this.sourceData.length; i < maxi; i++) + { + var newBox = editBox.cloneNode(true); + newBox.firstChild.setAttribute('value', this.sourceData[i]) + newBox.setAttribute('id', this.EDIT_BOX_ID_PREFIX+i); + contents.appendChild(newBox); + } + + this.pages.appendChild(contents); + }, + + toggleEditStyle : function(aEvent) + { + var tabbox = document.getElementById('editTabBox'); + var tab = tabbox.selectedTab; + if (tab.id == 'editTab-pages') { + this.sourceData = this.source.value.split(/\n?----+\n?/); + this.initEditPages(); + } + else { + this.source.value = this.sourceData.join('\n----\n'); + } + }, + + insert : function(aType) { + switch (aType) + { + case 'page': + this.insertTextFor('\n----\n', this.source, 6); + break; + case 'header': + this.insertTextFor('\nHEADER::\n', this.source, 9); + break; + case 'footer': + this.insertTextFor('\nFOOTER::\n', this.source, 9); + break; + + case 'em': + case 'emphasis': + this.insertTextFor(this.phraseOpenParen+this.phraseOpenParen+'EM:'+this.phraseCloseParen+this.phraseCloseParen, this.source, 5); + break; + case 'pre': + case 'preformatted': + this.insertTextFor(this.phraseOpenParen+this.phraseOpenParen+'PRE:'+this.phraseCloseParen+this.phraseCloseParen, this.source, 6); + break; + case 'monta': + this.insertTextFor(this.phraseOpenParen+this.phraseCloseParen, this.source, 1); + break; + case 'link': + this.insertTextFor(this.phraseOpenParen+this.phraseOpenParen+'|http://'+this.phraseCloseParen+this.phraseCloseParen, this.source, 2); + break; + case 'img': + case 'image': + this.insertTextFor(this.phraseOpenParen+this.phraseOpenParen+'image src="" width="" height=""'+this.phraseCloseParen+this.phraseCloseParen, this.source, 13); + break; + + default: + return; + } + this.onEditSource(); + }, + + insertTextFor : function(aString, aNode, aPosOffset) + { + var pos = aNode.selectionStart; + var value = aNode.value; + aNode.value = [value.substring(0, pos), aString, value.substring(pos, value.length)].join(''); + aNode.selectionEnd = aNode.selectionStart = pos + (aPosOffset || 0); + }, + + removePage : function(aPage) + { + if (aPage === void(0) || this.pages.childNodes.length == 1) return; + + var target = document.getElementById(this.EDIT_BOX_ID_PREFIX+aPage); + + var next = target; + while (next = next.nextSibling) + { + next.setAttribute('id', this.EDIT_BOX_ID_PREFIX + (Number(next.id.match(/\d+/)) - 1)); + } + this.pages.removeChild(target); + + this.sourceData.splice(aPage, 1); + + var maxPage = this.pages.childNodes.length-1; + if (this.offset > maxPage) this.offset = maxPage; + + this.onEditPage(); + }, + + onEditSource : function() { + if (this.isPrinting) return; + }, + + + onEditPage : function(aPage) + { + if (aPage !== void(0)) { + var target = document.getElementById(this.EDIT_BOX_ID_PREFIX+aPage); + if (target) { + target = getNodesByXPath('descendant::*[@class="page-edit-box-main"]', target).snapshotItem(0); + this.sourceData[aPage] = target.value; + } + } + }, + + output : function() + { + location.href = 'data:application/octet-stream,'+encodeURIComponent(this.source.value); + } + +}; + +var StrokeService = { + + className : 'stroke-dot', + dragStartDelta : 10, + lineColor : 'red', + lineWidth : 3, + + initialized : false, + + + mode : null, + canvas : null, + canvasContext : null, + startX : -1, + startY : -1, + + init : function(aCanvas) + { + this.initialized = true; + + this.canvas = aCanvas; + this.canvasElement = aCanvas; + + var canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas'); + canvas.width = this.canvas.boxObject.width; + canvas.height = this.canvas.boxObject.height; + this.canvas.appendChild(canvas); + if (!('getContext' in canvas) || !canvas.getContext) { + this.canvas.removeChild(canvas); + this.mode = 'box'; + } + else { + this.canvasElement = canvas; + this.canvasContext = canvas.getContext('2d'); + this.mode = 'canvas'; + } + + document.documentElement.addEventListener('PresentationRedraw', this, false); + window.addEventListener('resize', this, false); + this.canvasElement.addEventListener('mouseup', this, false); + this.canvasElement.addEventListener('mousedown', this, false); + this.canvasElement.addEventListener('mousemove', this, false); + + this.canvasElement.addEventListener('click', this, false); + this.canvasElement.addEventListener('dblclick', this, false); + + this.clear(); + }, + + destroy : function() + { + document.documentElement.removeEventListener('PresentationRedraw', this, false); + window.removeEventListener('resize', this, false); + if (this.canvasElement) { + this.canvasElement.removeEventListener('mouseup', this, false); + this.canvasElement.removeEventListener('mousedown', this, false); + this.canvasElement.removeEventListener('mousemove', this, false); + this.canvasElement.removeEventListener('click', this, false); + } + + this.cliclableNodesManager = null; + this.canvasElement = null; + this.canvas = null; + + this.initialized = false; + }, + + handleEvent : function(aEvent) + { + switch(aEvent.type) + { + default: + break; + + case 'mouseup': + this.finish(aEvent); + this.startX = -1; + this.startY = -1; + window.setTimeout('StrokeService.preventToSendClickEvent = false', 10); + break; + + case 'mousedown': + if (this.startX < 0) { + this.startX = aEvent.clientX; + this.startY = aEvent.clientY; + } + break; + + case 'mousemove': + if (this.startX > -1 && !this.active) { + if (Math.abs(this.startX-aEvent.clientX) > Math.abs(this.dragStartDelta) || + Math.abs(this.startY-aEvent.clientY) > Math.abs(this.dragStartDelta)) { + this.start(aEvent, this.startX, this.startY); + this.preventToSendClickEvent = true; + } + } + else + this.trace(aEvent); + + break; + + case 'PresentationRedraw': + case 'resize': + this.clear(); + break; + + case 'click': + if (this.preventToSendClickEvent) { + aEvent.stopPropagation(); + aEvent.preventCapture(); + aEvent.preventDefault(); + aEvent.preventBubble(); + this.preventToSendClickEvent = false; + } + else if (this.cliclableNodesManager && this.cliclableNodesManager.clickableNodes) { + var nodes = this.cliclableNodesManager.clickableNodes; + var max = nodes.length; + var x, y, width, height + for (var i = 0; i < max; i++) + { + if (nodes[i].boxObject) { + x = nodes[i].boxObject.x; + y = nodes[i].boxObject.y; + width = nodes[i].boxObject.width; + height = nodes[i].boxObject.height; + } + else { + x = nodes[i].offsetLeft; + y = nodes[i].offsetTop; + width = nodes[i].offsetWidth; + height = nodes[i].offsetHeight; + } + if (aEvent.clientX < x || + aEvent.clientX > x+width || + aEvent.clientY < y || + aEvent.clientY > y+height) + continue; + + var event = document.createEvent('MouseEvents'); + event.initMouseEvent( + aEvent.type, aEvent.canBubble, aEvent.cancelable, aEvent.view, + aEvent.detail, + aEvent.screenX, aEvent.screenY, aEvent.clientX, aEvent.clientY, + aEvent.ctrlKey, aEvent.altKey, aEvent.shiftKey, aEvent.metaKey, + aEvent.button, + aEvent.relatedTarget + ); + nodes[i].dispatchEvent(event); + break; + } + } + break; + } + }, + preventToSendClickEvent : false, + + start : function(aEvent, aX, aY) + { + this.active = true; + this.trace(aEvent, aX, aY); + }, + + finish : function(aEvent) + { + if (!this.active) return; + this.trace(aEvent); + this.finishStroke(); + }, + + trace : function(aEvent, aX, aY) + { + if (!this.active) return; + this.addPoint((aX === void(0) ? aEvent.clientX : aX ), (aY === void(0) ? aEvent.clientY : aY )); + }, + + finishStroke : function() + { + this.active = false; + this.lastX = -1; + this.lastY = -1; + }, + + addPoint : function(aX, aY) + { + if (this.lastX != -1) + this.drawLine(this.lastX, this.lastY, aX, aY); + else + this.drawDot(aX, aY); + + this.lastX = aX; + this.lastY = aY; + }, + + clear : function() + { + this.active = false; + this.lastX = -1; + this.lastY = -1; + + if (this.mode == 'canvas') { + if (this.canvasElement.lastWindowWidth != window.innerWidth || + this.canvasElement.lastWindowHeight != window.innerHeight) { + this.canvasElement.width = this.canvasElement.parentNode.boxObject.width-2; + this.canvasElement.height = this.canvasElement.parentNode.boxObject.height-2; + + this.canvasElement.lastWindowWidth = window.innerWidth; + this.canvasElement.lastWindowHeight = window.innerHeight; + } + this.canvasContext.clearRect(0, 0, this.canvasElement.width, this.canvasElement.height); + this.canvasContext.strokeStyle = this.lineColor; + this.canvasContext.lineWidth = this.lineWidth; + } + else { + var dotes = this.canvasElement.getElementsByAttribute('class', this.className); + if (!dotes.length) return; + + var range = document.createRange(); + range.selectNodeContents(this.canvasElement); + range.setStartBefore(dotes[0]); + range.setEndAfter(dotes[dotes.length-1]); + range.deleteContents(); + range.detach(); + } + }, + + drawDot : function(aX, aY, aParent) + { + if (this.mode == 'canvas') { + this.canvasContext.strokeRect(aX, aY, 0, 0); + this.canvasContext.stroke(); + } + else { + var dot = document.createElement('spacer'); + dot.setAttribute('style', 'left:'+aX+'px; top:'+aY+'px'); + dot.setAttribute('class', this.className); + (aParent || this.canvasElement).appendChild(dot); + } + }, + + drawLine : function(aX1, aY1, aX2, aY2) + { + if (aX1 == aX2 && aY1 == aY2) return; + + + if (this.mode == 'canvas') { + this.canvasContext.beginPath(); + this.canvasContext.moveTo(aX1, aY1); + this.canvasContext.lineTo(aX2, aY2); +/* + this.canvasContext.bezierCurveTo( + parseInt(aX1+((aX2-this.lastX)*0.3)), parseInt(aY1+((aY2-this.lastY)*0.3)), + parseInt(aX1+((aX2-this.lastX)*0.6)), parseInt(aY1+((aY2-this.lastY)*0.6)), + aX2, aY2 + ); +*/ + this.canvasContext.closePath(); + this.canvasContext.stroke(); + } + else { + var x_move = aX2 - aX1; + var y_move = aY2 - aY1; + var x_diff = x_move < 0 ? 1 : -1; + var y_diff = y_move < 0 ? 1 : -1; + + var fragment = document.createDocumentFragment(); + if (Math.abs(x_move) >= Math.abs(y_move)) { + for (var i = x_move; i != 0; i += x_diff) + this.drawDot(aX2 - i, aY2 - Math.round(y_move * i / x_move), fragment); + } + else { + for (var i = y_move; i != 0; i += y_diff) + this.drawDot(aX2 - Math.round(x_move * i / y_move), aY2 - i, fragment); + } + this.canvasElement.appendChild(fragment); + } + } + +}; + +var StrokablePresentationService = { + + id : 'stroke-canvas-box', + + strokeService : null, + cliclableNodesManager : null, + canvasContainer : null, + canvas : null, + + autoStart : false, + + init : function(aPresentation, aStrokeService) + { + this.cliclableNodesManager = aPresentation; + this.strokeService = aStrokeService; + this.canvasContainer = document.getElementById('canvas').firstChild; + this.check = document.getElementById('penButton'); + + document.documentElement.addEventListener('StartDragOnCanvas', this, false); + document.documentElement.addEventListener('PresentationRedraw', this, false); + }, + + toggle : function(aEnable) + { + if (aEnable) + this.start(); + else + this.end(); + }, + + start : function() + { + if (!this.strokeService || !this.canvasContainer) return; + + this.strokeService.cliclableNodesManager = this.cliclableNodesManager; + var box = document.createElement('vbox'); + box.setAttribute('flex', 1); + box.setAttribute('id', this.id); + box.style.width = this.canvasContainer.boxObject.width+'px'; + box.style.height = this.canvasContainer.boxObject.height+'px'; + this.canvas = this.canvasContainer.appendChild(box); + this.strokeService.init(this.canvas); + + this.canvas.addEventListener('dblclick', this, false); + }, + + end : function() + { + this.strokeService.destroy(); + if (this.canvas) { + this.canvas.removeEventListener('dblclick', this, false); + this.canvasContainer.removeChild(this.canvas); + this.canvas = null; + } + }, + + handleEvent : function(aEvent) + { + switch (aEvent.type) + { + default: + break; + + case 'StartDragOnCanvas': + if (!this.check.checked) { + this.toggleCheck(); + this.strokeService.startX = Presentation.dragStartX; + this.strokeService.startY = Presentation.dragStartY; + + this.autoStart = true; + } + break; + + case 'PresentationRedraw': + if (this.autoStart && this.check.checked) { + this.autoStart = false; + this.toggleCheck(); + } + break; + + case 'dblclick': + if (this.canvas) + this.end(); + break; + } + }, + + toggleCheck : function() + { + var enable = !this.check.checked; + this.toggle(enable); + this.check.checked = enable; + + this.autoStart = false; + } + +}; + +function init() +{ + window.removeEventListener('load', init, false); + + Presentation.init(); + StrokablePresentationService.init(Presentation, StrokeService); +} +window.addEventListener('load', init, false); + +function getNodesByXPath(aExpression, aContext, aLive) +{ + var d = aContext.ownerDocument || aContext; + var type = aLive ? XPathResult.ORDERED_NODE_ITERATOR_TYPE : XPathResult.ORDERED_NODE_SNAPSHOT_TYPE ; + var nodes; + try { + nodes = d.evaluate(aExpression, aContext, null, type, null); + } + catch(e) { + nodes = document.evaluate(aExpression, aContext, null, type, null); + } + return nodes; +} + +// Import Node from E4X to DOM +// http://ecmanaut.blogspot.com/2006/03/e4x-and-dom.html + +function importE4XNode( e4x, doc, aDefaultNS ) +{ + aDefaultNS = aDefaultNS || XHTMLNS; + var root, domTree, importMe; + this.Const = this.Const || { mimeType: 'text/xml' }; + this.Static = this.Static || {}; + this.Static.parser = this.Static.parser || new DOMParser; + eval('root = <testing xmlns="'+aDefaultNS+'" />;'); + root.test = e4x; + domTree = this.Static.parser.parseFromString( root.toXMLString(), + this.Const.mimeType ); + importMe = domTree.documentElement.firstChild; + while( importMe && importMe.nodeType != 1 ) + importMe = importMe.nextSibling; + if( !doc ) doc = document; + return importMe ? doc.importNode( importMe, true ) : null; +} + +function appendE4XTo( e4x, node, doc, aDefaultNS ) +{ + return node.appendChild( importE4XNode( e4x, (doc || node.ownerDocument), aDefaultNS ) ); +} + +function setE4XContent( e4x, node, aDefaultNS ) +{ + while( node.firstChild ) + node.removeChild( node.firstChild ); + appendE4XTo( e4x, node, aDefaultNS ); +} + +// importE4XNodeã§å¾ããã¼ãããªã¼ãåãè¾¼ãã¨ãXULã§ãã¤ã³ãã£ã³ã°ãé©ç¨ãããªããã¨ãããã +// é å»¶å¦çã§ãã®åé¡ãä¸é¨é¿ãããã¨ãã§ããï¼ããããã§ãã¾ã ãã¡ãªå ´åããããmenuã¨ããï¼ +// ã¨ããããXULã¨SVGã¨XHTMLã¯ããããMathMLã¯ãã¡ã ã£ãã +function importNodeTreeWithDelay(aNode, aParent, aDefaultNS, aFromTimeout) +{ + if (aFromTimeout) { + importNodeTreeWithDelayTimers--; + } + + var node; + var delay = 1; + switch (aNode.nodeType) + { + case Node.ELEMENT_NODE: + var ns = (aNode.namespaceURI || aDefaultNS); + node = document.createElementNS(ns, aNode.localName); + aParent.appendChild(node); + + var attr = aNode.attributes; + for (var i = 0, maxi = attr.length; i < maxi; i++) + node.setAttribute(attr[i].name, attr[i].value); + + if (ns == XULNS) delay = 1; else delay = 0; + + var children = aNode.childNodes; + for (var i = 0, maxi = children.length; i < maxi; i++) + if (delay) { + importNodeTreeWithDelayTimers++; + window.setTimeout(importNodeTreeWithDelay, delay, children[i], node, aDefaultNS, true); + } + else + importNodeTreeWithDelay(children[i], node, aDefaultNS); + break; + + default: + if ( + aNode.nodeType == Node.TEXT_NODE && + /^\s*$/.test(aNode.nodeValue) && + (aNode.parentNode.namespaceURI || aDefaultNS) != XHTMLNS + ) + return; + node = aParent.appendChild(aNode.cloneNode(true)); + break; + } + + var event = document.createEvent('Events'); + event.initEvent('CanvasContentAdded', true, true); + node.dispatchEvent(event); + + return node; +} +var importNodeTreeWithDelayTimers = 0; + +]]></script> + +</page> + diff --git a/object_meta_programming_slides/.Spork.slides.swp b/object_meta_programming_slides/.Spork.slides.swp new file mode 100644 index 0000000..ff24fdb Binary files /dev/null and b/object_meta_programming_slides/.Spork.slides.swp differ diff --git a/object_meta_programming_slides/Spork.slides b/object_meta_programming_slides/Spork.slides new file mode 100644 index 0000000..ddb86b2 --- /dev/null +++ b/object_meta_programming_slides/Spork.slides @@ -0,0 +1,546 @@ +---- +presentation_topic: meta meta meta meta +presentation_title: Object Meta Programming +presentation_place: YAPC::EU::2007 +presentation_date: Aug 29, 2007 +---- += HAI FRENDS +{image:http://personal.inet.fi/taide/junttila/desert/2002/promopi.jpg} +== My name is Yuval +---- += Meta Programming +{image: http://www.prints.co.nz/Merchant2/graphics/00000001/7104_Squares_with_Concentric_Circles_Kandinsky_Wassily.jpg} +---- += Introduction +{image: http://www.room101.net/door.jpg} ++* Meta programming ++* writing /code/ which /outputs/ or /manipulates/ /code/ +---- += Many forms +{image: http://www.internationalhero.co.uk/m/manimal.jpg} ++* string `eval` ++* `%::` ++* closure generators ++* macros ++* real macros ++* compilers +---- += Many forms +{image: http://www.junjan.org/weblog/images/Flying_Spaghetti_Monster-thumb.jpg} ++* Home grown snippets ++* Home grown packages ++* Stuff on the CPAN (e.g. `Class::Accessor`, `Code::Perl`) ++* Large systems (`Template::Toolkit`) +---- += Summary +{image: http://www.evc.org/programs/TD_web_projects/westside_amy_2003_1/teen_times/peerpressure/images/16_peer_pressure_smoking.gif} +* You should already know it +* You probably do it ++* That's the intended audience anyway ;-) +---- += Object Meta Programming +---- += Object Meta Programming ++* Code that outputs or manipulates /object oriented code/ ++* Often written in OO +---- += Simple Examples +{image: http://www.wildoats.com/content/ApplePieSlice.jpg} ++* `Class::Accessor`, `Class::InsideOut` ++** Generates accessor methods ++* `Class::Prototyped` ++** Prototype object support in Perl ++* Lots of stuff on the CPAN +---- += Modeling OO +{image: http://www.nordicsubs.co.uk/covers/vogue.jpg} ++* High level object meta programming ++** The current trend ++** The picture illustrates an object modelling with class =) ++** Seriously though... +---- += Modeling OO +{image: http://www.nordicsubs.co.uk/covers/vogue.jpg} +* High level object meta programming +* What is a class? ++.vim +filetype: perl6 + + class Class { + has @isa; + has %methods; + has %attributes; + + ... + } +.vim +---- += Modeling OO +{image: http://www.nordicsubs.co.uk/covers/vogue.jpg} ++* Implementing OO ++** In OO ++* Meta objects: ++** Class ++** Method ++** Attribute +---- += Example class + +.vim +filetype: perl6 + + class Point { + has $x; + has $y; + + method distance_to { ... } + } +.vim +---- += Modeled with objects + +.vim +filetype: perl + + Class->new( + attributes => [ + Attribute->new( name => '$x' ), + Attribute->new( name => '$y' ), + ], + methods => [ + Method->new( + name => "distance_to", + definition => sub { ... } + ), + ], + ); +.vim +---- += Metamodel Services +{image: http://www1.istockphoto.com/file_thumbview_approve/944779/2/istockphoto_944779_reception_bell.jpg} ++* Form ++** Introspection/Reflection ++* Function ++** Class generation ++** Class transformation ++* Pattern packaging +---- += Case Study +{image: http://www.iinteractive.com/moose/images/a_moose.gif} +== Moose ++* A deep meta object system ++* 4 layers deep ++** Syntactic sugar ++** Custom metaclasses ++** Class::MOP ++** Perl's native OO +---- += Perl's native OO +{image: http://www.mileslight.com/images/perl-camel.gif} ++* Minimalistic ++** Class = Package = Symbol table hash +** Inheritence tree embedded in `@ISA` entry +** `bless` links data to a class +** `->` ++* Insanely flexible ++* Pretty klunky ++* Written in C (not very accessible) +---- += Class::MOP +{image: http://nothingmuch.woobling.org/MOP.jpg} ++* port of CLOS, more or less ++* MOP = Meta Object Protocol +---- += Class::MOP +{image: http://nothingmuch.woobling.org/MOP.jpg} ++* Model ++** `Class::MOP::Class` +** `Class::MOP::Method` +** `Class::MOP::Attribute` ++* Easy interface ++** Introspection ++** Transformation +---- += Class::MOP +{image: http://nothingmuch.woobling.org/MOP.jpg} ++* Can "parse" packages into meta objects ++* Modifying the objects writes back to packages ++* Code generation ++** Accessors from attributes ++** Constructor from attributes ++** Method modifiers +---- += Moose's custom metaclasses +{image: http://www.iinteractive.com/moose/images/a_moose.gif} ++* Subclasses of `Class::MOP::Class` et al ++* More fun features ++** Roles ++** `BUILD` etc a la Perl 6 ++* Type constraints +---- += Moose sugar layer +{image: http://nothingmuch.woobling.org/sugar.jpg} ++* Pseudo-declarative syntax ++* Maps to metaclass manipulations ++.vim + has foo => ( is => "rw" ); +.vim ++* becomes ++.vim + $metaclass->add_attribute( + Moose::Meta::Attribute->new( + foo => ( is => "rw" ), + ) + ); +.vim +---- += Moose vs. Class::Accessor +{image: http://nothingmuch.woobling.org/p-seal-at-toronto-zoo.jpg} ++* All that bloat just for the `has` syntax? ++* *NO!* ++* Pattern packaging +---- += MooseX:: +{image: http://www.threadpit.com/photos/all_styles/small/401.jpg} ++* Packaged meta code ++* Pretty clean ++* Mostly composable +---- += MooseX:: +{image: http://www.threadpit.com/photos/all_styles/small/401.jpg} ++* `MooseX::Storage` ++** Customizable serialization through metaprogramming ++* `MooseX::AttributeHelpers` ++** Additional methods for collection type attributes ++* `MooseX::Getopt` ++** Additional constructor compiles attributes into a `Getopt` spec ++* `MooseX::IOC` ++** Inversion of control integrated into the object system +---- += The point of Moose +{image: http://nothingmuch.woobling.org/cute_moose.jpg} ++* OO is less tedious ++* Helps you write meta code ++** Good APIs promote clean code ++** Easier to build on existing base ++** Conventions and structure let you play well with others (`MooseX::`) ++** Introspectable & tranformable metamodel +---- += Another Case Study +{image: http://www.rockies-ice.com/images/MainHeaderPic_5.gif} +== ORMs ++* Are *HARD* ++* Not even fun like the picture +---- += ORMs +{image: http://www.agiledata.org/images/legacyDataSources.jpg} ++* Modeling ++** Tables <-> Classes ++** Fields <-> Attributes ++* Code Generation ++** SQL ++** Accessors ++** Relationship fetchers +---- += `Class::DBI` ++* Meta code is in the base class ++* No clear schema modelling ++* No separation between regular & meta code ++* Lots of hacks ++* Don't go there +---- += `DBIx::Class` ++* Meta enlightened ++** Schema objects fully model the SQL side ++** ResultSource etc partially model the OO side ++** Components for everything +---- += `DBIx::Class` ++* Meta code: ++** Proxy objects ++** Accessors ++** Code generation (SQL, Perl) +---- += ORM related meta programming ++* Complex ++* But manageable +---- += Vaporware +{image: http://www.nzgeothermal.org.nz/geothermal_energy/images/big/b-silencer-water-vapour.jpg} +---- += MO +{image: http://www.nzgeothermal.org.nz/geothermal_energy/images/big/b-silencer-water-vapour.jpg} ++* My baby ++* Moose spinoff ++** Stevan says it's Moose 2.0's ++* Perl 5 & Haskell (in pugs) +---- += MO Sucks +{image: http://www5f.biglobe.ne.jp/~tantan-kids/I.syokuzai/lollypop.jpg} ++* Experimental code ++* Boring parts messy or unwritten ++* Lacking integration, sugar layer ++** mst promised to help ;-) ++* Some parts slow as $*!&% +---- += MO Rocks +{image: http://nothingmuch.woobling.org/rocks.jpg} ++* Purely functional ++* Very suited for meta transformations ++* Fine grained control over everything ++* Can introduce entirely new conceptions of OO +---- += MO Architechture +{image: http://www.narrabay.com/images/engineering_large.jpg} ++* Modeling layer ++** Corresponds to compilation ++* Responder layer ++** Corresponds to runtime +---- += MO Architechture +{image: http://www.narrabay.com/images/engineering_large.jpg} ++* Compiler/sugar layer creates the modeling layer ++** Class objects are constructed, with all the details ++** No meta calculations happen yet ++* Modeling layer is "compiled" into responder layer ++** Can be done on demand or upfront ++* Obscurely named objects ++** Bear with me +---- += "Concepts" +{image: http://gallery.hd.org/_exhibits/light/_more2003/_more05/light-bulb-glowing-filament-light-blue-uncropped-lores-3-AHD.jpg} ++* The purest form of OO is prototypes ++** prototype OO can implement class OO ++* Concepts are new ways to express objects ++* A class is a concept ++* A role is a concept +---- += "Responder Interfaces" +{image: http://www.cs.usfca.edu/~parrt/course/652/lectures/images/vtable.jpg} ++* `$ri->dispatch( $responder, $invocation )` ++* Generated from concepts ++* Abstract VTable ++** The flattened method hierarchy ++** ... or something completely different ++** Performance ++** Flexibility +---- += "Responders" +{image: http://www.maine.gov/spo/flood/images/fema_seal.gif} ++* Something that is the subject of invocations ++** An object instance ++** A class (class methods) ++* A simple tuple `( $data, $ri )` +---- += "Invocations" +{image: http://www.mobilenews.sk/wp-content/lg-banana.jpg} ++* A method call, multimethod, message... whatever ++** Arguments, too ++* Whatever an RI will put up with ++** Extensible calling semantics +---- += MO compilation flow +{image: http://www.daveltd.com/photo/rolls/digital/water/waterfalls/snoqualmie-falls/snoqualmie-falls-flowing-3811-equalized.jpg} ++* Instantiate a `Class` object ++** Specify members (methods, attributes) ++** ... and ancestor classes & roles ++* Compile class ++** `my $class_methods_ri = $class->class_interface()` ++** Instance method RI closed in the constructor, within `$ri` ++** Purely functional operation +---- += RI composition +{image: http://www.daveltd.com/photo/rolls/digital/water/waterfalls/snoqualmie-falls/snoqualmie-falls-flowing-3811-equalized.jpg} ++* Compute instance methods and attributes from ancestry ++* Compute instance slots from attributes ++* Generate accessors ++.vim + MO::Run::ResponderInterface::MethodTable->new( + methods => %methods + ); +.vim ++* Generate constructor ++.vim + sub { + my $data = process_params(@_); + return box( $data, $instance_ri ); + } +.vim +---- += Instantiation +{image: http://d6044171.u109.worldispnetwork.com/images/Creation-hands-L.jpg} ++* Lookup RI using class name ++* Dispatch constructor class method ++* Compose data from params ++** Slightly complicated ++* Link data with closed `$instance_ri` ++** Responder == ( Data, RI ) ++** Like `bless` +---- += Method calls +{image: http://www.w3.org/2005/Talks/05-maxf-xtech/telephone.jpg} ++* How to talk with your new object? ++.vim + my $ri = $responder->responder_interface; + + ++ my $method = MO::Run::Invocation::Method->new( + name => "foo" + arguments => \@blah, + ); + + ++ $ri->dispatch( $responder, $method ); +.vim ++* Arbitrary responder interfaces also allowed ++** Doesn't have to be `$responder->responder_interface` +---- += OH NOES!!! +{image: http://www.encyclopediadramatica.com/images/f/f5/Surprise-buttsecks.jpg} ++* What's wrong with the previous slide? ++* RIs are objects too! ++* Need to bootstrap method calls ++* Runtime must bootstrap low level OO ++** More on this soon +---- += Meta level polymorphism +{image: http://www.worth1000.com/entries/44500/44790qV87_w.jpg} ++* An important point ++** In fact, *the* point of MO ++* Responder interfaces are polymorphic ++** Method table, network proxy, whatever ++* Easy to specialize ++** Optimizations ++** Strange features ++* Easy to mix several OO systems ++** Just compile to separate RIs +---- += MO in Perl 5 +{image: http://www.vetaid.org/assets/shop/card-camel-108.jpg} ++* Two runtimes ++* Very different ++* `MO::Run::Aux` wraps both ++** Share tests by running with different `%ENV` var +---- += Hosted runtime +{image: http://www.philnjill.com/collections/kubricks/kub_alien/S2Secret.jpg} ++* Nested object system ++* Bootstraps with Perl 5 ++** Native Perl OO == Low level, like VM opcodes ++** Virtualized MO == High Level ++** Completely separate levels ++* `$ri->dispatch( $responder, $method )` ++** not `$responder->$method()` ++* Full expressiveness ++* Slow, verbose +---- += Native runtime +{image: http://www.sonofthesouth.net/american-indians/pictures/indian-camp.jpg} ++* Integrated object system ++* RIs are compiled into packages ++** Simple RIs are dissassembled and stuffed into the stash ++** Complex RIs use `AUTOLOAD`, delegating to the RI meta object ++* Only named method calls ++** No arbitrary call concepts ++** `->` doesn't support anything else ++* As fast as "regular" Perl OO ++** Even makes simple, standalone `.pmc`s +---- += Perl 5 Runtimes ++* Native ++** Usable with regular Perl OO {html:☺} ++** Lacks arbitrary invocations {html:☹} ++* Virtualized ++** Feature complete {html:☺} ++** Doesn't integrate {html:☹} ++** Slow {html:☹} +---- += Idealized MO toolchain +{image: http://www.ibiblio.org/wm/paint/auth/botticelli/botticelli.venus.jpg} ++* Compiler handles modeling ++** Constructs meta objects at compile time ++* VM Opcodes support standard RI ++* Custom RIs are just objects ++** Bootstrapped using standard runtime objects ++*** Method table RI ++*** Named method invocation +---- += Perl 6 +{image: http://lolgeeks.com/wp-content/uploads/2007/05/lolgeeks016.jpg} ++* Perl 6 is the idealized MO toolchain ++** Can introduce syntax ++*** Invocation types ++*** Concept declarations ++** Implement bootstrap RIs in VM opcodes ++* Pugs might be using MO ++** I'm not really sure ++** It was ported a while ago +---- += Introducing new concepts ++* Roles are the shit ++* But what about next week's fad? ++* MO lets you introduce a new concept ++** Arbitrary at compile time ++** RI protocol at runtime +---- += Example - Prototype Objects ++* One shared RI +.vim + sub dispatch { + my ( $object, $invocation ) = @_; + + my $method = $object->{ $invocation->name }; + + $object->$method( $invocation->arguments ); + } +.vim +---- += Example - Attribute Grammars +{image: http://nothingmuch.woobling.org/village_people.jpg} ++* Crazy stuff from the 1970s ++* Renewed interest in {html:λ} land ++* Was pretty easy in MO +---- += Attribute Grammer Implementation +{image: http://grammar.ccc.commnet.edu/grammar/images/grammar.gif} ++* Introduce new concept objects ++** Attribute Grammar ++** Attribute Grammer Instance - one per AG per class ++* Runtime specialized RI ++** Shadows any RI with additional context sensitive methods ++* Additional runtime support code +---- += MO TODO +{image: http://www.constructionownerslawblog.com/checklist.jpg} ++* Write a sugar layer ++** Make it fun to use ++* Tests ++* Refactor the Class objects ++** Bloated example code ++** There are some patterns to extract ++* Self hosting +---- += Self Hosting ++* Easier to maintain MO written in Moose ++* Need to have clean syntax ++* Stable `.pmc` compilation +---- += Conclusion +{image: http://www1.istockphoto.com/file_thumbview_approve/2540021/2/istockphoto_2540021_painted_exclamation_mark.jpg} ++* Meta code is awesome code ++** Especially my meta code ;-) +---- += Conclusion +{image: http://www1.istockphoto.com/file_thumbview_approve/2540021/2/istockphoto_2540021_painted_exclamation_mark.jpg} +* Meta code is awesome code ++** Lets you program in new ways ++** Helps you take care of your other code ++* Meta code is important code ++** It can affect *anything* ++** Keep it minimalistic, and clearly defined ++** No spaghetti monsters ++* Meta code can be simple ++** Only complicated if you aren't careful +---- += BIE FRENDS +{image: http://www.girlscoutsofblackhawk.org/Portals/0/webphotos/thanks.jpg} diff --git a/object_meta_programming_slides/Spork.slides~ b/object_meta_programming_slides/Spork.slides~ new file mode 100644 index 0000000..ddb86b2 --- /dev/null +++ b/object_meta_programming_slides/Spork.slides~ @@ -0,0 +1,546 @@ +---- +presentation_topic: meta meta meta meta +presentation_title: Object Meta Programming +presentation_place: YAPC::EU::2007 +presentation_date: Aug 29, 2007 +---- += HAI FRENDS +{image:http://personal.inet.fi/taide/junttila/desert/2002/promopi.jpg} +== My name is Yuval +---- += Meta Programming +{image: http://www.prints.co.nz/Merchant2/graphics/00000001/7104_Squares_with_Concentric_Circles_Kandinsky_Wassily.jpg} +---- += Introduction +{image: http://www.room101.net/door.jpg} ++* Meta programming ++* writing /code/ which /outputs/ or /manipulates/ /code/ +---- += Many forms +{image: http://www.internationalhero.co.uk/m/manimal.jpg} ++* string `eval` ++* `%::` ++* closure generators ++* macros ++* real macros ++* compilers +---- += Many forms +{image: http://www.junjan.org/weblog/images/Flying_Spaghetti_Monster-thumb.jpg} ++* Home grown snippets ++* Home grown packages ++* Stuff on the CPAN (e.g. `Class::Accessor`, `Code::Perl`) ++* Large systems (`Template::Toolkit`) +---- += Summary +{image: http://www.evc.org/programs/TD_web_projects/westside_amy_2003_1/teen_times/peerpressure/images/16_peer_pressure_smoking.gif} +* You should already know it +* You probably do it ++* That's the intended audience anyway ;-) +---- += Object Meta Programming +---- += Object Meta Programming ++* Code that outputs or manipulates /object oriented code/ ++* Often written in OO +---- += Simple Examples +{image: http://www.wildoats.com/content/ApplePieSlice.jpg} ++* `Class::Accessor`, `Class::InsideOut` ++** Generates accessor methods ++* `Class::Prototyped` ++** Prototype object support in Perl ++* Lots of stuff on the CPAN +---- += Modeling OO +{image: http://www.nordicsubs.co.uk/covers/vogue.jpg} ++* High level object meta programming ++** The current trend ++** The picture illustrates an object modelling with class =) ++** Seriously though... +---- += Modeling OO +{image: http://www.nordicsubs.co.uk/covers/vogue.jpg} +* High level object meta programming +* What is a class? ++.vim +filetype: perl6 + + class Class { + has @isa; + has %methods; + has %attributes; + + ... + } +.vim +---- += Modeling OO +{image: http://www.nordicsubs.co.uk/covers/vogue.jpg} ++* Implementing OO ++** In OO ++* Meta objects: ++** Class ++** Method ++** Attribute +---- += Example class + +.vim +filetype: perl6 + + class Point { + has $x; + has $y; + + method distance_to { ... } + } +.vim +---- += Modeled with objects + +.vim +filetype: perl + + Class->new( + attributes => [ + Attribute->new( name => '$x' ), + Attribute->new( name => '$y' ), + ], + methods => [ + Method->new( + name => "distance_to", + definition => sub { ... } + ), + ], + ); +.vim +---- += Metamodel Services +{image: http://www1.istockphoto.com/file_thumbview_approve/944779/2/istockphoto_944779_reception_bell.jpg} ++* Form ++** Introspection/Reflection ++* Function ++** Class generation ++** Class transformation ++* Pattern packaging +---- += Case Study +{image: http://www.iinteractive.com/moose/images/a_moose.gif} +== Moose ++* A deep meta object system ++* 4 layers deep ++** Syntactic sugar ++** Custom metaclasses ++** Class::MOP ++** Perl's native OO +---- += Perl's native OO +{image: http://www.mileslight.com/images/perl-camel.gif} ++* Minimalistic ++** Class = Package = Symbol table hash +** Inheritence tree embedded in `@ISA` entry +** `bless` links data to a class +** `->` ++* Insanely flexible ++* Pretty klunky ++* Written in C (not very accessible) +---- += Class::MOP +{image: http://nothingmuch.woobling.org/MOP.jpg} ++* port of CLOS, more or less ++* MOP = Meta Object Protocol +---- += Class::MOP +{image: http://nothingmuch.woobling.org/MOP.jpg} ++* Model ++** `Class::MOP::Class` +** `Class::MOP::Method` +** `Class::MOP::Attribute` ++* Easy interface ++** Introspection ++** Transformation +---- += Class::MOP +{image: http://nothingmuch.woobling.org/MOP.jpg} ++* Can "parse" packages into meta objects ++* Modifying the objects writes back to packages ++* Code generation ++** Accessors from attributes ++** Constructor from attributes ++** Method modifiers +---- += Moose's custom metaclasses +{image: http://www.iinteractive.com/moose/images/a_moose.gif} ++* Subclasses of `Class::MOP::Class` et al ++* More fun features ++** Roles ++** `BUILD` etc a la Perl 6 ++* Type constraints +---- += Moose sugar layer +{image: http://nothingmuch.woobling.org/sugar.jpg} ++* Pseudo-declarative syntax ++* Maps to metaclass manipulations ++.vim + has foo => ( is => "rw" ); +.vim ++* becomes ++.vim + $metaclass->add_attribute( + Moose::Meta::Attribute->new( + foo => ( is => "rw" ), + ) + ); +.vim +---- += Moose vs. Class::Accessor +{image: http://nothingmuch.woobling.org/p-seal-at-toronto-zoo.jpg} ++* All that bloat just for the `has` syntax? ++* *NO!* ++* Pattern packaging +---- += MooseX:: +{image: http://www.threadpit.com/photos/all_styles/small/401.jpg} ++* Packaged meta code ++* Pretty clean ++* Mostly composable +---- += MooseX:: +{image: http://www.threadpit.com/photos/all_styles/small/401.jpg} ++* `MooseX::Storage` ++** Customizable serialization through metaprogramming ++* `MooseX::AttributeHelpers` ++** Additional methods for collection type attributes ++* `MooseX::Getopt` ++** Additional constructor compiles attributes into a `Getopt` spec ++* `MooseX::IOC` ++** Inversion of control integrated into the object system +---- += The point of Moose +{image: http://nothingmuch.woobling.org/cute_moose.jpg} ++* OO is less tedious ++* Helps you write meta code ++** Good APIs promote clean code ++** Easier to build on existing base ++** Conventions and structure let you play well with others (`MooseX::`) ++** Introspectable & tranformable metamodel +---- += Another Case Study +{image: http://www.rockies-ice.com/images/MainHeaderPic_5.gif} +== ORMs ++* Are *HARD* ++* Not even fun like the picture +---- += ORMs +{image: http://www.agiledata.org/images/legacyDataSources.jpg} ++* Modeling ++** Tables <-> Classes ++** Fields <-> Attributes ++* Code Generation ++** SQL ++** Accessors ++** Relationship fetchers +---- += `Class::DBI` ++* Meta code is in the base class ++* No clear schema modelling ++* No separation between regular & meta code ++* Lots of hacks ++* Don't go there +---- += `DBIx::Class` ++* Meta enlightened ++** Schema objects fully model the SQL side ++** ResultSource etc partially model the OO side ++** Components for everything +---- += `DBIx::Class` ++* Meta code: ++** Proxy objects ++** Accessors ++** Code generation (SQL, Perl) +---- += ORM related meta programming ++* Complex ++* But manageable +---- += Vaporware +{image: http://www.nzgeothermal.org.nz/geothermal_energy/images/big/b-silencer-water-vapour.jpg} +---- += MO +{image: http://www.nzgeothermal.org.nz/geothermal_energy/images/big/b-silencer-water-vapour.jpg} ++* My baby ++* Moose spinoff ++** Stevan says it's Moose 2.0's ++* Perl 5 & Haskell (in pugs) +---- += MO Sucks +{image: http://www5f.biglobe.ne.jp/~tantan-kids/I.syokuzai/lollypop.jpg} ++* Experimental code ++* Boring parts messy or unwritten ++* Lacking integration, sugar layer ++** mst promised to help ;-) ++* Some parts slow as $*!&% +---- += MO Rocks +{image: http://nothingmuch.woobling.org/rocks.jpg} ++* Purely functional ++* Very suited for meta transformations ++* Fine grained control over everything ++* Can introduce entirely new conceptions of OO +---- += MO Architechture +{image: http://www.narrabay.com/images/engineering_large.jpg} ++* Modeling layer ++** Corresponds to compilation ++* Responder layer ++** Corresponds to runtime +---- += MO Architechture +{image: http://www.narrabay.com/images/engineering_large.jpg} ++* Compiler/sugar layer creates the modeling layer ++** Class objects are constructed, with all the details ++** No meta calculations happen yet ++* Modeling layer is "compiled" into responder layer ++** Can be done on demand or upfront ++* Obscurely named objects ++** Bear with me +---- += "Concepts" +{image: http://gallery.hd.org/_exhibits/light/_more2003/_more05/light-bulb-glowing-filament-light-blue-uncropped-lores-3-AHD.jpg} ++* The purest form of OO is prototypes ++** prototype OO can implement class OO ++* Concepts are new ways to express objects ++* A class is a concept ++* A role is a concept +---- += "Responder Interfaces" +{image: http://www.cs.usfca.edu/~parrt/course/652/lectures/images/vtable.jpg} ++* `$ri->dispatch( $responder, $invocation )` ++* Generated from concepts ++* Abstract VTable ++** The flattened method hierarchy ++** ... or something completely different ++** Performance ++** Flexibility +---- += "Responders" +{image: http://www.maine.gov/spo/flood/images/fema_seal.gif} ++* Something that is the subject of invocations ++** An object instance ++** A class (class methods) ++* A simple tuple `( $data, $ri )` +---- += "Invocations" +{image: http://www.mobilenews.sk/wp-content/lg-banana.jpg} ++* A method call, multimethod, message... whatever ++** Arguments, too ++* Whatever an RI will put up with ++** Extensible calling semantics +---- += MO compilation flow +{image: http://www.daveltd.com/photo/rolls/digital/water/waterfalls/snoqualmie-falls/snoqualmie-falls-flowing-3811-equalized.jpg} ++* Instantiate a `Class` object ++** Specify members (methods, attributes) ++** ... and ancestor classes & roles ++* Compile class ++** `my $class_methods_ri = $class->class_interface()` ++** Instance method RI closed in the constructor, within `$ri` ++** Purely functional operation +---- += RI composition +{image: http://www.daveltd.com/photo/rolls/digital/water/waterfalls/snoqualmie-falls/snoqualmie-falls-flowing-3811-equalized.jpg} ++* Compute instance methods and attributes from ancestry ++* Compute instance slots from attributes ++* Generate accessors ++.vim + MO::Run::ResponderInterface::MethodTable->new( + methods => %methods + ); +.vim ++* Generate constructor ++.vim + sub { + my $data = process_params(@_); + return box( $data, $instance_ri ); + } +.vim +---- += Instantiation +{image: http://d6044171.u109.worldispnetwork.com/images/Creation-hands-L.jpg} ++* Lookup RI using class name ++* Dispatch constructor class method ++* Compose data from params ++** Slightly complicated ++* Link data with closed `$instance_ri` ++** Responder == ( Data, RI ) ++** Like `bless` +---- += Method calls +{image: http://www.w3.org/2005/Talks/05-maxf-xtech/telephone.jpg} ++* How to talk with your new object? ++.vim + my $ri = $responder->responder_interface; + + ++ my $method = MO::Run::Invocation::Method->new( + name => "foo" + arguments => \@blah, + ); + + ++ $ri->dispatch( $responder, $method ); +.vim ++* Arbitrary responder interfaces also allowed ++** Doesn't have to be `$responder->responder_interface` +---- += OH NOES!!! +{image: http://www.encyclopediadramatica.com/images/f/f5/Surprise-buttsecks.jpg} ++* What's wrong with the previous slide? ++* RIs are objects too! ++* Need to bootstrap method calls ++* Runtime must bootstrap low level OO ++** More on this soon +---- += Meta level polymorphism +{image: http://www.worth1000.com/entries/44500/44790qV87_w.jpg} ++* An important point ++** In fact, *the* point of MO ++* Responder interfaces are polymorphic ++** Method table, network proxy, whatever ++* Easy to specialize ++** Optimizations ++** Strange features ++* Easy to mix several OO systems ++** Just compile to separate RIs +---- += MO in Perl 5 +{image: http://www.vetaid.org/assets/shop/card-camel-108.jpg} ++* Two runtimes ++* Very different ++* `MO::Run::Aux` wraps both ++** Share tests by running with different `%ENV` var +---- += Hosted runtime +{image: http://www.philnjill.com/collections/kubricks/kub_alien/S2Secret.jpg} ++* Nested object system ++* Bootstraps with Perl 5 ++** Native Perl OO == Low level, like VM opcodes ++** Virtualized MO == High Level ++** Completely separate levels ++* `$ri->dispatch( $responder, $method )` ++** not `$responder->$method()` ++* Full expressiveness ++* Slow, verbose +---- += Native runtime +{image: http://www.sonofthesouth.net/american-indians/pictures/indian-camp.jpg} ++* Integrated object system ++* RIs are compiled into packages ++** Simple RIs are dissassembled and stuffed into the stash ++** Complex RIs use `AUTOLOAD`, delegating to the RI meta object ++* Only named method calls ++** No arbitrary call concepts ++** `->` doesn't support anything else ++* As fast as "regular" Perl OO ++** Even makes simple, standalone `.pmc`s +---- += Perl 5 Runtimes ++* Native ++** Usable with regular Perl OO {html:☺} ++** Lacks arbitrary invocations {html:☹} ++* Virtualized ++** Feature complete {html:☺} ++** Doesn't integrate {html:☹} ++** Slow {html:☹} +---- += Idealized MO toolchain +{image: http://www.ibiblio.org/wm/paint/auth/botticelli/botticelli.venus.jpg} ++* Compiler handles modeling ++** Constructs meta objects at compile time ++* VM Opcodes support standard RI ++* Custom RIs are just objects ++** Bootstrapped using standard runtime objects ++*** Method table RI ++*** Named method invocation +---- += Perl 6 +{image: http://lolgeeks.com/wp-content/uploads/2007/05/lolgeeks016.jpg} ++* Perl 6 is the idealized MO toolchain ++** Can introduce syntax ++*** Invocation types ++*** Concept declarations ++** Implement bootstrap RIs in VM opcodes ++* Pugs might be using MO ++** I'm not really sure ++** It was ported a while ago +---- += Introducing new concepts ++* Roles are the shit ++* But what about next week's fad? ++* MO lets you introduce a new concept ++** Arbitrary at compile time ++** RI protocol at runtime +---- += Example - Prototype Objects ++* One shared RI +.vim + sub dispatch { + my ( $object, $invocation ) = @_; + + my $method = $object->{ $invocation->name }; + + $object->$method( $invocation->arguments ); + } +.vim +---- += Example - Attribute Grammars +{image: http://nothingmuch.woobling.org/village_people.jpg} ++* Crazy stuff from the 1970s ++* Renewed interest in {html:λ} land ++* Was pretty easy in MO +---- += Attribute Grammer Implementation +{image: http://grammar.ccc.commnet.edu/grammar/images/grammar.gif} ++* Introduce new concept objects ++** Attribute Grammar ++** Attribute Grammer Instance - one per AG per class ++* Runtime specialized RI ++** Shadows any RI with additional context sensitive methods ++* Additional runtime support code +---- += MO TODO +{image: http://www.constructionownerslawblog.com/checklist.jpg} ++* Write a sugar layer ++** Make it fun to use ++* Tests ++* Refactor the Class objects ++** Bloated example code ++** There are some patterns to extract ++* Self hosting +---- += Self Hosting ++* Easier to maintain MO written in Moose ++* Need to have clean syntax ++* Stable `.pmc` compilation +---- += Conclusion +{image: http://www1.istockphoto.com/file_thumbview_approve/2540021/2/istockphoto_2540021_painted_exclamation_mark.jpg} ++* Meta code is awesome code ++** Especially my meta code ;-) +---- += Conclusion +{image: http://www1.istockphoto.com/file_thumbview_approve/2540021/2/istockphoto_2540021_painted_exclamation_mark.jpg} +* Meta code is awesome code ++** Lets you program in new ways ++** Helps you take care of your other code ++* Meta code is important code ++** It can affect *anything* ++** Keep it minimalistic, and clearly defined ++** No spaghetti monsters ++* Meta code can be simple ++** Only complicated if you aren't careful +---- += BIE FRENDS +{image: http://www.girlscoutsofblackhawk.org/Portals/0/webphotos/thanks.jpg} diff --git a/object_meta_programming_slides/config.yaml b/object_meta_programming_slides/config.yaml new file mode 100644 index 0000000..52a1f26 --- /dev/null +++ b/object_meta_programming_slides/config.yaml @@ -0,0 +1,70 @@ +################################################################################ +# Spork Configuration File. +# +# Please read this file over and set the values to your own. +# +# If you want global settings for all your slideshows, copy this file to +# ~/.sporkrc/config.yaml. Any settings in this local file will override +# the global value of that setting. +# +# See C<perldoc Spork::Config> for details on settings. +################################################################################ + +# These will be guessed using getpwuid on the real uid + +# author_name: Brian Ingerson +# author_email: ingy@cpan.org +# author_webpage: http://search.cpan.org/~ingy/ +# copyright_string: Copyright © 2005 Brian Ingerson + + + + +# Some styling: + +# banner_bgcolor: hotpink +# logo_image: logo.png +# image_width: 350 +# auto_scrolldown: 1 +# show_controls: 1 +# mouse_controls: 0 +# link_previous: < < Previous +# link_next: Next >> +# link_index: Index + + +# Some paths: + +# slides_file: Spork.slides +# template_directory: template/tt2 +# template_path: +# - ./template/tt2 +# slides_directory: slides + +# This one defaults to CWD, and will vary each time you run 'spork -make' +# file_base: /Users/ingy/dev/cpan/Spork/ + + +# These should probably go in ~/.sporkrc/config.yaml if they're wrong + +# download_method: wget +# start_command: open slides/start.html + +# character_encoding: utf-8 + + + +# Change core classes here: + +# formatter_class: Spork::Formatter::Kwid + + +# Set plugin classes here: + +# plugin_classes: +# - Spork::S5 +# - Spork::S5Theme +# - Spork::S5ThemeFlower +# - Spork::S5ThemeBlackday +# - Kwiki::PerlBlocks + diff --git a/object_meta_programming_slides/config/config.yaml b/object_meta_programming_slides/config/config.yaml new file mode 100644 index 0000000..059e356 --- /dev/null +++ b/object_meta_programming_slides/config/config.yaml @@ -0,0 +1,9 @@ +# DO NOT EDIT THIS FILE +# Put overrides in the top level config.yaml +# See: http://www.kwiki.org/?ChangingConfigDotYaml +# +site_title: Kwiki +main_page: HomePage +database_directory: database +logo_image: palm90.png +script_name: index.cgi diff --git a/object_meta_programming_slides/pretty.css b/object_meta_programming_slides/pretty.css new file mode 100644 index 0000000..5db43b7 --- /dev/null +++ b/object_meta_programming_slides/pretty.css @@ -0,0 +1,48 @@ +/* + Theme: i18n + Eric A. Meyer (http://meyerweb.com/) + Theme placed under CC by-sa 2.0 license +*/ + +body {background: #95A7D4 url(bg-slide.jpg) 100% 100% no-repeat; color: #210; font: 36px Arial, sans-serif; line-height: .9;} +a {text-decoration: none; color: #336; border-bottom: 1px dotted;} +h1, h2, h3, h4, h5, h6 {font-size: 1.3em; margin: 0 2em;} +sup {font-size: 0.75em; font-weight: normal; + vertical-align: 0.5em; line-height: 1px;} +ul {margin-left: 1em; padding-left: 0; font-size: } +li {margin-bottom: 0.66em;} +li li {margin: 0.33em 0; font-size: smaller;} + +#header {background: url(bg-shade.png); border-bottom: 1px solid #333; + padding-bottom: 2em;} +#footer {background: url(bg-shade.png); color: #BBB; border-top: 1px solid #333;} +#header, #footer {font-size: 0.5em;} +#footer h1, #footer h2 { padding: 0.5em 0.75em; + font-weight: normal; font-style: italic;} +#footer h1 {left: 0; font-size: 1em; letter-spacing: 1px;} +#footer h2 {position: absolute; bottom: 0; right: 0;} + +#controls {font-size: 0.75em;} +#navList {margin-top: 3px;} +#navLinks a {margin: 0 0.33em; padding: 0 0.25em; + border: 1px solid; border-color: #CCD #556 #556 #CCD; + background-color: #8597C4;} + +#currentSlide {font-size: 0.5em;} +#currentSlide span {font-size: 13px; color: rgb(49%,47%,66%);} +#currentSlide #csSep {display: none;} +#currentSlide #csHere {font-weight: bold;} +#currentSlide #csHere:before {content: "#"; font-weight: normal;} +#currentSlide #csTotal:before {content: " of ";} + +.slide h1 {font-size: 2em; line-height: 1; letter-spacing: -1px; font-weight: +100%; + margin: 0 -15% 1em 0; padding: 0.5em 15% 0.06125em 0; border-bottom: 0.06125em solid rgb(90,94,120);} +#slide0 h1 {border: none; font-size: 2em; letter-spacing: 0; margin: 3em 0 1.5em;} +#slide0 h2 {font-size: 1em; margin: 0.5em 0 0;} +#slide0 h3 {font-size: 1em; margin: 0.5em 0 0;} +#slide0 h4 {margin-top: 0; font-size: smaller;} + +small { display: none }; + +.slide .current {color: #003; text-shadow: 0 0 0.25em #9AABD7;} + diff --git a/object_meta_programming_slides/slides/css/vim_mode.css b/object_meta_programming_slides/slides/css/vim_mode.css new file mode 100644 index 0000000..a7ba2e3 --- /dev/null +++ b/object_meta_programming_slides/slides/css/vim_mode.css @@ -0,0 +1,11 @@ +pre.vim { margin-left: 1em } +.synComment { color: #0000FF } +.synConstant { color: #FF00FF } +.synIdentifier { color: #008B8B } +.synStatement { color: #A52A2A ; font-weight: bold } +.synPreProc { color: #A020F0 } +.synType { color: #2E8B57 ; font-weight: bold } +.synSpecial { color: #6A5ACD } +.synUnderlined { color: #000000 ; text-decoration: underline } +.synError { color: #FFFFFF ; background: #FF0000 none } +.synTodo { color: #0000FF ; background: #FFFF00 none } diff --git a/object_meta_programming_slides/slides/css/vim_mode.css~ b/object_meta_programming_slides/slides/css/vim_mode.css~ new file mode 100644 index 0000000..a7ba2e3 --- /dev/null +++ b/object_meta_programming_slides/slides/css/vim_mode.css~ @@ -0,0 +1,11 @@ +pre.vim { margin-left: 1em } +.synComment { color: #0000FF } +.synConstant { color: #FF00FF } +.synIdentifier { color: #008B8B } +.synStatement { color: #A52A2A ; font-weight: bold } +.synPreProc { color: #A020F0 } +.synType { color: #2E8B57 ; font-weight: bold } +.synSpecial { color: #6A5ACD } +.synUnderlined { color: #000000 ; text-decoration: underline } +.synError { color: #FFFFFF ; background: #FF0000 none } +.synTodo { color: #0000FF ; background: #FFFF00 none } diff --git a/object_meta_programming_slides/slides/images/16_peer_pressure_smoking.gif b/object_meta_programming_slides/slides/images/16_peer_pressure_smoking.gif new file mode 100644 index 0000000..4c30c8c Binary files /dev/null and b/object_meta_programming_slides/slides/images/16_peer_pressure_smoking.gif differ diff --git a/object_meta_programming_slides/slides/images/2.jpg b/object_meta_programming_slides/slides/images/2.jpg new file mode 100644 index 0000000..fb4991e Binary files /dev/null and b/object_meta_programming_slides/slides/images/2.jpg differ diff --git a/object_meta_programming_slides/slides/images/401.jpg b/object_meta_programming_slides/slides/images/401.jpg new file mode 100644 index 0000000..a641d9e Binary files /dev/null and b/object_meta_programming_slides/slides/images/401.jpg differ diff --git a/object_meta_programming_slides/slides/images/44790qV87_w.jpg b/object_meta_programming_slides/slides/images/44790qV87_w.jpg new file mode 100644 index 0000000..6ef2533 Binary files /dev/null and b/object_meta_programming_slides/slides/images/44790qV87_w.jpg differ diff --git a/object_meta_programming_slides/slides/images/7104_Squares_with_Concentric_Circles_Kandinsky_Wassily.jpg b/object_meta_programming_slides/slides/images/7104_Squares_with_Concentric_Circles_Kandinsky_Wassily.jpg new file mode 100644 index 0000000..f90a214 Binary files /dev/null and b/object_meta_programming_slides/slides/images/7104_Squares_with_Concentric_Circles_Kandinsky_Wassily.jpg differ diff --git a/object_meta_programming_slides/slides/images/ApplePieSlice.jpg b/object_meta_programming_slides/slides/images/ApplePieSlice.jpg new file mode 100644 index 0000000..e52872c Binary files /dev/null and b/object_meta_programming_slides/slides/images/ApplePieSlice.jpg differ diff --git a/object_meta_programming_slides/slides/images/Blacksmith.jpg b/object_meta_programming_slides/slides/images/Blacksmith.jpg new file mode 100644 index 0000000..28ad0e8 Binary files /dev/null and b/object_meta_programming_slides/slides/images/Blacksmith.jpg differ diff --git a/object_meta_programming_slides/slides/images/Blog.Ubuntu5.jpg b/object_meta_programming_slides/slides/images/Blog.Ubuntu5.jpg new file mode 100644 index 0000000..6b6cbdd Binary files /dev/null and b/object_meta_programming_slides/slides/images/Blog.Ubuntu5.jpg differ diff --git a/object_meta_programming_slides/slides/images/Creation-hands-L.jpg b/object_meta_programming_slides/slides/images/Creation-hands-L.jpg new file mode 100644 index 0000000..0cd9e1f Binary files /dev/null and b/object_meta_programming_slides/slides/images/Creation-hands-L.jpg differ diff --git a/object_meta_programming_slides/slides/images/FLDancers03.jpg b/object_meta_programming_slides/slides/images/FLDancers03.jpg new file mode 100644 index 0000000..f114bd1 Binary files /dev/null and b/object_meta_programming_slides/slides/images/FLDancers03.jpg differ diff --git a/object_meta_programming_slides/slides/images/Flying_Spaghetti_Monster-thumb.jpg b/object_meta_programming_slides/slides/images/Flying_Spaghetti_Monster-thumb.jpg new file mode 100644 index 0000000..ad18867 Binary files /dev/null and b/object_meta_programming_slides/slides/images/Flying_Spaghetti_Monster-thumb.jpg differ diff --git a/object_meta_programming_slides/slides/images/JulieMomBOM.jpg b/object_meta_programming_slides/slides/images/JulieMomBOM.jpg new file mode 100644 index 0000000..519e6cd Binary files /dev/null and b/object_meta_programming_slides/slides/images/JulieMomBOM.jpg differ diff --git a/object_meta_programming_slides/slides/images/LDL-1000_012.jpg b/object_meta_programming_slides/slides/images/LDL-1000_012.jpg new file mode 100644 index 0000000..5443a6a Binary files /dev/null and b/object_meta_programming_slides/slides/images/LDL-1000_012.jpg differ diff --git a/object_meta_programming_slides/slides/images/MOP.jpg b/object_meta_programming_slides/slides/images/MOP.jpg new file mode 100644 index 0000000..5fdcddd Binary files /dev/null and b/object_meta_programming_slides/slides/images/MOP.jpg differ diff --git a/object_meta_programming_slides/slides/images/MainHeaderPic_5.gif b/object_meta_programming_slides/slides/images/MainHeaderPic_5.gif new file mode 100644 index 0000000..921567b Binary files /dev/null and b/object_meta_programming_slides/slides/images/MainHeaderPic_5.gif differ diff --git a/object_meta_programming_slides/slides/images/Moibeal-Mop-Detail.jpg b/object_meta_programming_slides/slides/images/Moibeal-Mop-Detail.jpg new file mode 100644 index 0000000..d198659 Binary files /dev/null and b/object_meta_programming_slides/slides/images/Moibeal-Mop-Detail.jpg differ diff --git a/object_meta_programming_slides/slides/images/S2Secret.jpg b/object_meta_programming_slides/slides/images/S2Secret.jpg new file mode 100644 index 0000000..ed8b351 Binary files /dev/null and b/object_meta_programming_slides/slides/images/S2Secret.jpg differ diff --git a/object_meta_programming_slides/slides/images/Surprise-buttsecks.jpg b/object_meta_programming_slides/slides/images/Surprise-buttsecks.jpg new file mode 100644 index 0000000..79ca860 Binary files /dev/null and b/object_meta_programming_slides/slides/images/Surprise-buttsecks.jpg differ diff --git a/object_meta_programming_slides/slides/images/Sweden-coins-10-5-Kronor-50-oere-silver-copper-gold-colours-SEK-1-DHD.jpg b/object_meta_programming_slides/slides/images/Sweden-coins-10-5-Kronor-50-oere-silver-copper-gold-colours-SEK-1-DHD.jpg new file mode 100644 index 0000000..821d476 Binary files /dev/null and b/object_meta_programming_slides/slides/images/Sweden-coins-10-5-Kronor-50-oere-silver-copper-gold-colours-SEK-1-DHD.jpg differ diff --git a/object_meta_programming_slides/slides/images/Thank b/object_meta_programming_slides/slides/images/Thank new file mode 100644 index 0000000..07eae5c --- /dev/null +++ b/object_meta_programming_slides/slides/images/Thank @@ -0,0 +1,24 @@ +<html> + <head> + <title>Not yet in...</title> + </head> + <body> + <p>Go away, come back later.</p> + <ul> + <li>nothingmuch - my nickname/handle/username</li> + <li><a href="http://search.cpan.org/~nuffin">my CPAN modules</a></li> + <li><a href="mailto:nothingmuch@woobling.org">my email</a></li> + <li>Yuval Kogman - my name in english</li> + <li>×××× ×§××'×× - my name in hebrew</li> + <li>my <a href="http://perlmonks.org/?node_id=205152">perlmonks homenode</a></li> + <li><a href="http://gallery.woobling.org/nothingmuch">some pictures</a></li> + <li><a href="gpg-key.asc">gpg key</a></li> + <li><a href="http://www.woobling.org/">family website</a></li> + </ul> + + <div style="padding: 3em"> + <h2 style="font-family: sans-serif; text-align: center" class="delicious-banner sidebar-title"><a href="http://del.icio.us"><img src="http://del.icio.us/static/img/delicious.med.gif" width="16" height="16" alt="del.icio.us"></a> <a href="http://del.icio.us/nothingmuch">del.icio.us</a></h2> + <script type="text/javascript" src="http://del.icio.us/feeds/js/tags/nothingmuch?icon;count=80;size=10-28;color=87ceeb-0000ff"></script> + </div> + </body> +</html> diff --git a/object_meta_programming_slides/slides/images/a_moose.gif b/object_meta_programming_slides/slides/images/a_moose.gif new file mode 100644 index 0000000..d3e67b2 Binary files /dev/null and b/object_meta_programming_slides/slides/images/a_moose.gif differ diff --git a/object_meta_programming_slides/slides/images/b-silencer-water-vapour.jpg b/object_meta_programming_slides/slides/images/b-silencer-water-vapour.jpg new file mode 100644 index 0000000..400e3e0 Binary files /dev/null and b/object_meta_programming_slides/slides/images/b-silencer-water-vapour.jpg differ diff --git a/object_meta_programming_slides/slides/images/bagdad_bob_large.gif b/object_meta_programming_slides/slides/images/bagdad_bob_large.gif new file mode 100644 index 0000000..e3a3f6e Binary files /dev/null and b/object_meta_programming_slides/slides/images/bagdad_bob_large.gif differ diff --git a/object_meta_programming_slides/slides/images/basics.jpg b/object_meta_programming_slides/slides/images/basics.jpg new file mode 100644 index 0000000..33524d6 Binary files /dev/null and b/object_meta_programming_slides/slides/images/basics.jpg differ diff --git a/object_meta_programming_slides/slides/images/bcg_fresh_fruits_1024x768.jpg b/object_meta_programming_slides/slides/images/bcg_fresh_fruits_1024x768.jpg new file mode 100644 index 0000000..dbec8f7 Binary files /dev/null and b/object_meta_programming_slides/slides/images/bcg_fresh_fruits_1024x768.jpg differ diff --git a/object_meta_programming_slides/slides/images/botticelli.venus.jpg b/object_meta_programming_slides/slides/images/botticelli.venus.jpg new file mode 100644 index 0000000..a9171b8 Binary files /dev/null and b/object_meta_programming_slides/slides/images/botticelli.venus.jpg differ diff --git a/object_meta_programming_slides/slides/images/burger.jpg b/object_meta_programming_slides/slides/images/burger.jpg new file mode 100644 index 0000000..d7b5ff2 Binary files /dev/null and b/object_meta_programming_slides/slides/images/burger.jpg differ diff --git a/object_meta_programming_slides/slides/images/card-camel-108.jpg b/object_meta_programming_slides/slides/images/card-camel-108.jpg new file mode 100644 index 0000000..8b5ad3a Binary files /dev/null and b/object_meta_programming_slides/slides/images/card-camel-108.jpg differ diff --git a/object_meta_programming_slides/slides/images/centralized_decentralized.gif b/object_meta_programming_slides/slides/images/centralized_decentralized.gif new file mode 100644 index 0000000..72a0298 Binary files /dev/null and b/object_meta_programming_slides/slides/images/centralized_decentralized.gif differ diff --git a/object_meta_programming_slides/slides/images/checklist.jpg b/object_meta_programming_slides/slides/images/checklist.jpg new file mode 100644 index 0000000..ba3d214 Binary files /dev/null and b/object_meta_programming_slides/slides/images/checklist.jpg differ diff --git a/object_meta_programming_slides/slides/images/cherries.png b/object_meta_programming_slides/slides/images/cherries.png new file mode 100644 index 0000000..d806914 Binary files /dev/null and b/object_meta_programming_slides/slides/images/cherries.png differ diff --git a/object_meta_programming_slides/slides/images/colorpref.gif b/object_meta_programming_slides/slides/images/colorpref.gif new file mode 100644 index 0000000..0cf8915 Binary files /dev/null and b/object_meta_programming_slides/slides/images/colorpref.gif differ diff --git a/object_meta_programming_slides/slides/images/concepts-bicycleObject.gif b/object_meta_programming_slides/slides/images/concepts-bicycleObject.gif new file mode 100644 index 0000000..f7f37f1 Binary files /dev/null and b/object_meta_programming_slides/slides/images/concepts-bicycleObject.gif differ diff --git a/object_meta_programming_slides/slides/images/conflict-1.1.gif b/object_meta_programming_slides/slides/images/conflict-1.1.gif new file mode 100644 index 0000000..2975797 Binary files /dev/null and b/object_meta_programming_slides/slides/images/conflict-1.1.gif differ diff --git a/object_meta_programming_slides/slides/images/cpan.jpg b/object_meta_programming_slides/slides/images/cpan.jpg new file mode 100644 index 0000000..2b98e13 Binary files /dev/null and b/object_meta_programming_slides/slides/images/cpan.jpg differ diff --git a/object_meta_programming_slides/slides/images/cute_moose.jpg b/object_meta_programming_slides/slides/images/cute_moose.jpg new file mode 100644 index 0000000..db9a4f2 Binary files /dev/null and b/object_meta_programming_slides/slides/images/cute_moose.jpg differ diff --git a/object_meta_programming_slides/slides/images/dependencies.png b/object_meta_programming_slides/slides/images/dependencies.png new file mode 100644 index 0000000..4606a95 Binary files /dev/null and b/object_meta_programming_slides/slides/images/dependencies.png differ diff --git a/object_meta_programming_slides/slides/images/desk.jpg b/object_meta_programming_slides/slides/images/desk.jpg new file mode 100644 index 0000000..8d52ee1 Binary files /dev/null and b/object_meta_programming_slides/slides/images/desk.jpg differ diff --git a/object_meta_programming_slides/slides/images/door.jpg b/object_meta_programming_slides/slides/images/door.jpg new file mode 100644 index 0000000..d1ba86b Binary files /dev/null and b/object_meta_programming_slides/slides/images/door.jpg differ diff --git a/object_meta_programming_slides/slides/images/email_final.jpg b/object_meta_programming_slides/slides/images/email_final.jpg new file mode 100644 index 0000000..df6cbcd Binary files /dev/null and b/object_meta_programming_slides/slides/images/email_final.jpg differ diff --git a/object_meta_programming_slides/slides/images/engineering_large.jpg b/object_meta_programming_slides/slides/images/engineering_large.jpg new file mode 100644 index 0000000..dd3430c Binary files /dev/null and b/object_meta_programming_slides/slides/images/engineering_large.jpg differ diff --git a/object_meta_programming_slides/slides/images/fema_seal.gif b/object_meta_programming_slides/slides/images/fema_seal.gif new file mode 100644 index 0000000..b314260 Binary files /dev/null and b/object_meta_programming_slides/slides/images/fema_seal.gif differ diff --git a/object_meta_programming_slides/slides/images/friend16.jpg b/object_meta_programming_slides/slides/images/friend16.jpg new file mode 100644 index 0000000..36cb7c0 Binary files /dev/null and b/object_meta_programming_slides/slides/images/friend16.jpg differ diff --git a/object_meta_programming_slides/slides/images/giant b/object_meta_programming_slides/slides/images/giant new file mode 100644 index 0000000..07eae5c --- /dev/null +++ b/object_meta_programming_slides/slides/images/giant @@ -0,0 +1,24 @@ +<html> + <head> + <title>Not yet in...</title> + </head> + <body> + <p>Go away, come back later.</p> + <ul> + <li>nothingmuch - my nickname/handle/username</li> + <li><a href="http://search.cpan.org/~nuffin">my CPAN modules</a></li> + <li><a href="mailto:nothingmuch@woobling.org">my email</a></li> + <li>Yuval Kogman - my name in english</li> + <li>×××× ×§××'×× - my name in hebrew</li> + <li>my <a href="http://perlmonks.org/?node_id=205152">perlmonks homenode</a></li> + <li><a href="http://gallery.woobling.org/nothingmuch">some pictures</a></li> + <li><a href="gpg-key.asc">gpg key</a></li> + <li><a href="http://www.woobling.org/">family website</a></li> + </ul> + + <div style="padding: 3em"> + <h2 style="font-family: sans-serif; text-align: center" class="delicious-banner sidebar-title"><a href="http://del.icio.us"><img src="http://del.icio.us/static/img/delicious.med.gif" width="16" height="16" alt="del.icio.us"></a> <a href="http://del.icio.us/nothingmuch">del.icio.us</a></h2> + <script type="text/javascript" src="http://del.icio.us/feeds/js/tags/nothingmuch?icon;count=80;size=10-28;color=87ceeb-0000ff"></script> + </div> + </body> +</html> diff --git a/object_meta_programming_slides/slides/images/giant_cake.jpg b/object_meta_programming_slides/slides/images/giant_cake.jpg new file mode 100644 index 0000000..cd55e77 Binary files /dev/null and b/object_meta_programming_slides/slides/images/giant_cake.jpg differ diff --git a/object_meta_programming_slides/slides/images/grammar.gif b/object_meta_programming_slides/slides/images/grammar.gif new file mode 100644 index 0000000..971fe3c Binary files /dev/null and b/object_meta_programming_slides/slides/images/grammar.gif differ diff --git a/object_meta_programming_slides/slides/images/img19.png b/object_meta_programming_slides/slides/images/img19.png new file mode 100644 index 0000000..6667982 Binary files /dev/null and b/object_meta_programming_slides/slides/images/img19.png differ diff --git a/object_meta_programming_slides/slides/images/indian-camp.jpg b/object_meta_programming_slides/slides/images/indian-camp.jpg new file mode 100644 index 0000000..da05814 Binary files /dev/null and b/object_meta_programming_slides/slides/images/indian-camp.jpg differ diff --git a/object_meta_programming_slides/slides/images/istockphoto_2540021_painted_exclamation_mark.jpg b/object_meta_programming_slides/slides/images/istockphoto_2540021_painted_exclamation_mark.jpg new file mode 100644 index 0000000..945cc4b Binary files /dev/null and b/object_meta_programming_slides/slides/images/istockphoto_2540021_painted_exclamation_mark.jpg differ diff --git a/object_meta_programming_slides/slides/images/istockphoto_944779_reception_bell.jpg b/object_meta_programming_slides/slides/images/istockphoto_944779_reception_bell.jpg new file mode 100644 index 0000000..fd96479 Binary files /dev/null and b/object_meta_programming_slides/slides/images/istockphoto_944779_reception_bell.jpg differ diff --git a/object_meta_programming_slides/slides/images/kyle-needs-help-2.half.jpg b/object_meta_programming_slides/slides/images/kyle-needs-help-2.half.jpg new file mode 100644 index 0000000..16ba1c4 Binary files /dev/null and b/object_meta_programming_slides/slides/images/kyle-needs-help-2.half.jpg differ diff --git a/object_meta_programming_slides/slides/images/large_logo.png b/object_meta_programming_slides/slides/images/large_logo.png new file mode 100644 index 0000000..7e4773c Binary files /dev/null and b/object_meta_programming_slides/slides/images/large_logo.png differ diff --git a/object_meta_programming_slides/slides/images/legacyDataSources.jpg b/object_meta_programming_slides/slides/images/legacyDataSources.jpg new file mode 100644 index 0000000..08b3061 Binary files /dev/null and b/object_meta_programming_slides/slides/images/legacyDataSources.jpg differ diff --git a/object_meta_programming_slides/slides/images/lg-banana.jpg b/object_meta_programming_slides/slides/images/lg-banana.jpg new file mode 100644 index 0000000..9df9eb5 Binary files /dev/null and b/object_meta_programming_slides/slides/images/lg-banana.jpg differ diff --git a/object_meta_programming_slides/slides/images/light-bulb-glowing-filament-light-blue-uncropped-lores-3-AHD.jpg b/object_meta_programming_slides/slides/images/light-bulb-glowing-filament-light-blue-uncropped-lores-3-AHD.jpg new file mode 100644 index 0000000..8d976ff Binary files /dev/null and b/object_meta_programming_slides/slides/images/light-bulb-glowing-filament-light-blue-uncropped-lores-3-AHD.jpg differ diff --git a/object_meta_programming_slides/slides/images/lolgeeks016.jpg b/object_meta_programming_slides/slides/images/lolgeeks016.jpg new file mode 100644 index 0000000..f3c14a2 Binary files /dev/null and b/object_meta_programming_slides/slides/images/lolgeeks016.jpg differ diff --git a/object_meta_programming_slides/slides/images/lollypop.jpg b/object_meta_programming_slides/slides/images/lollypop.jpg new file mode 100644 index 0000000..38e1d1e Binary files /dev/null and b/object_meta_programming_slides/slides/images/lollypop.jpg differ diff --git a/object_meta_programming_slides/slides/images/mag_glass.jpg b/object_meta_programming_slides/slides/images/mag_glass.jpg new file mode 100644 index 0000000..19eeda1 Binary files /dev/null and b/object_meta_programming_slides/slides/images/mag_glass.jpg differ diff --git a/object_meta_programming_slides/slides/images/maintop.jpg b/object_meta_programming_slides/slides/images/maintop.jpg new file mode 100644 index 0000000..ba801a9 Binary files /dev/null and b/object_meta_programming_slides/slides/images/maintop.jpg differ diff --git a/object_meta_programming_slides/slides/images/manimal.jpg b/object_meta_programming_slides/slides/images/manimal.jpg new file mode 100644 index 0000000..e7818b0 Binary files /dev/null and b/object_meta_programming_slides/slides/images/manimal.jpg differ diff --git a/object_meta_programming_slides/slides/images/microphone.jpg b/object_meta_programming_slides/slides/images/microphone.jpg new file mode 100644 index 0000000..0d8b99b Binary files /dev/null and b/object_meta_programming_slides/slides/images/microphone.jpg differ diff --git a/object_meta_programming_slides/slides/images/moose3sm.jpg b/object_meta_programming_slides/slides/images/moose3sm.jpg new file mode 100644 index 0000000..b363f0a Binary files /dev/null and b/object_meta_programming_slides/slides/images/moose3sm.jpg differ diff --git a/object_meta_programming_slides/slides/images/mushroomcloud-37024.jpg b/object_meta_programming_slides/slides/images/mushroomcloud-37024.jpg new file mode 100644 index 0000000..e08601b Binary files /dev/null and b/object_meta_programming_slides/slides/images/mushroomcloud-37024.jpg differ diff --git a/object_meta_programming_slides/slides/images/p-seal-at-toronto-zoo.jpg b/object_meta_programming_slides/slides/images/p-seal-at-toronto-zoo.jpg new file mode 100644 index 0000000..fd504ed Binary files /dev/null and b/object_meta_programming_slides/slides/images/p-seal-at-toronto-zoo.jpg differ diff --git a/object_meta_programming_slides/slides/images/p4v_revision_graph_6.gif b/object_meta_programming_slides/slides/images/p4v_revision_graph_6.gif new file mode 100644 index 0000000..ee5ba65 Binary files /dev/null and b/object_meta_programming_slides/slides/images/p4v_revision_graph_6.gif differ diff --git a/object_meta_programming_slides/slides/images/perl-camel.gif b/object_meta_programming_slides/slides/images/perl-camel.gif new file mode 100644 index 0000000..1c90410 Binary files /dev/null and b/object_meta_programming_slides/slides/images/perl-camel.gif differ diff --git a/object_meta_programming_slides/slides/images/perl6book-parody.gif b/object_meta_programming_slides/slides/images/perl6book-parody.gif new file mode 100644 index 0000000..e6a8f59 Binary files /dev/null and b/object_meta_programming_slides/slides/images/perl6book-parody.gif differ diff --git a/object_meta_programming_slides/slides/images/promopi.jpg b/object_meta_programming_slides/slides/images/promopi.jpg new file mode 100644 index 0000000..5260d15 Binary files /dev/null and b/object_meta_programming_slides/slides/images/promopi.jpg differ diff --git a/object_meta_programming_slides/slides/images/rocks.jpg b/object_meta_programming_slides/slides/images/rocks.jpg new file mode 100644 index 0000000..cf7e52f Binary files /dev/null and b/object_meta_programming_slides/slides/images/rocks.jpg differ diff --git a/object_meta_programming_slides/slides/images/snoqualmie-falls-flowing-3811-equalized.jpg b/object_meta_programming_slides/slides/images/snoqualmie-falls-flowing-3811-equalized.jpg new file mode 100644 index 0000000..e9db203 Binary files /dev/null and b/object_meta_programming_slides/slides/images/snoqualmie-falls-flowing-3811-equalized.jpg differ diff --git a/object_meta_programming_slides/slides/images/sugar.jpg b/object_meta_programming_slides/slides/images/sugar.jpg new file mode 100644 index 0000000..20c10e9 Binary files /dev/null and b/object_meta_programming_slides/slides/images/sugar.jpg differ diff --git a/object_meta_programming_slides/slides/images/telephone.jpg b/object_meta_programming_slides/slides/images/telephone.jpg new file mode 100644 index 0000000..5b55622 Binary files /dev/null and b/object_meta_programming_slides/slides/images/telephone.jpg differ diff --git a/object_meta_programming_slides/slides/images/thanks.jpg b/object_meta_programming_slides/slides/images/thanks.jpg new file mode 100644 index 0000000..04f78d4 Binary files /dev/null and b/object_meta_programming_slides/slides/images/thanks.jpg differ diff --git a/object_meta_programming_slides/slides/images/tip.gif b/object_meta_programming_slides/slides/images/tip.gif new file mode 100644 index 0000000..01d9b8e Binary files /dev/null and b/object_meta_programming_slides/slides/images/tip.gif differ diff --git a/object_meta_programming_slides/slides/images/trashcanc.gif b/object_meta_programming_slides/slides/images/trashcanc.gif new file mode 100644 index 0000000..a66a994 Binary files /dev/null and b/object_meta_programming_slides/slides/images/trashcanc.gif differ diff --git a/object_meta_programming_slides/slides/images/village_people.jpg b/object_meta_programming_slides/slides/images/village_people.jpg new file mode 100644 index 0000000..956a60a Binary files /dev/null and b/object_meta_programming_slides/slides/images/village_people.jpg differ diff --git a/object_meta_programming_slides/slides/images/vogue.jpg b/object_meta_programming_slides/slides/images/vogue.jpg new file mode 100644 index 0000000..6ad1211 Binary files /dev/null and b/object_meta_programming_slides/slides/images/vogue.jpg differ diff --git a/object_meta_programming_slides/slides/images/vtable.jpg b/object_meta_programming_slides/slides/images/vtable.jpg new file mode 100644 index 0000000..19f42e4 Binary files /dev/null and b/object_meta_programming_slides/slides/images/vtable.jpg differ diff --git a/object_meta_programming_slides/slides/start.html b/object_meta_programming_slides/slides/start.html new file mode 100644 index 0000000..c55532f --- /dev/null +++ b/object_meta_programming_slides/slides/start.html @@ -0,0 +1,6535 @@ +<!-- BEGIN s5 --> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> +<title>meta meta meta meta</title> +<meta name="generator" content="S5" /> +<meta name="version" content="S5 1.0" /> +<meta name="presdate" content="20041007" /> +<meta name="author" content="Eric A. Meyer" /> +<link rel="stylesheet" href="ui/slides.css" type="text/css" media="projection" id="slideProj" /> +<link rel="stylesheet" href="ui/opera.css" type="text/css" media="projection" id="operaFix" /> +<link rel="stylesheet" href="ui/print.css" type="text/css" media="print" id="slidePrint" /> +<script src="ui/slides.js" type="text/javascript"></script> +</head> +<body> + +<div class="layout"> + <div id="currentSlide"></div> + <div id="header"></div> + <div id="footer"> + <h2>×××× ×§××'××</h2> + <h2>nothingmuch@woobling.org</h2> + <div id="controls"></div> + </div> +</div> + +<div class="slide"> + <h1>Object Meta Programming</h1> + <h2>YAPC::EU::2007</h2> + <h3>Aug 29, 2007</h3> +</div> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/promopi.jpg" align=right> +<h1>HAI FRENDS</h1> +<p> + +</p> +<h2>My name is Yuval</h2> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/7104_Squares_with_Concentric_Circles_Kandinsky_Wassily.jpg" align=right> +<h1>Meta Programming</h1> +<p> + +</p> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/door.jpg" align=right> +<h1>Introduction</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/door.jpg" align=right> +<h1>Introduction</h1> +<p> + +</p> +<ul> +<li>Meta programming</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/door.jpg" align=right> +<h1>Introduction</h1> +<p> + +</p> +<ul> +<li>Meta programming</li> +<li>writing <em>code</em> which <em>outputs</em> or <em>manipulates</em> <em>code</em></li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/manimal.jpg" align=right> +<h1>Many forms</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/manimal.jpg" align=right> +<h1>Many forms</h1> +<p> + +</p> +<ul> +<li>string <tt>eval</tt></li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/manimal.jpg" align=right> +<h1>Many forms</h1> +<p> + +</p> +<ul> +<li>string <tt>eval</tt></li> +<li><tt>%::</tt></li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/manimal.jpg" align=right> +<h1>Many forms</h1> +<p> + +</p> +<ul> +<li>string <tt>eval</tt></li> +<li><tt>%::</tt></li> +<li>closure generators</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/manimal.jpg" align=right> +<h1>Many forms</h1> +<p> + +</p> +<ul> +<li>string <tt>eval</tt></li> +<li><tt>%::</tt></li> +<li>closure generators</li> +<li>macros</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/manimal.jpg" align=right> +<h1>Many forms</h1> +<p> + +</p> +<ul> +<li>string <tt>eval</tt></li> +<li><tt>%::</tt></li> +<li>closure generators</li> +<li>macros</li> +<li>real macros</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/manimal.jpg" align=right> +<h1>Many forms</h1> +<p> + +</p> +<ul> +<li>string <tt>eval</tt></li> +<li><tt>%::</tt></li> +<li>closure generators</li> +<li>macros</li> +<li>real macros</li> +<li>compilers</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Flying_Spaghetti_Monster-thumb.jpg" align=right> +<h1>Many forms</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Flying_Spaghetti_Monster-thumb.jpg" align=right> +<h1>Many forms</h1> +<p> + +</p> +<ul> +<li>Home grown snippets</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Flying_Spaghetti_Monster-thumb.jpg" align=right> +<h1>Many forms</h1> +<p> + +</p> +<ul> +<li>Home grown snippets</li> +<li>Home grown packages</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Flying_Spaghetti_Monster-thumb.jpg" align=right> +<h1>Many forms</h1> +<p> + +</p> +<ul> +<li>Home grown snippets</li> +<li>Home grown packages</li> +<li>Stuff on the CPAN (e.g. <tt>Class::Accessor</tt>, <tt>Code::Perl</tt>)</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Flying_Spaghetti_Monster-thumb.jpg" align=right> +<h1>Many forms</h1> +<p> + +</p> +<ul> +<li>Home grown snippets</li> +<li>Home grown packages</li> +<li>Stuff on the CPAN (e.g. <tt>Class::Accessor</tt>, <tt>Code::Perl</tt>)</li> +<li>Large systems (<tt>Template::Toolkit</tt>)</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/16_peer_pressure_smoking.gif" align=right> +<h1>Summary</h1> +<p> + +</p> +<ul> +<li>You should already know it</li> +<li>You probably do it</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/16_peer_pressure_smoking.gif" align=right> +<h1>Summary</h1> +<p> + +</p> +<ul> +<li>You should already know it</li> +<li>You probably do it</li> +<li>That's the intended audience anyway ;-)</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Object Meta Programming</h1> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Object Meta Programming</h1> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Object Meta Programming</h1> +<ul> +<li>Code that outputs or manipulates <em>object oriented code</em></li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Object Meta Programming</h1> +<ul> +<li>Code that outputs or manipulates <em>object oriented code</em></li> +<li>Often written in OO</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/ApplePieSlice.jpg" align=right> +<h1>Simple Examples</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/ApplePieSlice.jpg" align=right> +<h1>Simple Examples</h1> +<p> + +</p> +<ul> +<li><tt>Class::Accessor</tt>, <tt>Class::InsideOut</tt></li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/ApplePieSlice.jpg" align=right> +<h1>Simple Examples</h1> +<p> + +</p> +<ul> +<li><tt>Class::Accessor</tt>, <tt>Class::InsideOut</tt></li> + +<ul> +<li>Generates accessor methods</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/ApplePieSlice.jpg" align=right> +<h1>Simple Examples</h1> +<p> + +</p> +<ul> +<li><tt>Class::Accessor</tt>, <tt>Class::InsideOut</tt></li> + +<ul> +<li>Generates accessor methods</li> +</ul> +<li><tt>Class::Prototyped</tt></li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/ApplePieSlice.jpg" align=right> +<h1>Simple Examples</h1> +<p> + +</p> +<ul> +<li><tt>Class::Accessor</tt>, <tt>Class::InsideOut</tt></li> + +<ul> +<li>Generates accessor methods</li> +</ul> +<li><tt>Class::Prototyped</tt></li> + +<ul> +<li>Prototype object support in Perl</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/ApplePieSlice.jpg" align=right> +<h1>Simple Examples</h1> +<p> + +</p> +<ul> +<li><tt>Class::Accessor</tt>, <tt>Class::InsideOut</tt></li> + +<ul> +<li>Generates accessor methods</li> +</ul> +<li><tt>Class::Prototyped</tt></li> + +<ul> +<li>Prototype object support in Perl</li> +</ul> +<li>Lots of stuff on the CPAN</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vogue.jpg" align=right> +<h1>Modeling OO</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vogue.jpg" align=right> +<h1>Modeling OO</h1> +<p> + +</p> +<ul> +<li>High level object meta programming</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vogue.jpg" align=right> +<h1>Modeling OO</h1> +<p> + +</p> +<ul> +<li>High level object meta programming</li> + +<ul> +<li>The current trend</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vogue.jpg" align=right> +<h1>Modeling OO</h1> +<p> + +</p> +<ul> +<li>High level object meta programming</li> + +<ul> +<li>The current trend</li> +<li>The picture illustrates an object modelling with class =)</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vogue.jpg" align=right> +<h1>Modeling OO</h1> +<p> + +</p> +<ul> +<li>High level object meta programming</li> + +<ul> +<li>The current trend</li> +<li>The picture illustrates an object modelling with class =)</li> +<li>Seriously though...</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vogue.jpg" align=right> +<h1>Modeling OO</h1> +<p> + +</p> +<ul> +<li>High level object meta programming</li> +<li>What is a class?</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vogue.jpg" align=right> +<h1>Modeling OO</h1> +<p> + +</p> +<ul> +<li>High level object meta programming</li> +<li>What is a class?</li> +</ul> +<pre class="vim"> class Class { + has @isa; + has %methods; + has %attributes; + + ... + } +</pre> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vogue.jpg" align=right> +<h1>Modeling OO</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vogue.jpg" align=right> +<h1>Modeling OO</h1> +<p> + +</p> +<ul> +<li>Implementing OO</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vogue.jpg" align=right> +<h1>Modeling OO</h1> +<p> + +</p> +<ul> +<li>Implementing OO</li> + +<ul> +<li>In OO</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vogue.jpg" align=right> +<h1>Modeling OO</h1> +<p> + +</p> +<ul> +<li>Implementing OO</li> + +<ul> +<li>In OO</li> +</ul> +<li>Meta objects:</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vogue.jpg" align=right> +<h1>Modeling OO</h1> +<p> + +</p> +<ul> +<li>Implementing OO</li> + +<ul> +<li>In OO</li> +</ul> +<li>Meta objects:</li> + +<ul> +<li>Class</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vogue.jpg" align=right> +<h1>Modeling OO</h1> +<p> + +</p> +<ul> +<li>Implementing OO</li> + +<ul> +<li>In OO</li> +</ul> +<li>Meta objects:</li> + +<ul> +<li>Class</li> +<li>Method</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vogue.jpg" align=right> +<h1>Modeling OO</h1> +<p> + +</p> +<ul> +<li>Implementing OO</li> + +<ul> +<li>In OO</li> +</ul> +<li>Meta objects:</li> + +<ul> +<li>Class</li> +<li>Method</li> +<li>Attribute</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Example class</h1> +<pre class="vim"> class Point { + has $x; + has $y; + + method distance_to { ... } + } +</pre> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Modeled with objects</h1> +<pre class="vim"> Class-><span class="synStatement">new</span>( + <span class="synConstant">attributes </span>=> [ + Attribute-><span class="synStatement">new</span>( <span class="synConstant">name </span>=> <span class="synConstant">'$x'</span> ), + Attribute-><span class="synStatement">new</span>( <span class="synConstant">name </span>=> <span class="synConstant">'$y'</span> ), + ], + <span class="synConstant">methods </span>=> [ + Method-><span class="synStatement">new</span>( + <span class="synConstant">name </span>=> <span class="synConstant">"distance_to"</span>, + <span class="synConstant">definition </span>=><span class="synIdentifier"> </span><span class="synStatement">sub</span><span class="synIdentifier"> </span>{ ... } + ), + ], + ); +</pre> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_944779_reception_bell.jpg" align=right> +<h1>Metamodel Services</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_944779_reception_bell.jpg" align=right> +<h1>Metamodel Services</h1> +<p> + +</p> +<ul> +<li>Form</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_944779_reception_bell.jpg" align=right> +<h1>Metamodel Services</h1> +<p> + +</p> +<ul> +<li>Form</li> + +<ul> +<li>Introspection/Reflection</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_944779_reception_bell.jpg" align=right> +<h1>Metamodel Services</h1> +<p> + +</p> +<ul> +<li>Form</li> + +<ul> +<li>Introspection/Reflection</li> +</ul> +<li>Function</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_944779_reception_bell.jpg" align=right> +<h1>Metamodel Services</h1> +<p> + +</p> +<ul> +<li>Form</li> + +<ul> +<li>Introspection/Reflection</li> +</ul> +<li>Function</li> + +<ul> +<li>Class generation</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_944779_reception_bell.jpg" align=right> +<h1>Metamodel Services</h1> +<p> + +</p> +<ul> +<li>Form</li> + +<ul> +<li>Introspection/Reflection</li> +</ul> +<li>Function</li> + +<ul> +<li>Class generation</li> +<li>Class transformation</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_944779_reception_bell.jpg" align=right> +<h1>Metamodel Services</h1> +<p> + +</p> +<ul> +<li>Form</li> + +<ul> +<li>Introspection/Reflection</li> +</ul> +<li>Function</li> + +<ul> +<li>Class generation</li> +<li>Class transformation</li> +</ul> +<li>Pattern packaging</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/a_moose.gif" align=right> +<h1>Case Study</h1> +<p> + +</p> +<h2>Moose</h2> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/a_moose.gif" align=right> +<h1>Case Study</h1> +<p> + +</p> +<h2>Moose</h2> +<ul> +<li>A deep meta object system</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/a_moose.gif" align=right> +<h1>Case Study</h1> +<p> + +</p> +<h2>Moose</h2> +<ul> +<li>A deep meta object system</li> +<li>4 layers deep</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/a_moose.gif" align=right> +<h1>Case Study</h1> +<p> + +</p> +<h2>Moose</h2> +<ul> +<li>A deep meta object system</li> +<li>4 layers deep</li> + +<ul> +<li>Syntactic sugar</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/a_moose.gif" align=right> +<h1>Case Study</h1> +<p> + +</p> +<h2>Moose</h2> +<ul> +<li>A deep meta object system</li> +<li>4 layers deep</li> + +<ul> +<li>Syntactic sugar</li> +<li>Custom metaclasses</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/a_moose.gif" align=right> +<h1>Case Study</h1> +<p> + +</p> +<h2>Moose</h2> +<ul> +<li>A deep meta object system</li> +<li>4 layers deep</li> + +<ul> +<li>Syntactic sugar</li> +<li>Custom metaclasses</li> +<li>Class::MOP</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/a_moose.gif" align=right> +<h1>Case Study</h1> +<p> + +</p> +<h2>Moose</h2> +<ul> +<li>A deep meta object system</li> +<li>4 layers deep</li> + +<ul> +<li>Syntactic sugar</li> +<li>Custom metaclasses</li> +<li>Class::MOP</li> +<li>Perl's native OO</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/perl-camel.gif" align=right> +<h1>Perl's native OO</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/perl-camel.gif" align=right> +<h1>Perl's native OO</h1> +<p> + +</p> +<ul> +<li>Minimalistic</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/perl-camel.gif" align=right> +<h1>Perl's native OO</h1> +<p> + +</p> +<ul> +<li>Minimalistic</li> + +<ul> +<li>Class = Package = Symbol table hash</li> +<li>Inheritence tree embedded in <tt>@ISA</tt> entry</li> +<li><tt>bless</tt> links data to a class</li> +<li><tt>-></tt></li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/perl-camel.gif" align=right> +<h1>Perl's native OO</h1> +<p> + +</p> +<ul> +<li>Minimalistic</li> + +<ul> +<li>Class = Package = Symbol table hash</li> +<li>Inheritence tree embedded in <tt>@ISA</tt> entry</li> +<li><tt>bless</tt> links data to a class</li> +<li><tt>-></tt></li> +</ul> +<li>Insanely flexible</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/perl-camel.gif" align=right> +<h1>Perl's native OO</h1> +<p> + +</p> +<ul> +<li>Minimalistic</li> + +<ul> +<li>Class = Package = Symbol table hash</li> +<li>Inheritence tree embedded in <tt>@ISA</tt> entry</li> +<li><tt>bless</tt> links data to a class</li> +<li><tt>-></tt></li> +</ul> +<li>Insanely flexible</li> +<li>Pretty klunky</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/perl-camel.gif" align=right> +<h1>Perl's native OO</h1> +<p> + +</p> +<ul> +<li>Minimalistic</li> + +<ul> +<li>Class = Package = Symbol table hash</li> +<li>Inheritence tree embedded in <tt>@ISA</tt> entry</li> +<li><tt>bless</tt> links data to a class</li> +<li><tt>-></tt></li> +</ul> +<li>Insanely flexible</li> +<li>Pretty klunky</li> +<li>Written in C (not very accessible)</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MOP.jpg" align=right> +<h1>Class::MOP</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MOP.jpg" align=right> +<h1>Class::MOP</h1> +<p> + +</p> +<ul> +<li>port of CLOS, more or less</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MOP.jpg" align=right> +<h1>Class::MOP</h1> +<p> + +</p> +<ul> +<li>port of CLOS, more or less</li> +<li>MOP = Meta Object Protocol</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MOP.jpg" align=right> +<h1>Class::MOP</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MOP.jpg" align=right> +<h1>Class::MOP</h1> +<p> + +</p> +<ul> +<li>Model</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MOP.jpg" align=right> +<h1>Class::MOP</h1> +<p> + +</p> +<ul> +<li>Model</li> + +<ul> +<li><tt>Class::MOP::Class</tt></li> +<li><tt>Class::MOP::Method</tt></li> +<li><tt>Class::MOP::Attribute</tt></li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MOP.jpg" align=right> +<h1>Class::MOP</h1> +<p> + +</p> +<ul> +<li>Model</li> + +<ul> +<li><tt>Class::MOP::Class</tt></li> +<li><tt>Class::MOP::Method</tt></li> +<li><tt>Class::MOP::Attribute</tt></li> +</ul> +<li>Easy interface</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MOP.jpg" align=right> +<h1>Class::MOP</h1> +<p> + +</p> +<ul> +<li>Model</li> + +<ul> +<li><tt>Class::MOP::Class</tt></li> +<li><tt>Class::MOP::Method</tt></li> +<li><tt>Class::MOP::Attribute</tt></li> +</ul> +<li>Easy interface</li> + +<ul> +<li>Introspection</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MOP.jpg" align=right> +<h1>Class::MOP</h1> +<p> + +</p> +<ul> +<li>Model</li> + +<ul> +<li><tt>Class::MOP::Class</tt></li> +<li><tt>Class::MOP::Method</tt></li> +<li><tt>Class::MOP::Attribute</tt></li> +</ul> +<li>Easy interface</li> + +<ul> +<li>Introspection</li> +<li>Transformation</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MOP.jpg" align=right> +<h1>Class::MOP</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MOP.jpg" align=right> +<h1>Class::MOP</h1> +<p> + +</p> +<ul> +<li>Can "parse" packages into meta objects</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MOP.jpg" align=right> +<h1>Class::MOP</h1> +<p> + +</p> +<ul> +<li>Can "parse" packages into meta objects</li> +<li>Modifying the objects writes back to packages</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MOP.jpg" align=right> +<h1>Class::MOP</h1> +<p> + +</p> +<ul> +<li>Can "parse" packages into meta objects</li> +<li>Modifying the objects writes back to packages</li> +<li>Code generation</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MOP.jpg" align=right> +<h1>Class::MOP</h1> +<p> + +</p> +<ul> +<li>Can "parse" packages into meta objects</li> +<li>Modifying the objects writes back to packages</li> +<li>Code generation</li> + +<ul> +<li>Accessors from attributes</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MOP.jpg" align=right> +<h1>Class::MOP</h1> +<p> + +</p> +<ul> +<li>Can "parse" packages into meta objects</li> +<li>Modifying the objects writes back to packages</li> +<li>Code generation</li> + +<ul> +<li>Accessors from attributes</li> +<li>Constructor from attributes</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MOP.jpg" align=right> +<h1>Class::MOP</h1> +<p> + +</p> +<ul> +<li>Can "parse" packages into meta objects</li> +<li>Modifying the objects writes back to packages</li> +<li>Code generation</li> + +<ul> +<li>Accessors from attributes</li> +<li>Constructor from attributes</li> +<li>Method modifiers</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/a_moose.gif" align=right> +<h1>Moose's custom metaclasses</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/a_moose.gif" align=right> +<h1>Moose's custom metaclasses</h1> +<p> + +</p> +<ul> +<li>Subclasses of <tt>Class::MOP::Class</tt> et al</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/a_moose.gif" align=right> +<h1>Moose's custom metaclasses</h1> +<p> + +</p> +<ul> +<li>Subclasses of <tt>Class::MOP::Class</tt> et al</li> +<li>More fun features</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/a_moose.gif" align=right> +<h1>Moose's custom metaclasses</h1> +<p> + +</p> +<ul> +<li>Subclasses of <tt>Class::MOP::Class</tt> et al</li> +<li>More fun features</li> + +<ul> +<li>Roles</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/a_moose.gif" align=right> +<h1>Moose's custom metaclasses</h1> +<p> + +</p> +<ul> +<li>Subclasses of <tt>Class::MOP::Class</tt> et al</li> +<li>More fun features</li> + +<ul> +<li>Roles</li> +<li><tt>BUILD</tt> etc a la Perl 6</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/a_moose.gif" align=right> +<h1>Moose's custom metaclasses</h1> +<p> + +</p> +<ul> +<li>Subclasses of <tt>Class::MOP::Class</tt> et al</li> +<li>More fun features</li> + +<ul> +<li>Roles</li> +<li><tt>BUILD</tt> etc a la Perl 6</li> +</ul> +<li>Type constraints</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/sugar.jpg" align=right> +<h1>Moose sugar layer</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/sugar.jpg" align=right> +<h1>Moose sugar layer</h1> +<p> + +</p> +<ul> +<li>Pseudo-declarative syntax</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/sugar.jpg" align=right> +<h1>Moose sugar layer</h1> +<p> + +</p> +<ul> +<li>Pseudo-declarative syntax</li> +<li>Maps to metaclass manipulations</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/sugar.jpg" align=right> +<h1>Moose sugar layer</h1> +<p> + +</p> +<ul> +<li>Pseudo-declarative syntax</li> +<li>Maps to metaclass manipulations</li> +</ul> +<pre class="vim"> has foo => ( is => "rw" ); +</pre> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/sugar.jpg" align=right> +<h1>Moose sugar layer</h1> +<p> + +</p> +<ul> +<li>Pseudo-declarative syntax</li> +<li>Maps to metaclass manipulations</li> +</ul> +<pre class="vim"> has foo => ( is => "rw" ); +</pre> +<ul> +<li>becomes</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/sugar.jpg" align=right> +<h1>Moose sugar layer</h1> +<p> + +</p> +<ul> +<li>Pseudo-declarative syntax</li> +<li>Maps to metaclass manipulations</li> +</ul> +<pre class="vim"> has foo => ( is => "rw" ); +</pre> +<ul> +<li>becomes</li> +</ul> +<pre class="vim"> $metaclass->add_attribute( + Moose::Meta::Attribute->new( + foo => ( is => "rw" ), + ) + ); +</pre> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/p-seal-at-toronto-zoo.jpg" align=right> +<h1>Moose vs. Class::Accessor</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/p-seal-at-toronto-zoo.jpg" align=right> +<h1>Moose vs. Class::Accessor</h1> +<p> + +</p> +<ul> +<li>All that bloat just for the <tt>has</tt> syntax?</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/p-seal-at-toronto-zoo.jpg" align=right> +<h1>Moose vs. Class::Accessor</h1> +<p> + +</p> +<ul> +<li>All that bloat just for the <tt>has</tt> syntax?</li> +<li><strong>NO!</strong></li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/p-seal-at-toronto-zoo.jpg" align=right> +<h1>Moose vs. Class::Accessor</h1> +<p> + +</p> +<ul> +<li>All that bloat just for the <tt>has</tt> syntax?</li> +<li><strong>NO!</strong></li> +<li>Pattern packaging</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/401.jpg" align=right> +<h1>MooseX::</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/401.jpg" align=right> +<h1>MooseX::</h1> +<p> + +</p> +<ul> +<li>Packaged meta code</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/401.jpg" align=right> +<h1>MooseX::</h1> +<p> + +</p> +<ul> +<li>Packaged meta code</li> +<li>Pretty clean</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/401.jpg" align=right> +<h1>MooseX::</h1> +<p> + +</p> +<ul> +<li>Packaged meta code</li> +<li>Pretty clean</li> +<li>Mostly composable</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/401.jpg" align=right> +<h1>MooseX::</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/401.jpg" align=right> +<h1>MooseX::</h1> +<p> + +</p> +<ul> +<li><tt>MooseX::Storage</tt></li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/401.jpg" align=right> +<h1>MooseX::</h1> +<p> + +</p> +<ul> +<li><tt>MooseX::Storage</tt></li> + +<ul> +<li>Customizable serialization through metaprogramming</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/401.jpg" align=right> +<h1>MooseX::</h1> +<p> + +</p> +<ul> +<li><tt>MooseX::Storage</tt></li> + +<ul> +<li>Customizable serialization through metaprogramming</li> +</ul> +<li><tt>MooseX::AttributeHelpers</tt></li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/401.jpg" align=right> +<h1>MooseX::</h1> +<p> + +</p> +<ul> +<li><tt>MooseX::Storage</tt></li> + +<ul> +<li>Customizable serialization through metaprogramming</li> +</ul> +<li><tt>MooseX::AttributeHelpers</tt></li> + +<ul> +<li>Additional methods for collection type attributes</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/401.jpg" align=right> +<h1>MooseX::</h1> +<p> + +</p> +<ul> +<li><tt>MooseX::Storage</tt></li> + +<ul> +<li>Customizable serialization through metaprogramming</li> +</ul> +<li><tt>MooseX::AttributeHelpers</tt></li> + +<ul> +<li>Additional methods for collection type attributes</li> +</ul> +<li><tt>MooseX::Getopt</tt></li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/401.jpg" align=right> +<h1>MooseX::</h1> +<p> + +</p> +<ul> +<li><tt>MooseX::Storage</tt></li> + +<ul> +<li>Customizable serialization through metaprogramming</li> +</ul> +<li><tt>MooseX::AttributeHelpers</tt></li> + +<ul> +<li>Additional methods for collection type attributes</li> +</ul> +<li><tt>MooseX::Getopt</tt></li> + +<ul> +<li>Additional constructor compiles attributes into a <tt>Getopt</tt> spec</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/401.jpg" align=right> +<h1>MooseX::</h1> +<p> + +</p> +<ul> +<li><tt>MooseX::Storage</tt></li> + +<ul> +<li>Customizable serialization through metaprogramming</li> +</ul> +<li><tt>MooseX::AttributeHelpers</tt></li> + +<ul> +<li>Additional methods for collection type attributes</li> +</ul> +<li><tt>MooseX::Getopt</tt></li> + +<ul> +<li>Additional constructor compiles attributes into a <tt>Getopt</tt> spec</li> +</ul> +<li><tt>MooseX::IOC</tt></li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/401.jpg" align=right> +<h1>MooseX::</h1> +<p> + +</p> +<ul> +<li><tt>MooseX::Storage</tt></li> + +<ul> +<li>Customizable serialization through metaprogramming</li> +</ul> +<li><tt>MooseX::AttributeHelpers</tt></li> + +<ul> +<li>Additional methods for collection type attributes</li> +</ul> +<li><tt>MooseX::Getopt</tt></li> + +<ul> +<li>Additional constructor compiles attributes into a <tt>Getopt</tt> spec</li> +</ul> +<li><tt>MooseX::IOC</tt></li> + +<ul> +<li>Inversion of control integrated into the object system</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/cute_moose.jpg" align=right> +<h1>The point of Moose</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/cute_moose.jpg" align=right> +<h1>The point of Moose</h1> +<p> + +</p> +<ul> +<li>OO is less tedious</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/cute_moose.jpg" align=right> +<h1>The point of Moose</h1> +<p> + +</p> +<ul> +<li>OO is less tedious</li> +<li>Helps you write meta code</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/cute_moose.jpg" align=right> +<h1>The point of Moose</h1> +<p> + +</p> +<ul> +<li>OO is less tedious</li> +<li>Helps you write meta code</li> + +<ul> +<li>Good APIs promote clean code</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/cute_moose.jpg" align=right> +<h1>The point of Moose</h1> +<p> + +</p> +<ul> +<li>OO is less tedious</li> +<li>Helps you write meta code</li> + +<ul> +<li>Good APIs promote clean code</li> +<li>Easier to build on existing base</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/cute_moose.jpg" align=right> +<h1>The point of Moose</h1> +<p> + +</p> +<ul> +<li>OO is less tedious</li> +<li>Helps you write meta code</li> + +<ul> +<li>Good APIs promote clean code</li> +<li>Easier to build on existing base</li> +<li>Conventions and structure let you play well with others (<tt>MooseX::</tt>)</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/cute_moose.jpg" align=right> +<h1>The point of Moose</h1> +<p> + +</p> +<ul> +<li>OO is less tedious</li> +<li>Helps you write meta code</li> + +<ul> +<li>Good APIs promote clean code</li> +<li>Easier to build on existing base</li> +<li>Conventions and structure let you play well with others (<tt>MooseX::</tt>)</li> +<li>Introspectable & tranformable metamodel</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MainHeaderPic_5.gif" align=right> +<h1>Another Case Study</h1> +<p> + +</p> +<h2>ORMs</h2> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MainHeaderPic_5.gif" align=right> +<h1>Another Case Study</h1> +<p> + +</p> +<h2>ORMs</h2> +<ul> +<li>Are <strong>HARD</strong></li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/MainHeaderPic_5.gif" align=right> +<h1>Another Case Study</h1> +<p> + +</p> +<h2>ORMs</h2> +<ul> +<li>Are <strong>HARD</strong></li> +<li>Not even fun like the picture</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/legacyDataSources.jpg" align=right> +<h1>ORMs</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/legacyDataSources.jpg" align=right> +<h1>ORMs</h1> +<p> + +</p> +<ul> +<li>Modeling</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/legacyDataSources.jpg" align=right> +<h1>ORMs</h1> +<p> + +</p> +<ul> +<li>Modeling</li> + +<ul> +<li>Tables <-> Classes</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/legacyDataSources.jpg" align=right> +<h1>ORMs</h1> +<p> + +</p> +<ul> +<li>Modeling</li> + +<ul> +<li>Tables <-> Classes</li> +<li>Fields <-> Attributes</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/legacyDataSources.jpg" align=right> +<h1>ORMs</h1> +<p> + +</p> +<ul> +<li>Modeling</li> + +<ul> +<li>Tables <-> Classes</li> +<li>Fields <-> Attributes</li> +</ul> +<li>Code Generation</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/legacyDataSources.jpg" align=right> +<h1>ORMs</h1> +<p> + +</p> +<ul> +<li>Modeling</li> + +<ul> +<li>Tables <-> Classes</li> +<li>Fields <-> Attributes</li> +</ul> +<li>Code Generation</li> + +<ul> +<li>SQL</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/legacyDataSources.jpg" align=right> +<h1>ORMs</h1> +<p> + +</p> +<ul> +<li>Modeling</li> + +<ul> +<li>Tables <-> Classes</li> +<li>Fields <-> Attributes</li> +</ul> +<li>Code Generation</li> + +<ul> +<li>SQL</li> +<li>Accessors</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/legacyDataSources.jpg" align=right> +<h1>ORMs</h1> +<p> + +</p> +<ul> +<li>Modeling</li> + +<ul> +<li>Tables <-> Classes</li> +<li>Fields <-> Attributes</li> +</ul> +<li>Code Generation</li> + +<ul> +<li>SQL</li> +<li>Accessors</li> +<li>Relationship fetchers</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1><tt>Class::DBI</tt></h1> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1><tt>Class::DBI</tt></h1> +<ul> +<li>Meta code is in the base class</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1><tt>Class::DBI</tt></h1> +<ul> +<li>Meta code is in the base class</li> +<li>No clear schema modelling</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1><tt>Class::DBI</tt></h1> +<ul> +<li>Meta code is in the base class</li> +<li>No clear schema modelling</li> +<li>No separation between regular & meta code</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1><tt>Class::DBI</tt></h1> +<ul> +<li>Meta code is in the base class</li> +<li>No clear schema modelling</li> +<li>No separation between regular & meta code</li> +<li>Lots of hacks</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1><tt>Class::DBI</tt></h1> +<ul> +<li>Meta code is in the base class</li> +<li>No clear schema modelling</li> +<li>No separation between regular & meta code</li> +<li>Lots of hacks</li> +<li>Don't go there</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1><tt>DBIx::Class</tt></h1> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1><tt>DBIx::Class</tt></h1> +<ul> +<li>Meta enlightened</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1><tt>DBIx::Class</tt></h1> +<ul> +<li>Meta enlightened</li> + +<ul> +<li>Schema objects fully model the SQL side</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1><tt>DBIx::Class</tt></h1> +<ul> +<li>Meta enlightened</li> + +<ul> +<li>Schema objects fully model the SQL side</li> +<li>ResultSource etc partially model the OO side</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1><tt>DBIx::Class</tt></h1> +<ul> +<li>Meta enlightened</li> + +<ul> +<li>Schema objects fully model the SQL side</li> +<li>ResultSource etc partially model the OO side</li> +<li>Components for everything</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1><tt>DBIx::Class</tt></h1> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1><tt>DBIx::Class</tt></h1> +<ul> +<li>Meta code:</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1><tt>DBIx::Class</tt></h1> +<ul> +<li>Meta code:</li> + +<ul> +<li>Proxy objects</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1><tt>DBIx::Class</tt></h1> +<ul> +<li>Meta code:</li> + +<ul> +<li>Proxy objects</li> +<li>Accessors</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1><tt>DBIx::Class</tt></h1> +<ul> +<li>Meta code:</li> + +<ul> +<li>Proxy objects</li> +<li>Accessors</li> +<li>Code generation (SQL, Perl)</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>ORM related meta programming</h1> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>ORM related meta programming</h1> +<ul> +<li>Complex</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>ORM related meta programming</h1> +<ul> +<li>Complex</li> +<li>But manageable</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/b-silencer-water-vapour.jpg" align=right> +<h1>Vaporware</h1> +<p> + +</p> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/b-silencer-water-vapour.jpg" align=right> +<h1>MO</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/b-silencer-water-vapour.jpg" align=right> +<h1>MO</h1> +<p> + +</p> +<ul> +<li>My baby</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/b-silencer-water-vapour.jpg" align=right> +<h1>MO</h1> +<p> + +</p> +<ul> +<li>My baby</li> +<li>Moose spinoff</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/b-silencer-water-vapour.jpg" align=right> +<h1>MO</h1> +<p> + +</p> +<ul> +<li>My baby</li> +<li>Moose spinoff</li> + +<ul> +<li>Stevan says it's Moose 2.0's</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/b-silencer-water-vapour.jpg" align=right> +<h1>MO</h1> +<p> + +</p> +<ul> +<li>My baby</li> +<li>Moose spinoff</li> + +<ul> +<li>Stevan says it's Moose 2.0's</li> +</ul> +<li>Perl 5 & Haskell (in pugs)</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lollypop.jpg" align=right> +<h1>MO Sucks</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lollypop.jpg" align=right> +<h1>MO Sucks</h1> +<p> + +</p> +<ul> +<li>Experimental code</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lollypop.jpg" align=right> +<h1>MO Sucks</h1> +<p> + +</p> +<ul> +<li>Experimental code</li> +<li>Boring parts messy or unwritten</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lollypop.jpg" align=right> +<h1>MO Sucks</h1> +<p> + +</p> +<ul> +<li>Experimental code</li> +<li>Boring parts messy or unwritten</li> +<li>Lacking integration, sugar layer</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lollypop.jpg" align=right> +<h1>MO Sucks</h1> +<p> + +</p> +<ul> +<li>Experimental code</li> +<li>Boring parts messy or unwritten</li> +<li>Lacking integration, sugar layer</li> + +<ul> +<li>mst promised to help ;-)</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lollypop.jpg" align=right> +<h1>MO Sucks</h1> +<p> + +</p> +<ul> +<li>Experimental code</li> +<li>Boring parts messy or unwritten</li> +<li>Lacking integration, sugar layer</li> + +<ul> +<li>mst promised to help ;-)</li> +</ul> +<li>Some parts slow as $*!&%</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/rocks.jpg" align=right> +<h1>MO Rocks</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/rocks.jpg" align=right> +<h1>MO Rocks</h1> +<p> + +</p> +<ul> +<li>Purely functional</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/rocks.jpg" align=right> +<h1>MO Rocks</h1> +<p> + +</p> +<ul> +<li>Purely functional</li> +<li>Very suited for meta transformations</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/rocks.jpg" align=right> +<h1>MO Rocks</h1> +<p> + +</p> +<ul> +<li>Purely functional</li> +<li>Very suited for meta transformations</li> +<li>Fine grained control over everything</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/rocks.jpg" align=right> +<h1>MO Rocks</h1> +<p> + +</p> +<ul> +<li>Purely functional</li> +<li>Very suited for meta transformations</li> +<li>Fine grained control over everything</li> +<li>Can introduce entirely new conceptions of OO</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/engineering_large.jpg" align=right> +<h1>MO Architechture</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/engineering_large.jpg" align=right> +<h1>MO Architechture</h1> +<p> + +</p> +<ul> +<li>Modeling layer</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/engineering_large.jpg" align=right> +<h1>MO Architechture</h1> +<p> + +</p> +<ul> +<li>Modeling layer</li> + +<ul> +<li>Corresponds to compilation</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/engineering_large.jpg" align=right> +<h1>MO Architechture</h1> +<p> + +</p> +<ul> +<li>Modeling layer</li> + +<ul> +<li>Corresponds to compilation</li> +</ul> +<li>Responder layer</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/engineering_large.jpg" align=right> +<h1>MO Architechture</h1> +<p> + +</p> +<ul> +<li>Modeling layer</li> + +<ul> +<li>Corresponds to compilation</li> +</ul> +<li>Responder layer</li> + +<ul> +<li>Corresponds to runtime</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/engineering_large.jpg" align=right> +<h1>MO Architechture</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/engineering_large.jpg" align=right> +<h1>MO Architechture</h1> +<p> + +</p> +<ul> +<li>Compiler/sugar layer creates the modeling layer</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/engineering_large.jpg" align=right> +<h1>MO Architechture</h1> +<p> + +</p> +<ul> +<li>Compiler/sugar layer creates the modeling layer</li> + +<ul> +<li>Class objects are constructed, with all the details</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/engineering_large.jpg" align=right> +<h1>MO Architechture</h1> +<p> + +</p> +<ul> +<li>Compiler/sugar layer creates the modeling layer</li> + +<ul> +<li>Class objects are constructed, with all the details</li> +<li>No meta calculations happen yet</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/engineering_large.jpg" align=right> +<h1>MO Architechture</h1> +<p> + +</p> +<ul> +<li>Compiler/sugar layer creates the modeling layer</li> + +<ul> +<li>Class objects are constructed, with all the details</li> +<li>No meta calculations happen yet</li> +</ul> +<li>Modeling layer is "compiled" into responder layer</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/engineering_large.jpg" align=right> +<h1>MO Architechture</h1> +<p> + +</p> +<ul> +<li>Compiler/sugar layer creates the modeling layer</li> + +<ul> +<li>Class objects are constructed, with all the details</li> +<li>No meta calculations happen yet</li> +</ul> +<li>Modeling layer is "compiled" into responder layer</li> + +<ul> +<li>Can be done on demand or upfront</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/engineering_large.jpg" align=right> +<h1>MO Architechture</h1> +<p> + +</p> +<ul> +<li>Compiler/sugar layer creates the modeling layer</li> + +<ul> +<li>Class objects are constructed, with all the details</li> +<li>No meta calculations happen yet</li> +</ul> +<li>Modeling layer is "compiled" into responder layer</li> + +<ul> +<li>Can be done on demand or upfront</li> +</ul> +<li>Obscurely named objects</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/engineering_large.jpg" align=right> +<h1>MO Architechture</h1> +<p> + +</p> +<ul> +<li>Compiler/sugar layer creates the modeling layer</li> + +<ul> +<li>Class objects are constructed, with all the details</li> +<li>No meta calculations happen yet</li> +</ul> +<li>Modeling layer is "compiled" into responder layer</li> + +<ul> +<li>Can be done on demand or upfront</li> +</ul> +<li>Obscurely named objects</li> + +<ul> +<li>Bear with me</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/light-bulb-glowing-filament-light-blue-uncropped-lores-3-AHD.jpg" align=right> +<h1>"Concepts"</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/light-bulb-glowing-filament-light-blue-uncropped-lores-3-AHD.jpg" align=right> +<h1>"Concepts"</h1> +<p> + +</p> +<ul> +<li>The purest form of OO is prototypes</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/light-bulb-glowing-filament-light-blue-uncropped-lores-3-AHD.jpg" align=right> +<h1>"Concepts"</h1> +<p> + +</p> +<ul> +<li>The purest form of OO is prototypes</li> + +<ul> +<li>prototype OO can implement class OO</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/light-bulb-glowing-filament-light-blue-uncropped-lores-3-AHD.jpg" align=right> +<h1>"Concepts"</h1> +<p> + +</p> +<ul> +<li>The purest form of OO is prototypes</li> + +<ul> +<li>prototype OO can implement class OO</li> +</ul> +<li>Concepts are new ways to express objects</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/light-bulb-glowing-filament-light-blue-uncropped-lores-3-AHD.jpg" align=right> +<h1>"Concepts"</h1> +<p> + +</p> +<ul> +<li>The purest form of OO is prototypes</li> + +<ul> +<li>prototype OO can implement class OO</li> +</ul> +<li>Concepts are new ways to express objects</li> +<li>A class is a concept</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/light-bulb-glowing-filament-light-blue-uncropped-lores-3-AHD.jpg" align=right> +<h1>"Concepts"</h1> +<p> + +</p> +<ul> +<li>The purest form of OO is prototypes</li> + +<ul> +<li>prototype OO can implement class OO</li> +</ul> +<li>Concepts are new ways to express objects</li> +<li>A class is a concept</li> +<li>A role is a concept</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vtable.jpg" align=right> +<h1>"Responder Interfaces"</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vtable.jpg" align=right> +<h1>"Responder Interfaces"</h1> +<p> + +</p> +<ul> +<li><tt>$ri->dispatch( $responder, $invocation )</tt></li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vtable.jpg" align=right> +<h1>"Responder Interfaces"</h1> +<p> + +</p> +<ul> +<li><tt>$ri->dispatch( $responder, $invocation )</tt></li> +<li>Generated from concepts</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vtable.jpg" align=right> +<h1>"Responder Interfaces"</h1> +<p> + +</p> +<ul> +<li><tt>$ri->dispatch( $responder, $invocation )</tt></li> +<li>Generated from concepts</li> +<li>Abstract VTable</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vtable.jpg" align=right> +<h1>"Responder Interfaces"</h1> +<p> + +</p> +<ul> +<li><tt>$ri->dispatch( $responder, $invocation )</tt></li> +<li>Generated from concepts</li> +<li>Abstract VTable</li> + +<ul> +<li>The flattened method hierarchy</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vtable.jpg" align=right> +<h1>"Responder Interfaces"</h1> +<p> + +</p> +<ul> +<li><tt>$ri->dispatch( $responder, $invocation )</tt></li> +<li>Generated from concepts</li> +<li>Abstract VTable</li> + +<ul> +<li>The flattened method hierarchy</li> +<li>... or something completely different</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vtable.jpg" align=right> +<h1>"Responder Interfaces"</h1> +<p> + +</p> +<ul> +<li><tt>$ri->dispatch( $responder, $invocation )</tt></li> +<li>Generated from concepts</li> +<li>Abstract VTable</li> + +<ul> +<li>The flattened method hierarchy</li> +<li>... or something completely different</li> +<li>Performance</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/vtable.jpg" align=right> +<h1>"Responder Interfaces"</h1> +<p> + +</p> +<ul> +<li><tt>$ri->dispatch( $responder, $invocation )</tt></li> +<li>Generated from concepts</li> +<li>Abstract VTable</li> + +<ul> +<li>The flattened method hierarchy</li> +<li>... or something completely different</li> +<li>Performance</li> +<li>Flexibility</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/fema_seal.gif" align=right> +<h1>"Responders"</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/fema_seal.gif" align=right> +<h1>"Responders"</h1> +<p> + +</p> +<ul> +<li>Something that is the subject of invocations</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/fema_seal.gif" align=right> +<h1>"Responders"</h1> +<p> + +</p> +<ul> +<li>Something that is the subject of invocations</li> + +<ul> +<li>An object instance</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/fema_seal.gif" align=right> +<h1>"Responders"</h1> +<p> + +</p> +<ul> +<li>Something that is the subject of invocations</li> + +<ul> +<li>An object instance</li> +<li>A class (class methods)</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/fema_seal.gif" align=right> +<h1>"Responders"</h1> +<p> + +</p> +<ul> +<li>Something that is the subject of invocations</li> + +<ul> +<li>An object instance</li> +<li>A class (class methods)</li> +</ul> +<li>A simple tuple <tt>( $data, $ri )</tt></li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lg-banana.jpg" align=right> +<h1>"Invocations"</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lg-banana.jpg" align=right> +<h1>"Invocations"</h1> +<p> + +</p> +<ul> +<li>A method call, multimethod, message... whatever</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lg-banana.jpg" align=right> +<h1>"Invocations"</h1> +<p> + +</p> +<ul> +<li>A method call, multimethod, message... whatever</li> + +<ul> +<li>Arguments, too</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lg-banana.jpg" align=right> +<h1>"Invocations"</h1> +<p> + +</p> +<ul> +<li>A method call, multimethod, message... whatever</li> + +<ul> +<li>Arguments, too</li> +</ul> +<li>Whatever an RI will put up with</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lg-banana.jpg" align=right> +<h1>"Invocations"</h1> +<p> + +</p> +<ul> +<li>A method call, multimethod, message... whatever</li> + +<ul> +<li>Arguments, too</li> +</ul> +<li>Whatever an RI will put up with</li> + +<ul> +<li>Extensible calling semantics</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/snoqualmie-falls-flowing-3811-equalized.jpg" align=right> +<h1>MO compilation flow</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/snoqualmie-falls-flowing-3811-equalized.jpg" align=right> +<h1>MO compilation flow</h1> +<p> + +</p> +<ul> +<li>Instantiate a <tt>Class</tt> object</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/snoqualmie-falls-flowing-3811-equalized.jpg" align=right> +<h1>MO compilation flow</h1> +<p> + +</p> +<ul> +<li>Instantiate a <tt>Class</tt> object</li> + +<ul> +<li>Specify members (methods, attributes)</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/snoqualmie-falls-flowing-3811-equalized.jpg" align=right> +<h1>MO compilation flow</h1> +<p> + +</p> +<ul> +<li>Instantiate a <tt>Class</tt> object</li> + +<ul> +<li>Specify members (methods, attributes)</li> +<li>... and ancestor classes & roles</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/snoqualmie-falls-flowing-3811-equalized.jpg" align=right> +<h1>MO compilation flow</h1> +<p> + +</p> +<ul> +<li>Instantiate a <tt>Class</tt> object</li> + +<ul> +<li>Specify members (methods, attributes)</li> +<li>... and ancestor classes & roles</li> +</ul> +<li>Compile class</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/snoqualmie-falls-flowing-3811-equalized.jpg" align=right> +<h1>MO compilation flow</h1> +<p> + +</p> +<ul> +<li>Instantiate a <tt>Class</tt> object</li> + +<ul> +<li>Specify members (methods, attributes)</li> +<li>... and ancestor classes & roles</li> +</ul> +<li>Compile class</li> + +<ul> +<li><tt>my $class_methods_ri = $class->class_interface()</tt></li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/snoqualmie-falls-flowing-3811-equalized.jpg" align=right> +<h1>MO compilation flow</h1> +<p> + +</p> +<ul> +<li>Instantiate a <tt>Class</tt> object</li> + +<ul> +<li>Specify members (methods, attributes)</li> +<li>... and ancestor classes & roles</li> +</ul> +<li>Compile class</li> + +<ul> +<li><tt>my $class_methods_ri = $class->class_interface()</tt></li> +<li>Instance method RI closed in the constructor, within <tt>$ri</tt></li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/snoqualmie-falls-flowing-3811-equalized.jpg" align=right> +<h1>MO compilation flow</h1> +<p> + +</p> +<ul> +<li>Instantiate a <tt>Class</tt> object</li> + +<ul> +<li>Specify members (methods, attributes)</li> +<li>... and ancestor classes & roles</li> +</ul> +<li>Compile class</li> + +<ul> +<li><tt>my $class_methods_ri = $class->class_interface()</tt></li> +<li>Instance method RI closed in the constructor, within <tt>$ri</tt></li> +<li>Purely functional operation </li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/snoqualmie-falls-flowing-3811-equalized.jpg" align=right> +<h1>RI composition</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/snoqualmie-falls-flowing-3811-equalized.jpg" align=right> +<h1>RI composition</h1> +<p> + +</p> +<ul> +<li>Compute instance methods and attributes from ancestry</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/snoqualmie-falls-flowing-3811-equalized.jpg" align=right> +<h1>RI composition</h1> +<p> + +</p> +<ul> +<li>Compute instance methods and attributes from ancestry</li> +<li>Compute instance slots from attributes</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/snoqualmie-falls-flowing-3811-equalized.jpg" align=right> +<h1>RI composition</h1> +<p> + +</p> +<ul> +<li>Compute instance methods and attributes from ancestry</li> +<li>Compute instance slots from attributes</li> +<li>Generate accessors</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/snoqualmie-falls-flowing-3811-equalized.jpg" align=right> +<h1>RI composition</h1> +<p> + +</p> +<ul> +<li>Compute instance methods and attributes from ancestry</li> +<li>Compute instance slots from attributes</li> +<li>Generate accessors</li> +</ul> +<pre class="vim"> MO::Run::ResponderInterface::MethodTable->new( + methods => %methods + ); +</pre> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/snoqualmie-falls-flowing-3811-equalized.jpg" align=right> +<h1>RI composition</h1> +<p> + +</p> +<ul> +<li>Compute instance methods and attributes from ancestry</li> +<li>Compute instance slots from attributes</li> +<li>Generate accessors</li> +</ul> +<pre class="vim"> MO::Run::ResponderInterface::MethodTable->new( + methods => %methods + ); +</pre> +<ul> +<li>Generate constructor</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/snoqualmie-falls-flowing-3811-equalized.jpg" align=right> +<h1>RI composition</h1> +<p> + +</p> +<ul> +<li>Compute instance methods and attributes from ancestry</li> +<li>Compute instance slots from attributes</li> +<li>Generate accessors</li> +</ul> +<pre class="vim"> MO::Run::ResponderInterface::MethodTable->new( + methods => %methods + ); +</pre> +<ul> +<li>Generate constructor</li> +</ul> +<pre class="vim"> sub { + my $data = process_params(@_); + return box( $data, $instance_ri ); + } +</pre> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Creation-hands-L.jpg" align=right> +<h1>Instantiation</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Creation-hands-L.jpg" align=right> +<h1>Instantiation</h1> +<p> + +</p> +<ul> +<li>Lookup RI using class name</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Creation-hands-L.jpg" align=right> +<h1>Instantiation</h1> +<p> + +</p> +<ul> +<li>Lookup RI using class name</li> +<li>Dispatch constructor class method</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Creation-hands-L.jpg" align=right> +<h1>Instantiation</h1> +<p> + +</p> +<ul> +<li>Lookup RI using class name</li> +<li>Dispatch constructor class method</li> +<li>Compose data from params</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Creation-hands-L.jpg" align=right> +<h1>Instantiation</h1> +<p> + +</p> +<ul> +<li>Lookup RI using class name</li> +<li>Dispatch constructor class method</li> +<li>Compose data from params</li> + +<ul> +<li>Slightly complicated</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Creation-hands-L.jpg" align=right> +<h1>Instantiation</h1> +<p> + +</p> +<ul> +<li>Lookup RI using class name</li> +<li>Dispatch constructor class method</li> +<li>Compose data from params</li> + +<ul> +<li>Slightly complicated</li> +</ul> +<li>Link data with closed <tt>$instance_ri</tt></li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Creation-hands-L.jpg" align=right> +<h1>Instantiation</h1> +<p> + +</p> +<ul> +<li>Lookup RI using class name</li> +<li>Dispatch constructor class method</li> +<li>Compose data from params</li> + +<ul> +<li>Slightly complicated</li> +</ul> +<li>Link data with closed <tt>$instance_ri</tt></li> + +<ul> +<li>Responder == ( Data, RI )</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Creation-hands-L.jpg" align=right> +<h1>Instantiation</h1> +<p> + +</p> +<ul> +<li>Lookup RI using class name</li> +<li>Dispatch constructor class method</li> +<li>Compose data from params</li> + +<ul> +<li>Slightly complicated</li> +</ul> +<li>Link data with closed <tt>$instance_ri</tt></li> + +<ul> +<li>Responder == ( Data, RI )</li> +<li>Like <tt>bless</tt></li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/telephone.jpg" align=right> +<h1>Method calls</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/telephone.jpg" align=right> +<h1>Method calls</h1> +<p> + +</p> +<ul> +<li>How to talk with your new object?</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/telephone.jpg" align=right> +<h1>Method calls</h1> +<p> + +</p> +<ul> +<li>How to talk with your new object?</li> +</ul> +<pre class="vim"> my $ri = $responder->responder_interface; + +</pre> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/telephone.jpg" align=right> +<h1>Method calls</h1> +<p> + +</p> +<ul> +<li>How to talk with your new object?</li> +</ul> +<pre class="vim"> my $ri = $responder->responder_interface; + + + my $method = MO::Run::Invocation::Method->new( + name => "foo" + arguments => \@blah, + ); + +</pre> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/telephone.jpg" align=right> +<h1>Method calls</h1> +<p> + +</p> +<ul> +<li>How to talk with your new object?</li> +</ul> +<pre class="vim"> my $ri = $responder->responder_interface; + + + my $method = MO::Run::Invocation::Method->new( + name => "foo" + arguments => \@blah, + ); + + + $ri->dispatch( $responder, $method ); +</pre> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/telephone.jpg" align=right> +<h1>Method calls</h1> +<p> + +</p> +<ul> +<li>How to talk with your new object?</li> +</ul> +<pre class="vim"> my $ri = $responder->responder_interface; + + + my $method = MO::Run::Invocation::Method->new( + name => "foo" + arguments => \@blah, + ); + + + $ri->dispatch( $responder, $method ); +</pre> +<ul> +<li>Arbitrary responder interfaces also allowed</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/telephone.jpg" align=right> +<h1>Method calls</h1> +<p> + +</p> +<ul> +<li>How to talk with your new object?</li> +</ul> +<pre class="vim"> my $ri = $responder->responder_interface; + + + my $method = MO::Run::Invocation::Method->new( + name => "foo" + arguments => \@blah, + ); + + + $ri->dispatch( $responder, $method ); +</pre> +<ul> +<li>Arbitrary responder interfaces also allowed</li> + +<ul> +<li>Doesn't have to be <tt>$responder->responder_interface</tt></li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Surprise-buttsecks.jpg" align=right> +<h1>OH NOES!!!</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Surprise-buttsecks.jpg" align=right> +<h1>OH NOES!!!</h1> +<p> + +</p> +<ul> +<li>What's wrong with the previous slide?</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Surprise-buttsecks.jpg" align=right> +<h1>OH NOES!!!</h1> +<p> + +</p> +<ul> +<li>What's wrong with the previous slide?</li> +<li>RIs are objects too!</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Surprise-buttsecks.jpg" align=right> +<h1>OH NOES!!!</h1> +<p> + +</p> +<ul> +<li>What's wrong with the previous slide?</li> +<li>RIs are objects too!</li> +<li>Need to bootstrap method calls</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Surprise-buttsecks.jpg" align=right> +<h1>OH NOES!!!</h1> +<p> + +</p> +<ul> +<li>What's wrong with the previous slide?</li> +<li>RIs are objects too!</li> +<li>Need to bootstrap method calls</li> +<li>Runtime must bootstrap low level OO</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/Surprise-buttsecks.jpg" align=right> +<h1>OH NOES!!!</h1> +<p> + +</p> +<ul> +<li>What's wrong with the previous slide?</li> +<li>RIs are objects too!</li> +<li>Need to bootstrap method calls</li> +<li>Runtime must bootstrap low level OO</li> + +<ul> +<li>More on this soon</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/44790qV87_w.jpg" align=right> +<h1>Meta level polymorphism</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/44790qV87_w.jpg" align=right> +<h1>Meta level polymorphism</h1> +<p> + +</p> +<ul> +<li>An important point</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/44790qV87_w.jpg" align=right> +<h1>Meta level polymorphism</h1> +<p> + +</p> +<ul> +<li>An important point</li> + +<ul> +<li>In fact, <strong>the</strong> point of MO</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/44790qV87_w.jpg" align=right> +<h1>Meta level polymorphism</h1> +<p> + +</p> +<ul> +<li>An important point</li> + +<ul> +<li>In fact, <strong>the</strong> point of MO</li> +</ul> +<li>Responder interfaces are polymorphic</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/44790qV87_w.jpg" align=right> +<h1>Meta level polymorphism</h1> +<p> + +</p> +<ul> +<li>An important point</li> + +<ul> +<li>In fact, <strong>the</strong> point of MO</li> +</ul> +<li>Responder interfaces are polymorphic</li> + +<ul> +<li>Method table, network proxy, whatever</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/44790qV87_w.jpg" align=right> +<h1>Meta level polymorphism</h1> +<p> + +</p> +<ul> +<li>An important point</li> + +<ul> +<li>In fact, <strong>the</strong> point of MO</li> +</ul> +<li>Responder interfaces are polymorphic</li> + +<ul> +<li>Method table, network proxy, whatever</li> +</ul> +<li>Easy to specialize</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/44790qV87_w.jpg" align=right> +<h1>Meta level polymorphism</h1> +<p> + +</p> +<ul> +<li>An important point</li> + +<ul> +<li>In fact, <strong>the</strong> point of MO</li> +</ul> +<li>Responder interfaces are polymorphic</li> + +<ul> +<li>Method table, network proxy, whatever</li> +</ul> +<li>Easy to specialize</li> + +<ul> +<li>Optimizations</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/44790qV87_w.jpg" align=right> +<h1>Meta level polymorphism</h1> +<p> + +</p> +<ul> +<li>An important point</li> + +<ul> +<li>In fact, <strong>the</strong> point of MO</li> +</ul> +<li>Responder interfaces are polymorphic</li> + +<ul> +<li>Method table, network proxy, whatever</li> +</ul> +<li>Easy to specialize</li> + +<ul> +<li>Optimizations</li> +<li>Strange features</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/44790qV87_w.jpg" align=right> +<h1>Meta level polymorphism</h1> +<p> + +</p> +<ul> +<li>An important point</li> + +<ul> +<li>In fact, <strong>the</strong> point of MO</li> +</ul> +<li>Responder interfaces are polymorphic</li> + +<ul> +<li>Method table, network proxy, whatever</li> +</ul> +<li>Easy to specialize</li> + +<ul> +<li>Optimizations</li> +<li>Strange features</li> +</ul> +<li>Easy to mix several OO systems</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/44790qV87_w.jpg" align=right> +<h1>Meta level polymorphism</h1> +<p> + +</p> +<ul> +<li>An important point</li> + +<ul> +<li>In fact, <strong>the</strong> point of MO</li> +</ul> +<li>Responder interfaces are polymorphic</li> + +<ul> +<li>Method table, network proxy, whatever</li> +</ul> +<li>Easy to specialize</li> + +<ul> +<li>Optimizations</li> +<li>Strange features</li> +</ul> +<li>Easy to mix several OO systems</li> + +<ul> +<li>Just compile to separate RIs</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/card-camel-108.jpg" align=right> +<h1>MO in Perl 5</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/card-camel-108.jpg" align=right> +<h1>MO in Perl 5</h1> +<p> + +</p> +<ul> +<li>Two runtimes</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/card-camel-108.jpg" align=right> +<h1>MO in Perl 5</h1> +<p> + +</p> +<ul> +<li>Two runtimes</li> +<li>Very different</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/card-camel-108.jpg" align=right> +<h1>MO in Perl 5</h1> +<p> + +</p> +<ul> +<li>Two runtimes</li> +<li>Very different</li> +<li><tt>MO::Run::Aux</tt> wraps both</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/card-camel-108.jpg" align=right> +<h1>MO in Perl 5</h1> +<p> + +</p> +<ul> +<li>Two runtimes</li> +<li>Very different</li> +<li><tt>MO::Run::Aux</tt> wraps both</li> + +<ul> +<li>Share tests by running with different <tt>%ENV</tt> var</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/S2Secret.jpg" align=right> +<h1>Hosted runtime</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/S2Secret.jpg" align=right> +<h1>Hosted runtime</h1> +<p> + +</p> +<ul> +<li>Nested object system</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/S2Secret.jpg" align=right> +<h1>Hosted runtime</h1> +<p> + +</p> +<ul> +<li>Nested object system</li> +<li>Bootstraps with Perl 5</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/S2Secret.jpg" align=right> +<h1>Hosted runtime</h1> +<p> + +</p> +<ul> +<li>Nested object system</li> +<li>Bootstraps with Perl 5</li> + +<ul> +<li>Native Perl OO == Low level, like VM opcodes</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/S2Secret.jpg" align=right> +<h1>Hosted runtime</h1> +<p> + +</p> +<ul> +<li>Nested object system</li> +<li>Bootstraps with Perl 5</li> + +<ul> +<li>Native Perl OO == Low level, like VM opcodes</li> +<li>Virtualized MO == High Level</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/S2Secret.jpg" align=right> +<h1>Hosted runtime</h1> +<p> + +</p> +<ul> +<li>Nested object system</li> +<li>Bootstraps with Perl 5</li> + +<ul> +<li>Native Perl OO == Low level, like VM opcodes</li> +<li>Virtualized MO == High Level</li> +<li>Completely separate levels</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/S2Secret.jpg" align=right> +<h1>Hosted runtime</h1> +<p> + +</p> +<ul> +<li>Nested object system</li> +<li>Bootstraps with Perl 5</li> + +<ul> +<li>Native Perl OO == Low level, like VM opcodes</li> +<li>Virtualized MO == High Level</li> +<li>Completely separate levels</li> +</ul> +<li><tt>$ri->dispatch( $responder, $method )</tt></li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/S2Secret.jpg" align=right> +<h1>Hosted runtime</h1> +<p> + +</p> +<ul> +<li>Nested object system</li> +<li>Bootstraps with Perl 5</li> + +<ul> +<li>Native Perl OO == Low level, like VM opcodes</li> +<li>Virtualized MO == High Level</li> +<li>Completely separate levels</li> +</ul> +<li><tt>$ri->dispatch( $responder, $method )</tt></li> + +<ul> +<li>not <tt>$responder->$method()</tt></li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/S2Secret.jpg" align=right> +<h1>Hosted runtime</h1> +<p> + +</p> +<ul> +<li>Nested object system</li> +<li>Bootstraps with Perl 5</li> + +<ul> +<li>Native Perl OO == Low level, like VM opcodes</li> +<li>Virtualized MO == High Level</li> +<li>Completely separate levels</li> +</ul> +<li><tt>$ri->dispatch( $responder, $method )</tt></li> + +<ul> +<li>not <tt>$responder->$method()</tt></li> +</ul> +<li>Full expressiveness</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/S2Secret.jpg" align=right> +<h1>Hosted runtime</h1> +<p> + +</p> +<ul> +<li>Nested object system</li> +<li>Bootstraps with Perl 5</li> + +<ul> +<li>Native Perl OO == Low level, like VM opcodes</li> +<li>Virtualized MO == High Level</li> +<li>Completely separate levels</li> +</ul> +<li><tt>$ri->dispatch( $responder, $method )</tt></li> + +<ul> +<li>not <tt>$responder->$method()</tt></li> +</ul> +<li>Full expressiveness</li> +<li>Slow, verbose</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/indian-camp.jpg" align=right> +<h1>Native runtime</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/indian-camp.jpg" align=right> +<h1>Native runtime</h1> +<p> + +</p> +<ul> +<li>Integrated object system</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/indian-camp.jpg" align=right> +<h1>Native runtime</h1> +<p> + +</p> +<ul> +<li>Integrated object system</li> +<li>RIs are compiled into packages</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/indian-camp.jpg" align=right> +<h1>Native runtime</h1> +<p> + +</p> +<ul> +<li>Integrated object system</li> +<li>RIs are compiled into packages</li> + +<ul> +<li>Simple RIs are dissassembled and stuffed into the stash</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/indian-camp.jpg" align=right> +<h1>Native runtime</h1> +<p> + +</p> +<ul> +<li>Integrated object system</li> +<li>RIs are compiled into packages</li> + +<ul> +<li>Simple RIs are dissassembled and stuffed into the stash</li> +<li>Complex RIs use <tt>AUTOLOAD</tt>, delegating to the RI meta object</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/indian-camp.jpg" align=right> +<h1>Native runtime</h1> +<p> + +</p> +<ul> +<li>Integrated object system</li> +<li>RIs are compiled into packages</li> + +<ul> +<li>Simple RIs are dissassembled and stuffed into the stash</li> +<li>Complex RIs use <tt>AUTOLOAD</tt>, delegating to the RI meta object</li> +</ul> +<li>Only named method calls</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/indian-camp.jpg" align=right> +<h1>Native runtime</h1> +<p> + +</p> +<ul> +<li>Integrated object system</li> +<li>RIs are compiled into packages</li> + +<ul> +<li>Simple RIs are dissassembled and stuffed into the stash</li> +<li>Complex RIs use <tt>AUTOLOAD</tt>, delegating to the RI meta object</li> +</ul> +<li>Only named method calls</li> + +<ul> +<li>No arbitrary call concepts</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/indian-camp.jpg" align=right> +<h1>Native runtime</h1> +<p> + +</p> +<ul> +<li>Integrated object system</li> +<li>RIs are compiled into packages</li> + +<ul> +<li>Simple RIs are dissassembled and stuffed into the stash</li> +<li>Complex RIs use <tt>AUTOLOAD</tt>, delegating to the RI meta object</li> +</ul> +<li>Only named method calls</li> + +<ul> +<li>No arbitrary call concepts</li> +<li><tt>-></tt> doesn't support anything else</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/indian-camp.jpg" align=right> +<h1>Native runtime</h1> +<p> + +</p> +<ul> +<li>Integrated object system</li> +<li>RIs are compiled into packages</li> + +<ul> +<li>Simple RIs are dissassembled and stuffed into the stash</li> +<li>Complex RIs use <tt>AUTOLOAD</tt>, delegating to the RI meta object</li> +</ul> +<li>Only named method calls</li> + +<ul> +<li>No arbitrary call concepts</li> +<li><tt>-></tt> doesn't support anything else</li> +</ul> +<li>As fast as "regular" Perl OO</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/indian-camp.jpg" align=right> +<h1>Native runtime</h1> +<p> + +</p> +<ul> +<li>Integrated object system</li> +<li>RIs are compiled into packages</li> + +<ul> +<li>Simple RIs are dissassembled and stuffed into the stash</li> +<li>Complex RIs use <tt>AUTOLOAD</tt>, delegating to the RI meta object</li> +</ul> +<li>Only named method calls</li> + +<ul> +<li>No arbitrary call concepts</li> +<li><tt>-></tt> doesn't support anything else</li> +</ul> +<li>As fast as "regular" Perl OO</li> + +<ul> +<li>Even makes simple, standalone `.pmc`s</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Perl 5 Runtimes</h1> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Perl 5 Runtimes</h1> +<ul> +<li>Native</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Perl 5 Runtimes</h1> +<ul> +<li>Native</li> + +<ul> +<li>Usable with regular Perl OO <span class="html">☺</span></li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Perl 5 Runtimes</h1> +<ul> +<li>Native</li> + +<ul> +<li>Usable with regular Perl OO <span class="html">☺</span></li> +<li>Lacks arbitrary invocations <span class="html">☹</span> </li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Perl 5 Runtimes</h1> +<ul> +<li>Native</li> + +<ul> +<li>Usable with regular Perl OO <span class="html">☺</span></li> +<li>Lacks arbitrary invocations <span class="html">☹</span> </li> +</ul> +<li>Virtualized</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Perl 5 Runtimes</h1> +<ul> +<li>Native</li> + +<ul> +<li>Usable with regular Perl OO <span class="html">☺</span></li> +<li>Lacks arbitrary invocations <span class="html">☹</span> </li> +</ul> +<li>Virtualized</li> + +<ul> +<li>Feature complete <span class="html">☺</span></li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Perl 5 Runtimes</h1> +<ul> +<li>Native</li> + +<ul> +<li>Usable with regular Perl OO <span class="html">☺</span></li> +<li>Lacks arbitrary invocations <span class="html">☹</span> </li> +</ul> +<li>Virtualized</li> + +<ul> +<li>Feature complete <span class="html">☺</span></li> +<li>Doesn't integrate <span class="html">☹</span></li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Perl 5 Runtimes</h1> +<ul> +<li>Native</li> + +<ul> +<li>Usable with regular Perl OO <span class="html">☺</span></li> +<li>Lacks arbitrary invocations <span class="html">☹</span> </li> +</ul> +<li>Virtualized</li> + +<ul> +<li>Feature complete <span class="html">☺</span></li> +<li>Doesn't integrate <span class="html">☹</span></li> +<li>Slow <span class="html">☹</span></li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/botticelli.venus.jpg" align=right> +<h1>Idealized MO toolchain</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/botticelli.venus.jpg" align=right> +<h1>Idealized MO toolchain</h1> +<p> + +</p> +<ul> +<li>Compiler handles modeling</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/botticelli.venus.jpg" align=right> +<h1>Idealized MO toolchain</h1> +<p> + +</p> +<ul> +<li>Compiler handles modeling</li> + +<ul> +<li>Constructs meta objects at compile time</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/botticelli.venus.jpg" align=right> +<h1>Idealized MO toolchain</h1> +<p> + +</p> +<ul> +<li>Compiler handles modeling</li> + +<ul> +<li>Constructs meta objects at compile time</li> +</ul> +<li>VM Opcodes support standard RI</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/botticelli.venus.jpg" align=right> +<h1>Idealized MO toolchain</h1> +<p> + +</p> +<ul> +<li>Compiler handles modeling</li> + +<ul> +<li>Constructs meta objects at compile time</li> +</ul> +<li>VM Opcodes support standard RI</li> +<li>Custom RIs are just objects</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/botticelli.venus.jpg" align=right> +<h1>Idealized MO toolchain</h1> +<p> + +</p> +<ul> +<li>Compiler handles modeling</li> + +<ul> +<li>Constructs meta objects at compile time</li> +</ul> +<li>VM Opcodes support standard RI</li> +<li>Custom RIs are just objects</li> + +<ul> +<li>Bootstrapped using standard runtime objects</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/botticelli.venus.jpg" align=right> +<h1>Idealized MO toolchain</h1> +<p> + +</p> +<ul> +<li>Compiler handles modeling</li> + +<ul> +<li>Constructs meta objects at compile time</li> +</ul> +<li>VM Opcodes support standard RI</li> +<li>Custom RIs are just objects</li> + +<ul> +<li>Bootstrapped using standard runtime objects</li> + +<ul> +<li>Method table RI</li> +</ul></ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/botticelli.venus.jpg" align=right> +<h1>Idealized MO toolchain</h1> +<p> + +</p> +<ul> +<li>Compiler handles modeling</li> + +<ul> +<li>Constructs meta objects at compile time</li> +</ul> +<li>VM Opcodes support standard RI</li> +<li>Custom RIs are just objects</li> + +<ul> +<li>Bootstrapped using standard runtime objects</li> + +<ul> +<li>Method table RI</li> +<li>Named method invocation</li> +</ul></ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lolgeeks016.jpg" align=right> +<h1>Perl 6</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lolgeeks016.jpg" align=right> +<h1>Perl 6</h1> +<p> + +</p> +<ul> +<li>Perl 6 is the idealized MO toolchain</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lolgeeks016.jpg" align=right> +<h1>Perl 6</h1> +<p> + +</p> +<ul> +<li>Perl 6 is the idealized MO toolchain</li> + +<ul> +<li>Can introduce syntax</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lolgeeks016.jpg" align=right> +<h1>Perl 6</h1> +<p> + +</p> +<ul> +<li>Perl 6 is the idealized MO toolchain</li> + +<ul> +<li>Can introduce syntax</li> + +<ul> +<li>Invocation types</li> +</ul></ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lolgeeks016.jpg" align=right> +<h1>Perl 6</h1> +<p> + +</p> +<ul> +<li>Perl 6 is the idealized MO toolchain</li> + +<ul> +<li>Can introduce syntax</li> + +<ul> +<li>Invocation types</li> +<li>Concept declarations</li> +</ul></ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lolgeeks016.jpg" align=right> +<h1>Perl 6</h1> +<p> + +</p> +<ul> +<li>Perl 6 is the idealized MO toolchain</li> + +<ul> +<li>Can introduce syntax</li> + +<ul> +<li>Invocation types</li> +<li>Concept declarations</li> +</ul> +<li>Implement bootstrap RIs in VM opcodes</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lolgeeks016.jpg" align=right> +<h1>Perl 6</h1> +<p> + +</p> +<ul> +<li>Perl 6 is the idealized MO toolchain</li> + +<ul> +<li>Can introduce syntax</li> + +<ul> +<li>Invocation types</li> +<li>Concept declarations</li> +</ul> +<li>Implement bootstrap RIs in VM opcodes</li> +</ul> +<li>Pugs might be using MO</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lolgeeks016.jpg" align=right> +<h1>Perl 6</h1> +<p> + +</p> +<ul> +<li>Perl 6 is the idealized MO toolchain</li> + +<ul> +<li>Can introduce syntax</li> + +<ul> +<li>Invocation types</li> +<li>Concept declarations</li> +</ul> +<li>Implement bootstrap RIs in VM opcodes</li> +</ul> +<li>Pugs might be using MO</li> + +<ul> +<li>I'm not really sure</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/lolgeeks016.jpg" align=right> +<h1>Perl 6</h1> +<p> + +</p> +<ul> +<li>Perl 6 is the idealized MO toolchain</li> + +<ul> +<li>Can introduce syntax</li> + +<ul> +<li>Invocation types</li> +<li>Concept declarations</li> +</ul> +<li>Implement bootstrap RIs in VM opcodes</li> +</ul> +<li>Pugs might be using MO</li> + +<ul> +<li>I'm not really sure</li> +<li>It was ported a while ago</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Introducing new concepts</h1> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Introducing new concepts</h1> +<ul> +<li>Roles are the shit</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Introducing new concepts</h1> +<ul> +<li>Roles are the shit</li> +<li>But what about next week's fad?</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Introducing new concepts</h1> +<ul> +<li>Roles are the shit</li> +<li>But what about next week's fad?</li> +<li>MO lets you introduce a new concept</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Introducing new concepts</h1> +<ul> +<li>Roles are the shit</li> +<li>But what about next week's fad?</li> +<li>MO lets you introduce a new concept</li> + +<ul> +<li>Arbitrary at compile time</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Introducing new concepts</h1> +<ul> +<li>Roles are the shit</li> +<li>But what about next week's fad?</li> +<li>MO lets you introduce a new concept</li> + +<ul> +<li>Arbitrary at compile time</li> +<li>RI protocol at runtime</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Example - Prototype Objects</h1> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Example - Prototype Objects</h1> +<ul> +<li>One shared RI</li> +</ul> +<pre class="vim"> sub dispatch { + my ( $object, $invocation ) = @_; + + my $method = $object->{ $invocation->name }; + + $object->$method( $invocation->arguments ); + } +</pre> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/village_people.jpg" align=right> +<h1>Example - Attribute Grammars</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/village_people.jpg" align=right> +<h1>Example - Attribute Grammars</h1> +<p> + +</p> +<ul> +<li>Crazy stuff from the 1970s</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/village_people.jpg" align=right> +<h1>Example - Attribute Grammars</h1> +<p> + +</p> +<ul> +<li>Crazy stuff from the 1970s</li> +<li>Renewed interest in <span class="html">λ</span> land </li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/village_people.jpg" align=right> +<h1>Example - Attribute Grammars</h1> +<p> + +</p> +<ul> +<li>Crazy stuff from the 1970s</li> +<li>Renewed interest in <span class="html">λ</span> land </li> +<li>Was pretty easy in MO</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/grammar.gif" align=right> +<h1>Attribute Grammer Implementation</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/grammar.gif" align=right> +<h1>Attribute Grammer Implementation</h1> +<p> + +</p> +<ul> +<li>Introduce new concept objects</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/grammar.gif" align=right> +<h1>Attribute Grammer Implementation</h1> +<p> + +</p> +<ul> +<li>Introduce new concept objects</li> + +<ul> +<li>Attribute Grammar</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/grammar.gif" align=right> +<h1>Attribute Grammer Implementation</h1> +<p> + +</p> +<ul> +<li>Introduce new concept objects</li> + +<ul> +<li>Attribute Grammar</li> +<li>Attribute Grammer Instance - one per AG per class</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/grammar.gif" align=right> +<h1>Attribute Grammer Implementation</h1> +<p> + +</p> +<ul> +<li>Introduce new concept objects</li> + +<ul> +<li>Attribute Grammar</li> +<li>Attribute Grammer Instance - one per AG per class</li> +</ul> +<li>Runtime specialized RI</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/grammar.gif" align=right> +<h1>Attribute Grammer Implementation</h1> +<p> + +</p> +<ul> +<li>Introduce new concept objects</li> + +<ul> +<li>Attribute Grammar</li> +<li>Attribute Grammer Instance - one per AG per class</li> +</ul> +<li>Runtime specialized RI</li> + +<ul> +<li>Shadows any RI with additional context sensitive methods</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/grammar.gif" align=right> +<h1>Attribute Grammer Implementation</h1> +<p> + +</p> +<ul> +<li>Introduce new concept objects</li> + +<ul> +<li>Attribute Grammar</li> +<li>Attribute Grammer Instance - one per AG per class</li> +</ul> +<li>Runtime specialized RI</li> + +<ul> +<li>Shadows any RI with additional context sensitive methods</li> +</ul> +<li>Additional runtime support code</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/checklist.jpg" align=right> +<h1>MO TODO</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/checklist.jpg" align=right> +<h1>MO TODO</h1> +<p> + +</p> +<ul> +<li>Write a sugar layer</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/checklist.jpg" align=right> +<h1>MO TODO</h1> +<p> + +</p> +<ul> +<li>Write a sugar layer</li> + +<ul> +<li>Make it fun to use</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/checklist.jpg" align=right> +<h1>MO TODO</h1> +<p> + +</p> +<ul> +<li>Write a sugar layer</li> + +<ul> +<li>Make it fun to use</li> +</ul> +<li>Tests</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/checklist.jpg" align=right> +<h1>MO TODO</h1> +<p> + +</p> +<ul> +<li>Write a sugar layer</li> + +<ul> +<li>Make it fun to use</li> +</ul> +<li>Tests</li> +<li>Refactor the Class objects</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/checklist.jpg" align=right> +<h1>MO TODO</h1> +<p> + +</p> +<ul> +<li>Write a sugar layer</li> + +<ul> +<li>Make it fun to use</li> +</ul> +<li>Tests</li> +<li>Refactor the Class objects</li> + +<ul> +<li>Bloated example code</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/checklist.jpg" align=right> +<h1>MO TODO</h1> +<p> + +</p> +<ul> +<li>Write a sugar layer</li> + +<ul> +<li>Make it fun to use</li> +</ul> +<li>Tests</li> +<li>Refactor the Class objects</li> + +<ul> +<li>Bloated example code</li> +<li>There are some patterns to extract</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/checklist.jpg" align=right> +<h1>MO TODO</h1> +<p> + +</p> +<ul> +<li>Write a sugar layer</li> + +<ul> +<li>Make it fun to use</li> +</ul> +<li>Tests</li> +<li>Refactor the Class objects</li> + +<ul> +<li>Bloated example code</li> +<li>There are some patterns to extract</li> +</ul> +<li>Self hosting</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Self Hosting</h1> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Self Hosting</h1> +<ul> +<li>Easier to maintain MO written in Moose</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Self Hosting</h1> +<ul> +<li>Easier to maintain MO written in Moose</li> +<li>Need to have clean syntax</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> + +<h1>Self Hosting</h1> +<ul> +<li>Easier to maintain MO written in Moose</li> +<li>Need to have clean syntax</li> +<li>Stable <tt>.pmc</tt> compilation</li> +</ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_2540021_painted_exclamation_mark.jpg" align=right> +<h1>Conclusion</h1> +<p> + +</p> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_2540021_painted_exclamation_mark.jpg" align=right> +<h1>Conclusion</h1> +<p> + +</p> +<ul> +<li>Meta code is awesome code</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_2540021_painted_exclamation_mark.jpg" align=right> +<h1>Conclusion</h1> +<p> + +</p> +<ul> +<li>Meta code is awesome code</li> + +<ul> +<li>Especially my meta code ;-)</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_2540021_painted_exclamation_mark.jpg" align=right> +<h1>Conclusion</h1> +<p> + +</p> +<ul> +<li>Meta code is awesome code</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_2540021_painted_exclamation_mark.jpg" align=right> +<h1>Conclusion</h1> +<p> + +</p> +<ul> +<li>Meta code is awesome code</li> + +<ul> +<li>Lets you program in new ways</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_2540021_painted_exclamation_mark.jpg" align=right> +<h1>Conclusion</h1> +<p> + +</p> +<ul> +<li>Meta code is awesome code</li> + +<ul> +<li>Lets you program in new ways</li> +<li>Helps you take care of your other code</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_2540021_painted_exclamation_mark.jpg" align=right> +<h1>Conclusion</h1> +<p> + +</p> +<ul> +<li>Meta code is awesome code</li> + +<ul> +<li>Lets you program in new ways</li> +<li>Helps you take care of your other code</li> +</ul> +<li>Meta code is important code</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_2540021_painted_exclamation_mark.jpg" align=right> +<h1>Conclusion</h1> +<p> + +</p> +<ul> +<li>Meta code is awesome code</li> + +<ul> +<li>Lets you program in new ways</li> +<li>Helps you take care of your other code</li> +</ul> +<li>Meta code is important code</li> + +<ul> +<li>It can affect <strong>anything</strong></li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_2540021_painted_exclamation_mark.jpg" align=right> +<h1>Conclusion</h1> +<p> + +</p> +<ul> +<li>Meta code is awesome code</li> + +<ul> +<li>Lets you program in new ways</li> +<li>Helps you take care of your other code</li> +</ul> +<li>Meta code is important code</li> + +<ul> +<li>It can affect <strong>anything</strong></li> +<li>Keep it minimalistic, and clearly defined</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_2540021_painted_exclamation_mark.jpg" align=right> +<h1>Conclusion</h1> +<p> + +</p> +<ul> +<li>Meta code is awesome code</li> + +<ul> +<li>Lets you program in new ways</li> +<li>Helps you take care of your other code</li> +</ul> +<li>Meta code is important code</li> + +<ul> +<li>It can affect <strong>anything</strong></li> +<li>Keep it minimalistic, and clearly defined</li> +<li>No spaghetti monsters</li> +</ul></ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_2540021_painted_exclamation_mark.jpg" align=right> +<h1>Conclusion</h1> +<p> + +</p> +<ul> +<li>Meta code is awesome code</li> + +<ul> +<li>Lets you program in new ways</li> +<li>Helps you take care of your other code</li> +</ul> +<li>Meta code is important code</li> + +<ul> +<li>It can affect <strong>anything</strong></li> +<li>Keep it minimalistic, and clearly defined</li> +<li>No spaghetti monsters</li> +</ul> +<li>Meta code can be simple</li> +</ul> +<small>continued...</small> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/istockphoto_2540021_painted_exclamation_mark.jpg" align=right> +<h1>Conclusion</h1> +<p> + +</p> +<ul> +<li>Meta code is awesome code</li> + +<ul> +<li>Lets you program in new ways</li> +<li>Helps you take care of your other code</li> +</ul> +<li>Meta code is important code</li> + +<ul> +<li>It can affect <strong>anything</strong></li> +<li>Keep it minimalistic, and clearly defined</li> +<li>No spaghetti monsters</li> +</ul> +<li>Meta code can be simple</li> + +<ul> +<li>Only complicated if you aren't careful</li> +</ul></ul> + +</div> +<!-- END slide --> + + +<!-- BEGIN slide --> +<div class="slide"> +<img name="img" id="img" width="350" src="images/thanks.jpg" align=right> +<h1>BIE FRENDS</h1> +<p> + +</p> + +</div> +<!-- END slide --> + + +</body> +</html> +<!-- END s5 --> diff --git a/object_meta_programming_slides/slides/template/s5/s5.html b/object_meta_programming_slides/slides/template/s5/s5.html new file mode 100644 index 0000000..0e03162 --- /dev/null +++ b/object_meta_programming_slides/slides/template/s5/s5.html @@ -0,0 +1,40 @@ +<!-- BEGIN s5 --> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> +<title>[% presentation_topic %]</title> +<meta name="generator" content="S5" /> +<meta name="version" content="S5 1.0" /> +<meta name="presdate" content="20041007" /> +<meta name="author" content="Eric A. Meyer" /> +<link rel="stylesheet" href="ui/slides.css" type="text/css" media="projection" id="slideProj" /> +<link rel="stylesheet" href="ui/opera.css" type="text/css" media="projection" id="operaFix" /> +<link rel="stylesheet" href="ui/print.css" type="text/css" media="print" id="slidePrint" /> +<script src="ui/slides.js" type="text/javascript"></script> +</head> +<body> + +<div class="layout"> + <div id="currentSlide"></div> + <div id="header"></div> + <div id="footer"> + <h2>[% author_name %]</h2> + <h2>[% author_email %]</h2> + <div id="controls"></div> + </div> +</div> + +<div class="slide"> + <h1>[% presentation_title %]</h1> + <h2>[% presentation_place %]</h2> + <h3>[% presentation_date %]</h3> +</div> + +[% FOREACH s = slides %] +[% s %] +[% END %] +</body> +</html> +<!-- END s5 --> diff --git a/object_meta_programming_slides/slides/template/s5/slide.html b/object_meta_programming_slides/slides/template/s5/slide.html new file mode 100644 index 0000000..aa20d02 --- /dev/null +++ b/object_meta_programming_slides/slides/template/s5/slide.html @@ -0,0 +1,9 @@ +<!-- BEGIN slide --> +<div class="slide"> +[% image_html %] +[% slide_content %] +[%- UNLESS last -%] +<small>continued...</small> +[% END %] +</div> +<!-- END slide --> diff --git a/object_meta_programming_slides/slides/ui/bg-shade.png b/object_meta_programming_slides/slides/ui/bg-shade.png new file mode 100644 index 0000000..172c914 Binary files /dev/null and b/object_meta_programming_slides/slides/ui/bg-shade.png differ diff --git a/object_meta_programming_slides/slides/ui/bg-slide.jpg b/object_meta_programming_slides/slides/ui/bg-slide.jpg new file mode 100644 index 0000000..6be0296 Binary files /dev/null and b/object_meta_programming_slides/slides/ui/bg-slide.jpg differ diff --git a/object_meta_programming_slides/slides/ui/blank.gif b/object_meta_programming_slides/slides/ui/blank.gif new file mode 100644 index 0000000..75b945d Binary files /dev/null and b/object_meta_programming_slides/slides/ui/blank.gif differ diff --git a/object_meta_programming_slides/slides/ui/bodybg.gif b/object_meta_programming_slides/slides/ui/bodybg.gif new file mode 100644 index 0000000..5f448a1 Binary files /dev/null and b/object_meta_programming_slides/slides/ui/bodybg.gif differ diff --git a/object_meta_programming_slides/slides/ui/framing.css b/object_meta_programming_slides/slides/ui/framing.css new file mode 100644 index 0000000..0fc59a5 --- /dev/null +++ b/object_meta_programming_slides/slides/ui/framing.css @@ -0,0 +1,24 @@ +/* The following styles size and place the slide components. + Edit them if you want to change the overall slide layout. + The commented lines can be uncommented (and modified, if necessary) + to help you with the rearrangement process. */ + +div#header, div#footer, div.slide {width: 100%; top: 0; left: 0;} +div#header {top: 0; left: 0; z-index: 1;} +div#footer {top: auto; bottom: 0; width: 100%; z-index: 5;} +div.slide {top: 0; width: 88%; padding: 1em 7% 2em 5%; z-index: 2;} + +div#controls {bottom: 1em; left: 0; width: 100%; text-align: center; z-index: 1000;} +div#controls form {margin: 0; padding: 0;} + +#currentSlide {position: absolute; left: 0; bottom: 0.5em; z-index: 10; + width: 100%; text-align: center;} +html>body #currentSlide {position: fixed;} + +/* +div#header {background: #FCC;} +div#footer {background: #CCF;} +div#controls {background: #BBD;} +div#currentSlide {background: #FFC;} +*/ + diff --git a/object_meta_programming_slides/slides/ui/iepngfix.htc b/object_meta_programming_slides/slides/ui/iepngfix.htc new file mode 100644 index 0000000..1e9d213 --- /dev/null +++ b/object_meta_programming_slides/slides/ui/iepngfix.htc @@ -0,0 +1,83 @@ +<public:component> + +<public:attach event="onpropertychange" onevent="doFix()" /> + + + +<script> + + + +// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com + +// Free usage permitted as long as this notice remains intact. + + + +// This must be a path to a blank image. That's all the configuration you need here. + +var blankImg = 'blank.gif'; + + + +var f = 'DXImageTransform.Microsoft.AlphaImageLoader'; + + + +function filt(s, m) { + + if (filters[f]) { + + filters[f].enabled = s ? true : false; + + if (s) with (filters[f]) { src = s; sizingMethod = m } + + } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")'; + +} + + + +function doFix() { + + if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) || + + (event && !/(background|src)/.test(event.propertyName))) return; + + + + if (tagName == 'IMG') { + + if ((/\.png$/i).test(src)) { + + filt(src, 'image'); // was 'scale' + + src = blankImg; + + } else if (src.indexOf(blankImg) < 0) filt(); + + } else if (style.backgroundImage) { + + if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) { + + var s = RegExp.$1; + + style.backgroundImage = ''; + + filt(s, 'crop'); + + } else filt(); + + } + +} + + + +doFix(); + + + +</script> + +</public:component> diff --git a/object_meta_programming_slides/slides/ui/opera.css b/object_meta_programming_slides/slides/ui/opera.css new file mode 100644 index 0000000..24921ba --- /dev/null +++ b/object_meta_programming_slides/slides/ui/opera.css @@ -0,0 +1,7 @@ +/* DO NOT CHANGE THESE unless you really want to break Opera Show */ +div.slide { + visibility: visible !important; + position: static !important; + page-break-before: always; +} +#slide0 {page-break-before: avoid;} diff --git a/object_meta_programming_slides/slides/ui/outline.css b/object_meta_programming_slides/slides/ui/outline.css new file mode 100644 index 0000000..56cfb32 --- /dev/null +++ b/object_meta_programming_slides/slides/ui/outline.css @@ -0,0 +1,16 @@ +/* don't change this unless you want the layout stuff to show up in the outline view! */ + +.layout div, #footer *, #controlForm * {display: none;} +#footer, #controls, #controlForm, #navLinks, #toggle { + display: block; visibility: visible; margin: 0; padding: 0;} +#toggle {float: right; padding: 0.5em;} +html>body #toggle {position: fixed; top: 0; right: 0;} + +/* making the outline look pretty-ish */ + +#slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;} +#slide0 h1 {padding-top: 1.5em;} +.slide h1 {margin: 1.5em 0 0; padding-top: 0.25em; + border-top: 1px solid #888; border-bottom: 1px solid #AAA;} +#toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;} + diff --git a/object_meta_programming_slides/slides/ui/pngbehavior.htc b/object_meta_programming_slides/slides/ui/pngbehavior.htc new file mode 100644 index 0000000..882e925 --- /dev/null +++ b/object_meta_programming_slides/slides/ui/pngbehavior.htc @@ -0,0 +1,87 @@ +<public:component lightWeight="true"> +<public:attach event="onpropertychange" onevent="propertyChanged()" /> +<public:attach event="onbeforeprint" onevent="beforePrint()" for="window"/> +<public:attach event="onafterprint" onevent="afterPrint()" for="window"/> +<script> + +/* + * PNG Behavior + * + * This script was created by Erik Arvidsson (http://webfx.eae.net/contact.html#erik) + * for WebFX (http://webfx.eae.net) + * Copyright 2002-2004 + * + * For usage see license at http://webfx.eae.net/license.html + * + * Version: 1.02 + * Created: 2001-??-?? First working version + * Updated: 2002-03-28 Fixed issue when starting with a non png image and + * switching between non png images + * 2003-01-06 Fixed RegExp to correctly work with IE 5.0x + * 2004-05-09 When printing revert to original + * + */ + +var supported = /MSIE ((5\.5)|[6789])/.test(navigator.userAgent) && + navigator.platform == "Win32"; + +var realSrc; +var blankSrc = "blank.gif"; +var isPrinting = false; + +if (supported) fixImage(); + +function propertyChanged() { + if (!supported || isPrinting) return; + + var pName = event.propertyName; + if (pName != "src") return; + // if not set to blank + if (!new RegExp(blankSrc).test(src)) + fixImage(); +}; + +function fixImage() { + // get src + var src = element.src; + + // check for real change + if (src == realSrc && /\.png$/i.test(src)) { + element.src = blankSrc; + return; + } + + if ( ! new RegExp(blankSrc).test(src)) { + // backup old src + realSrc = src; + } + + // test for png + if (/\.png$/i.test(realSrc)) { + // set blank image + element.src = blankSrc; + // set filter + element.runtimeStyle.filter = "progid:DXImageTransform.Microsoft." + + "AlphaImageLoader(src='" + src + "',sizingMethod='image')"; + } + else { + // remove filter + element.runtimeStyle.filter = ""; + } +} + +function beforePrint() { + isPrinting = true; + element.src = realSrc; + element.runtimeStyle.filter = ""; + realSrc = null; +} + +function afterPrint() { + isPrinting = false; + fixImage(); +} + +</script> +</public:component> + diff --git a/object_meta_programming_slides/slides/ui/pretty.css b/object_meta_programming_slides/slides/ui/pretty.css new file mode 100644 index 0000000..f3d1585 --- /dev/null +++ b/object_meta_programming_slides/slides/ui/pretty.css @@ -0,0 +1,48 @@ +/* + Theme: i18n + Eric A. Meyer (http://meyerweb.com/) + Theme placed under CC by-sa 2.0 license +*/ + +body {background: #95A7D4 url(bg-slide.jpg) 100% 100% no-repeat; color: #210; font: 36px Arial, sans-serif; line-height: .9;} +a {text-decoration: none; color: #336; border-bottom: 1px dotted;} +h1, h2, h3, h4, h5, h6 {font-size: 1.5em; margin: 0;} +sup {font-size: 0.75em; font-weight: normal; + vertical-align: 0.5em; line-height: 1px;} +ul {margin-left: 1em; padding-left: 0; font-size: } +li {margin-bottom: 0.66em;} +li li {margin: 0.33em 0; font-size: smaller;} + +#header {background: url(bg-shade.png); border-bottom: 1px solid #333; + padding-bottom: 2em;} +#footer {background: url(bg-shade.png); color: #BBB; border-top: 1px solid #333;} +#header, #footer {font-size: 0.5em;} +#footer h1, #footer h2 { padding: 0.5em 0.75em; + font-weight: normal; font-style: italic;} +#footer h1 {left: 0; font-size: 1em; letter-spacing: 1px;} +#footer h2 {position: absolute; bottom: 0; right: 0;} + +#controls {font-size: 0.75em;} +#navList {margin-top: 3px;} +#navLinks a {margin: 0 0.33em; padding: 0 0.25em; + border: 1px solid; border-color: #CCD #556 #556 #CCD; + background-color: #8597C4;} + +#currentSlide {font-size: 0.5em;} +#currentSlide span {font-size: 13px; color: rgb(49%,47%,66%);} +#currentSlide #csSep {display: none;} +#currentSlide #csHere {font-weight: bold;} +#currentSlide #csHere:before {content: "#"; font-weight: normal;} +#currentSlide #csTotal:before {content: " of ";} + +.slide h1 {font-size: 2em; line-height: 1; letter-spacing: -1px; font-weight: +100%; + margin: 0 -15% 1em 0; padding: 0.5em 15% 0.06125em 0; border-bottom: 0.06125em solid rgb(90,94,120);} +#slide0 h1 {border: none; font-size: 2em; letter-spacing: 0; margin: 3em 0 1.5em;} +#slide0 h2 {font-size: 1em; margin: 0.5em 0 0;} +#slide0 h3 {font-size: 1em; margin: 0.5em 0 0;} +#slide0 h4 {margin-top: 0; font-size: smaller;} + +small { display: none }; + +.slide .current {color: #003; text-shadow: 0 0 0.25em #9AABD7;} + diff --git a/object_meta_programming_slides/slides/ui/pretty.css~ b/object_meta_programming_slides/slides/ui/pretty.css~ new file mode 100644 index 0000000..510b5be --- /dev/null +++ b/object_meta_programming_slides/slides/ui/pretty.css~ @@ -0,0 +1,48 @@ +/* + Theme: i18n + Eric A. Meyer (http://meyerweb.com/) + Theme placed under CC by-sa 2.0 license +*/ + +body {background: #95A7D4 url(bg-slide.jpg) 100% 100% no-repeat; color: #210; font: 36px Arial, sans-serif; line-height: .9;} +a {text-decoration: none; color: #336; border-bottom: 1px dotted;} +h1, h2, h3, h4, h5, h6 {font-size: 1.3em; margin: 0 2em;} +sup {font-size: 0.75em; font-weight: normal; + vertical-align: 0.5em; line-height: 1px;} +ul {margin-left: 1em; padding-left: 0; font-size: } +li {margin-bottom: 0.66em;} +li li {margin: 0.33em 0; font-size: smaller;} + +#header {background: url(bg-shade.png); border-bottom: 1px solid #333; + padding-bottom: 2em;} +#footer {background: url(bg-shade.png); color: #BBB; border-top: 1px solid #333;} +#header, #footer {font-size: 0.5em;} +#footer h1, #footer h2 { padding: 0.5em 0.75em; + font-weight: normal; font-style: italic;} +#footer h1 {left: 0; font-size: 1em; letter-spacing: 1px;} +#footer h2 {position: absolute; bottom: 0; right: 0;} + +#controls {font-size: 0.75em;} +#navList {margin-top: 3px;} +#navLinks a {margin: 0 0.33em; padding: 0 0.25em; + border: 1px solid; border-color: #CCD #556 #556 #CCD; + background-color: #8597C4;} + +#currentSlide {font-size: 0.5em;} +#currentSlide span {font-size: 13px; color: rgb(49%,47%,66%);} +#currentSlide #csSep {display: none;} +#currentSlide #csHere {font-weight: bold;} +#currentSlide #csHere:before {content: "#"; font-weight: normal;} +#currentSlide #csTotal:before {content: " of ";} + +.slide h1 {font-size: 2em; line-height: 1; letter-spacing: -1px; font-weight: +100%; + margin: 0 -15% 1em 0; padding: 0.5em 15% 0.06125em 0; border-bottom: 0.06125em solid rgb(90,94,120);} +#slide0 h1 {border: none; font-size: 2em; letter-spacing: 0; margin: 3em 0 1.5em;} +#slide0 h2 {font-size: 1em; } +#slide0 h3 {margin: 0.5em 0 0;} +#slide0 h4 {margin-top: 0; font-size: smaller;} + +small { display: none }; + +.slide .current {color: #003; text-shadow: 0 0 0.25em #9AABD7;} + diff --git a/object_meta_programming_slides/slides/ui/print.css b/object_meta_programming_slides/slides/ui/print.css new file mode 100644 index 0000000..027bedf --- /dev/null +++ b/object_meta_programming_slides/slides/ui/print.css @@ -0,0 +1,23 @@ +/* The next rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */ +div.slide, ul {page-break-inside: avoid; visibility: visible !important;} +h1 {page-break-after: avoid;} + +body {font-size: 12pt; background: white;} +* {color: black;} + +#slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;} +#slide0 h3 {margin: 0; padding: 0;} +#slide0 h4 {margin: 0 0 0.5em; padding: 0;} +#slide0 {margin-bottom: 3em;} + +h1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;} +.extra {background: transparent !important;} +div.extra, pre.extra, .example {font-size: 10pt; color: #333;} +ul.extra a {font-weight: bold;} +p.example {display: none;} + +#header {display: none;} +#footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;} +#footer h2, #controls {display: none;} + +#currentSlide {display: none;} diff --git a/object_meta_programming_slides/slides/ui/s5-core.css b/object_meta_programming_slides/slides/ui/s5-core.css new file mode 100644 index 0000000..bf254b8 --- /dev/null +++ b/object_meta_programming_slides/slides/ui/s5-core.css @@ -0,0 +1,10 @@ +/* Do not edit or override these styles! The system will likely break if you do. */ + +div#header, div#footer, div#controls, div.slide {position: absolute;} +html>body div#header, html>body div#footer, + html>body div#controls, html>body div.slide {position: fixed;} +.handout {display: none;} +.layout {display: block;} +div.slide, .hideme, .incremental {visibility: hidden;} +#slide0 {visibility: visible;} + diff --git a/object_meta_programming_slides/slides/ui/slides-cc.js b/object_meta_programming_slides/slides/ui/slides-cc.js new file mode 100644 index 0000000..16696a6 --- /dev/null +++ b/object_meta_programming_slides/slides/ui/slides-cc.js @@ -0,0 +1,587 @@ +// S5 v1.1 slides.js -- released under CC by-sa 2.0 license +// +// Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information +// about all the wonderful and talented contributors to this code! + +var undef; +var snum = 0; +var smax = 1; +var incpos = 0; +var number = undef; +var s5mode = true; +var slideCSS = document.getElementById('slideProj').href; +var defaultView = 'slideshow'; +var controlVis = 'visible'; + +var isIE = navigator.appName == 'Microsoft Internet Explorer' ? 1 : 0; +var isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0; +var isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0; + +function hasClass(object, className) { + if (!object.className) return false; + return (object.className.search('(^|\\s)' + className + '(\\s|$)') != -1); +} + +function hasValue(object, value) { + if (!object) return false; + return (object.search('(^|\\s)' + value + '(\\s|$)') != -1); +} + +function removeClass(object,className) { + if (!object) return; + object.className = object.className.replace(new RegExp('(^|\\s)'+className+'(\\s|$)'), RegExp.$1+RegExp.$2); +} + +function addClass(object,className) { + if (!object || hasClass(object, className)) return; + if (object.className) { + object.className += ' '+className; + } else { + object.className = className; + } +} + +function GetElementsWithClassName(elementName,className) { + var allElements = document.getElementsByTagName(elementName); + var elemColl = new Array(); + for (var i = 0; i< allElements.length; i++) { + if (hasClass(allElements[i], className)) { + elemColl[elemColl.length] = allElements[i]; + } + } + return elemColl; +} + +function isParentOrSelf(element, id) { + if (element == null || element.nodeName=='BODY') return false; + else if (element.id == id) return true; + else return isParentOrSelf(element.parentNode, id); +} + +function nodeValue(node) { + var result = ""; + if (node.nodeType == 1) { + var children = node.childNodes; + for (var i = 0; i < children.length; ++i) { + result += nodeValue(children[i]); + } + } + else if (node.nodeType == 3) { + result = node.nodeValue; + } + return(result); +} + +function slideLabel() { + var slideColl = GetElementsWithClassName('*','slide'); + var list = document.getElementById('jumplist'); + smax = slideColl.length; + for (var n = 0; n < smax; n++) { + var obj = slideColl[n]; + + var did = 'slide' + n.toString(); + obj.setAttribute('id',did); + if (isOp) continue; + + var otext = ''; + var menu = obj.firstChild; + if (!menu) continue; // to cope with empty slides + while (menu && menu.nodeType == 3) { + menu = menu.nextSibling; + } + if (!menu) continue; // to cope with slides with only text nodes + + var menunodes = menu.childNodes; + for (var o = 0; o < menunodes.length; o++) { + otext += nodeValue(menunodes[o]); + } + list.options[list.length] = new Option(n + ' : ' + otext, n); + } +} + +function currentSlide() { + var cs; + if (document.getElementById) { + cs = document.getElementById('currentSlide'); + } else { + cs = document.currentSlide; + } + cs.innerHTML = '<span id="csHere">' + snum + '<\/span> ' + + '<span id="csSep">\/<\/span> ' + + '<span id="csTotal">' + (smax-1) + '<\/span>'; + if (snum == 0) { + cs.style.visibility = 'hidden'; + } else { + cs.style.visibility = 'visible'; + } +} + +function go(step) { + if (document.getElementById('slideProj').disabled || step == 0) return; + var jl = document.getElementById('jumplist'); + var cid = 'slide' + snum; + var ce = document.getElementById(cid); + if (incrementals[snum].length > 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + removeClass(incrementals[snum][i], 'current'); + removeClass(incrementals[snum][i], 'incremental'); + } + } + if (step != 'j') { + snum += step; + lmax = smax - 1; + if (snum > lmax) snum = lmax; + if (snum < 0) snum = 0; + } else + snum = parseInt(jl.value); + var nid = 'slide' + snum; + var ne = document.getElementById(nid); + if (!ne) { + ne = document.getElementById('slide0'); + snum = 0; + } + if (step < 0) {incpos = incrementals[snum].length} else {incpos = 0;} + if (incrementals[snum].length > 0 && incpos == 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + if (hasClass(incrementals[snum][i], 'current')) + incpos = i + 1; + else + addClass(incrementals[snum][i], 'incremental'); + } + } + if (incrementals[snum].length > 0 && incpos > 0) + addClass(incrementals[snum][incpos - 1], 'current'); + ce.style.visibility = 'hidden'; + ne.style.visibility = 'visible'; + jl.selectedIndex = snum; + currentSlide(); + number = 0; +} + +function goTo(target) { + if (target >= smax || target == snum) return; + go(target - snum); +} + +function subgo(step) { + if (step > 0) { + removeClass(incrementals[snum][incpos - 1],'current'); + removeClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos],'current'); + incpos++; + } else { + incpos--; + removeClass(incrementals[snum][incpos],'current'); + addClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos - 1],'current'); + } +} + +function toggle() { + var slideColl = GetElementsWithClassName('div','slide'); + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + if (!slides.disabled) { + slides.disabled = true; + outline.disabled = false; + s5mode = false; + fontSize('1em'); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'visible'; + } + } else { + slides.disabled = false; + outline.disabled = true; + s5mode = true; + fontScale(); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'hidden'; + } + slideColl[snum].style.visibility = 'visible'; + } +} + +function showHide(action) { + var obj = GetElementsWithClassName('*','hideme')[0]; + switch (action) { + case 's': obj.style.visibility = 'visible'; break; + case 'h': obj.style.visibility = 'hidden'; break; + case 'k': + if (obj.style.visibility != 'visible') { + obj.style.visibility = 'visible'; + } else { + obj.style.visibility = 'hidden'; + } + break; + } +} + +// 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/) +function keys(key) { + if (!key) { + key = event; + key.which = key.keyCode; + } + if (key.which == 84) { + toggle(); + return; + } + if (s5mode) { + switch (key.which) { + case 10: // return + case 13: // enter + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + if(number != undef) { + goTo(number); + break; + } + case 32: // spacebar + case 34: // page down + case 39: // rightkey + case 40: // downkey + if(number != undef) { + go(number); + } else if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + break; + case 33: // page up + case 37: // leftkey + case 38: // upkey + if(number != undef) { + go(-1 * number); + } else if (!incrementals[snum] || incpos <= 0) { + go(-1); + } else { + subgo(-1); + } + break; + case 67: // c + showHide('k'); + break; + } + if (key.which < 48 || key.which > 57) { + number = undef; + } else { + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + number = (((number != undef) ? number : 0) * 10) + (key.which - 48); + } + } +} + +function clicker(e) { + number = undef; + var target; + if (window.event) { + target = window.event.srcElement; + e = window.event; + } else target = e.target; + if (target.getAttribute('href') != null || hasValue(target.rel, 'external') || isParentOrSelf(target, 'controls') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object')) return true; + if (!e.which || e.which == 1) { + if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + } +} + +function findSlide(hash) { + var target = null; + var slides = GetElementsWithClassName('*','slide'); + for (var i = 0; i < slides.length; i++) { + var targetSlide = slides[i]; + if ( (targetSlide.name && targetSlide.name == hash) + || (targetSlide.id && targetSlide.id == hash) ) { + target = targetSlide; + break; + } + } + while(target != null && target.nodeName != 'BODY') { + if (hasClass(target, 'slide')) { + return parseInt(target.id.slice(5)); + } + target = target.parentNode; + } + return null; +} + +function slideJump() { + if (window.location.hash == null) return; + var sregex = /^#slide(\d+)$/; + var matches = sregex.exec(window.location.hash); + var dest = null; + if (matches != null) { + dest = parseInt(matches[1]); + } else { + dest = findSlide(window.location.hash.slice(1)); + } + if (dest != null) + go(dest - snum); +} + +function fixLinks() { + var thisUri = window.location.href; + thisUri = thisUri.slice(0, thisUri.length - window.location.hash.length); + var aelements = document.getElementsByTagName('A'); + for (var i = 0; i < aelements.length; i++) { + var a = aelements[i].href; + var slideID = a.match('\#slide[0-9]{1,2}'); + if ((slideID) && (slideID[0].slice(0,1) == '#')) { + var dest = findSlide(slideID[0].slice(1)); + if (dest != null) { + if (aelements[i].addEventListener) { + aelements[i].addEventListener("click", new Function("e", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "if (e.preventDefault) e.preventDefault();"), true); + } else if (aelements[i].attachEvent) { + aelements[i].attachEvent("onclick", new Function("", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "event.returnValue = false;")); + } + } + } + } +} + +function externalLinks() { + if (!document.getElementsByTagName) return; + var anchors = document.getElementsByTagName('a'); + for (var i=0; i<anchors.length; i++) { + var anchor = anchors[i]; + if (anchor.getAttribute('href') && hasValue(anchor.rel, 'external')) { + anchor.target = '_blank'; + addClass(anchor,'external'); + } + } +} + +function createControls() { + var controlsDiv = document.getElementById("controls"); + if (!controlsDiv) return; + var hider = ' onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"'; + var hideDiv, hideList = ''; + if (controlVis == 'hidden') { + hideDiv = hider; + } else { + hideList = hider; + } + controlsDiv.innerHTML = '<form action="#" id="controlForm"' + hideDiv + '>' + + '<div id="navLinks">' + + '<a accesskey="t" id="toggle" href="javascript:toggle();">Ø<\/a>' + + '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' + + '<a accesskey="x" id="next" href="javascript:go(1);">»<\/a>' + + '<div id="navList"' + hideList + '><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>' + + '<\/div><\/form>'; + if (controlVis == 'hidden') { + var hidden = document.getElementById('navLinks'); + } else { + var hidden = document.getElementById('jumplist'); + } + addClass(hidden,'hideme'); +} + +function fontScale() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers + if (!s5mode) return false; + var vScale = 22; // both yield 32 (after rounding) at 1024x768 + var hScale = 32; // perhaps should auto-calculate based on theme's declared value? + if (window.innerHeight) { + var vSize = window.innerHeight; + var hSize = window.innerWidth; + } else if (document.documentElement.clientHeight) { + var vSize = document.documentElement.clientHeight; + var hSize = document.documentElement.clientWidth; + } else if (document.body.clientHeight) { + var vSize = document.body.clientHeight; + var hSize = document.body.clientWidth; + } else { + var vSize = 700; // assuming 1024x768, minus chrome and such + var hSize = 1024; // these do not account for kiosk mode or Opera Show + } + var newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale)); + fontSize(newSize + 'px'); + if (isGe) { // hack to counter incremental reflow bugs + var obj = document.getElementsByTagName('body')[0]; + obj.style.display = 'none'; + obj.style.display = 'block'; + } +} + +function fontSize(value) { + if (!(s5ss = document.getElementById('s5ss'))) { + if (!isIE) { + document.getElementsByTagName('head')[0].appendChild(s5ss = document.createElement('style')); + s5ss.setAttribute('media','screen, projection'); + s5ss.setAttribute('id','s5ss'); + } else { + document.createStyleSheet(); + document.s5ss = document.styleSheets[document.styleSheets.length - 1]; + } + } + if (!isIE) { + while (s5ss.lastChild) s5ss.removeChild(s5ss.lastChild); + s5ss.appendChild(document.createTextNode('body {font-size: ' + value + ' !important;}')); + } else { + document.s5ss.addRule('body','font-size: ' + value + ' !important;'); + } +} + +function notOperaFix() { + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + slides.setAttribute('media','screen'); + outline.disabled = true; + if (isGe) { + slides.setAttribute('href','null'); // Gecko fix + slides.setAttribute('href',slideCSS); // Gecko fix + } +} + +function getIncrementals(obj) { + var incrementals = new Array(); + if (!obj) + return incrementals; + var children = obj.childNodes; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (hasClass(child, 'incremental')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'incremental'); + for (var j = 0; j < child.childNodes.length; j++) { + if (child.childNodes[j].nodeType == 1) { + addClass(child.childNodes[j], 'incremental'); + } + } + } else { + incrementals[incrementals.length] = child; + removeClass(child,'incremental'); + } + } + if (hasClass(child, 'show-first')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'show-first'); + if (child.childNodes[isGe].nodeType == 1) { + removeClass(child.childNodes[isGe], 'incremental'); + } + } else { + incrementals[incrementals.length] = child; + } + } + incrementals = incrementals.concat(getIncrementals(child)); + } + return incrementals; +} + +function createIncrementals() { + var incrementals = new Array(); + for (var i = 0; i < smax; i++) { + incrementals[i] = getIncrementals(document.getElementById('slide'+i)); + } + return incrementals; +} + +function defaultCheck() { + var allMetas = document.getElementsByTagName('meta'); + for (var i = 0; i< allMetas.length; i++) { + if (allMetas[i].name == 'defaultView') { + defaultView = allMetas[i].content; + } + if (allMetas[i].name == 'controlVis') { + controlVis = allMetas[i].content; + } + } +} + +// Key trap fix, new function body for trap() +function trap(e) { + if (!e) { + e = event; + e.which = e.keyCode; + } + try { + modifierKey = e.ctrlKey || e.altKey || e.metaKey; + } + catch(e) { + modifierKey = false; + } + return modifierKey || e.which == 0; +} + +function startup() { + defaultCheck(); + if (!isOp) createControls(); + slideLabel(); + fixLinks(); + externalLinks(); + fontScale(); + if (!isOp) { + notOperaFix(); + incrementals = createIncrementals(); + slideJump(); + if (defaultView == 'outline') { + toggle(); + } + document.onkeyup = keys; + document.onkeypress = trap; + document.onclick = clicker; + } +} + + +//IE/Win PNG transparency hack -- ONLY WORKS FOR FOREGROUND IMAGES! +/*@cc_on +@if (@_win16 != @_win16) +@set @_win16 = false +@end +@if (@_win32 != @_win32) +@set @_win32 = false +@end +@if (@_jscript_version >= 5.5 && (@_win32 || @_win16)) +window.attachEvent( + 'onload', function() { + for (var i = 0; i < document.images.length; i++) { + var img = document.images[i]; + var len = img.src.length; + if ('.PNG' == img.src.substring(len - 4, len).toUpperCase()) { + var span = { + id: img.id + ,className: img.className + ,title: (img.title) ? img.title : img.alt + ,style: 'display:inline-block;width:' + + img.width + 'px;height:' + img.height + 'px;' + + 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + + img.src + '\',sizingMethod=\'scale\');' + ,toString: function() { + return '<span ' + + ((this.id) ? 'id="' + this.id + '" ' : '') + + ((this.className) ? 'class="' + this.className + '" ' : '') + + 'title="' + this.title + '" ' + + 'style="' + this.style + '"><\/span>'; + } + } + if ('left' == img.align) + span.style += 'float:left;'; + if ('right' == img.align) + span.style += 'float:right;'; + if (img.parentElement.href) + span.style += 'cursor:hand;'; + if (0 != img.style.cssText.length) + span.style = img.currentStyle + ';' + span.style; + img.outerHTML = span + ''; + i--; + } + } + } + ); +@end @*/ + +window.onload = startup; +window.onresize = function(){setTimeout('fontScale()', 50);} diff --git a/object_meta_programming_slides/slides/ui/slides.css b/object_meta_programming_slides/slides/ui/slides.css new file mode 100644 index 0000000..328db3b --- /dev/null +++ b/object_meta_programming_slides/slides/ui/slides.css @@ -0,0 +1,4 @@ +@import url(s5-core.css); /* required to make the slide show run at all */ +@import url(framing.css); /* sets basic placement and size of slide components */ +@import url(pretty.css); /* stuff that makes the slides look better than blah */ + diff --git a/object_meta_programming_slides/slides/ui/slides.js b/object_meta_programming_slides/slides/ui/slides.js new file mode 100644 index 0000000..da1cd4d --- /dev/null +++ b/object_meta_programming_slides/slides/ui/slides.js @@ -0,0 +1,260 @@ +// S5 slides.js -- released under CC by-sa 2.0 license +// +// Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information +// about all the wonderful and talented contributors to this code! + +var snum = 0; +var smax = 1; +var undef; +var slcss = 1; +var isIE = navigator.appName == 'Microsoft Internet Explorer' ? 1 : 0; +var isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0; +var isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0; +var slideCSS = document.getElementById('slideProj').href; + +function isClass(object, className) { + return (object.className.search('(^|\\s)' + className + '(\\s|$)') != -1); +} + +function GetElementsWithClassName(elementName,className) { + var allElements = document.getElementsByTagName(elementName); + var elemColl = new Array(); + for (i = 0; i< allElements.length; i++) { + if (isClass(allElements[i], className)) { + elemColl[elemColl.length] = allElements[i]; + } + } + return elemColl; +} + +function isParentOrSelf(element, id) { + if (element == null || element.nodeName=='BODY') return false; + else if (element.id == id) return true; + else return isParentOrSelf(element.parentNode, id); +} + +function nodeValue(node) { + var result = ""; + if (node.nodeType == 1) { + var children = node.childNodes; + for ( i = 0; i < children.length; ++i ) { + result += nodeValue(children[i]); + } + } + else if (node.nodeType == 3) { + result = node.nodeValue; + } + return(result); +} + +function slideLabel() { + var slideColl = GetElementsWithClassName('div','slide'); + var list = document.getElementById('jumplist'); + smax = slideColl.length; + for (n = 0; n < smax; n++) { + var obj = slideColl[n]; + + var did = 'slide' + n.toString(); + obj.setAttribute('id',did); + if(isOp) continue; + + var otext = ''; + var menu = obj.firstChild; + if (!menu) continue; // to cope with empty slides + while (menu && menu.nodeType == 3) { + menu = menu.nextSibling; + } + if (!menu) continue; // to cope with slides with only text nodes + + var menunodes = menu.childNodes; + for (o = 0; o < menunodes.length; o++) { + otext += nodeValue(menunodes[o]); + } + list.options[list.length] = new Option(n+' : ' +otext,n); + } +} + +function currentSlide() { + var cs; + if (document.getElementById) { + cs = document.getElementById('currentSlide'); + } else { + cs = document.currentSlide; + } + cs.innerHTML = '<span id="csHere">' + snum + '<\/span> ' + + '<span id="csSep">\/<\/span> ' + + '<span id="csTotal">' + (smax-1) + '<\/span>'; + if (snum == 0) { + cs.style.visibility = 'hidden'; + } else { + cs.style.visibility = 'visible'; + } +} + +function go(inc) { + if (document.getElementById("slideProj").disabled) return; + var cid = 'slide' + snum; + if (inc != 'j') { + snum += inc; + lmax = smax - 1; + if (snum > lmax) snum = 0; + if (snum < 0) snum = lmax; + } else { + snum = parseInt(document.getElementById('jumplist').value); + } + var nid = 'slide' + snum; + var ne = document.getElementById(nid); + if (!ne) { + ne = document.getElementById('slide0'); + snum = 0; + } + document.getElementById(cid).style.visibility = 'hidden'; + ne.style.visibility = 'visible'; + document.getElementById('jumplist').selectedIndex = snum; + currentSlide(); +} + +function toggle() { + var slideColl = GetElementsWithClassName('div','slide'); + var obj = document.getElementById('slideProj'); + if (!obj.disabled) { + obj.disabled = true; + for (n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'visible'; + } + } else { + obj.disabled = false; + for (n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'hidden'; + } + slideColl[snum].style.visibility = 'visible'; + } +} + +function showHide(action) { + var obj = document.getElementById('jumplist'); + switch (action) { + case 's': obj.style.visibility = 'visible'; break; + case 'h': obj.style.visibility = 'hidden'; break; + case 'k': + if (obj.style.visibility != 'visible') { + obj.style.visibility = 'visible'; + } else { + obj.style.visibility = 'hidden'; + } + break; + } +} + +// 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/) +function keys(key) { + if (!key) { + key = event; + key.which = key.keyCode; + } + switch (key.which) { + case 10: // return + case 13: // enter + if (window.event && isParentOrSelf(window.event.srcElement, "controls")) return; + if (key.target && isParentOrSelf(key.target, "controls")) return; + case 32: // spacebar + case 34: // page down + case 39: // rightkey + case 40: // downkey + go(1); + break; + case 33: // page up + case 37: // leftkey + case 38: // upkey + go(-1); + break; + case 84: // t + toggle(); + break; + case 67: // c + showHide('k'); + break; + } +} + +function clicker(e) { + var target; + if (window.event) { + target = window.event.srcElement; + e = window.event; + } else target = e.target; + if (target.href != null || isParentOrSelf(target, 'controls')) return true; + if (!e.which || e.which == 1) go(1); +} + +function slideJump() { + if (window.location.hash == null) return; + var sregex = /^#slide(\d+)$/; + var matches = sregex.exec(window.location.hash); + var dest = null; + if (matches != null) { + dest = parseInt(matches[1]); + } else { + var target = window.location.hash.slice(1); + var targetElement = null; + var aelements = document.getElementsByTagName("a"); + for (i = 0; i < aelements.length; i++) { + var aelement = aelements[i]; + if ( (aelement.name && aelement.name == target) + || (aelement.id && aelement.id == target) ) { + targetElement = aelement; + break; + } + } + while(targetElement != null && targetElement.nodeName != "body") { + if (targetElement.className == "slide") break; + targetElement = targetElement.parentNode; + } + if (targetElement != null && targetElement.className == "slide") { + dest = parseInt(targetElement.id.slice(1)); + } + } + if (dest != null) + go(dest - snum); + } + +function createControls() { + controlsDiv = document.getElementById("controls"); + if (!controlsDiv) return; + controlsDiv.innerHTML = '<form action="#" id="controlForm">' + + '<div>' + + '<a accesskey="t" id="toggle" href="javascript:toggle();">Ø<\/a>' + + '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' + + '<a accesskey="x" id="next" href="javascript:go(1);">»<\/a>' + + '<\/div>' + + '<div onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>' + + '<\/form>'; +} + +function notOperaFix() { + var obj = document.getElementById('slideProj'); + obj.setAttribute('media','screen'); + if (isGe) { + obj.setAttribute('href','null'); // Gecko fix + obj.setAttribute('href',slideCSS); // Gecko fix + } +} + +function startup() { + if (!isOp) createControls(); + slideLabel(); + if (!isOp) { + notOperaFix(); + slideJump(); + document.onkeyup = keys; + document.onclick = clicker; + } +} + +window.onload = startup; + + + + diff --git a/object_meta_programming_slides/template/tt2/bottom.html b/object_meta_programming_slides/template/tt2/bottom.html new file mode 100644 index 0000000..7bfac8f --- /dev/null +++ b/object_meta_programming_slides/template/tt2/bottom.html @@ -0,0 +1,24 @@ +<!-- BEGIN bottom --> +<div id="bottombar"> +<table width="100%"> +<tr> +<td align="left" valign="middle"> + <div[% show_controls ? '' : ' style="display:none"' %]> + <a accesskey='p' href="[% prev_slide %]">[% link_previous %]</a> | + <a accesskey='i' href="[% index_slide %]">[% link_index %]</a> | + <a accesskey='n' href="[% next_slide %]">[% link_next %]</a> + </div> +</td> +<td align="right" valign="middle"> + [% copyright_string %] +</td> +</tr> +</table> +</div> +<div id="logo"></div> +<div class="spacer"> +<a name="end"></a> +</div> +</body> +</html> + diff --git a/object_meta_programming_slides/template/tt2/controls.js b/object_meta_programming_slides/template/tt2/controls.js new file mode 100644 index 0000000..79b7fb0 --- /dev/null +++ b/object_meta_programming_slides/template/tt2/controls.js @@ -0,0 +1,52 @@ +// BEGIN controls.js +function nextSlide() { + window.location = '[% next_slide %]'; +} + +function prevSlide() { + window.location = '[% prev_slide %]'; +} + +function indexSlide() { + window.location = 'index.html'; +} + +function startSlide() { + window.location = 'start.html'; +} + +function closeSlide() { + window.close(); +} + +function handleKey(e) { + var key; + if (e == null) { + // IE + key = event.keyCode + } + else { + // Mozilla + if (e.altKey || e.ctrlKey) { + return true + } + key = e.which + } + switch(key) { + case 8: prevSlide(); break + case 13: nextSlide(); break + case 32: nextSlide(); break + case 81: closeSlide(); break + case 105: indexSlide(); break + case 110: nextSlide(); break + case 112: prevSlide(); break + case 115: startSlide(); break + default: //xxx(e.which) + } +} + +document.onkeypress = handleKey +[% IF mouse_controls -%] +document.onclick = nextSlide +[% END -%] +// END controls.js diff --git a/object_meta_programming_slides/template/tt2/index.html b/object_meta_programming_slides/template/tt2/index.html new file mode 100644 index 0000000..2ec1abd --- /dev/null +++ b/object_meta_programming_slides/template/tt2/index.html @@ -0,0 +1,12 @@ +<!-- BEGIN index --> +[% INCLUDE top.html %] +<div id="content"> +<div class="top_spacer"></div> +<ol> +[% FOR slide = slides -%] +<li><a href="[% slide.slide_name %]">[% slide.slide_heading %]</a></li> +[% END -%] +</ol> +</div> +[% INCLUDE bottom.html %] +<!-- END index --> diff --git a/object_meta_programming_slides/template/tt2/slide.css b/object_meta_programming_slides/template/tt2/slide.css new file mode 100644 index 0000000..816e61c --- /dev/null +++ b/object_meta_programming_slides/template/tt2/slide.css @@ -0,0 +1,93 @@ +/* BEGIN index.css */ +hr { + color: #202040; + height: 0px; + border-top: 0px; + border-bottom: 3px #202040 ridge; + border-left: 0px; + border-right: 0px; +} + +a:link { + color: #123422; + text-decoration: none; +} + +a:visited { + color: #123333; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +p { + font-size: 24pt; + margin: 6pt; +} + +div p { + font-size: 18pt; + margin-top: 12pt; + margin-bottom: 12pt; + margin-left: 6pt; + margin-right: 6pt; +} + +small { + font-size: 9pt; + font-style: italic; +} + +#topbar { + background: [% banner_bgcolor %]; + color: blue; + position:absolute; + right: 5px; + left: 5px; + top: 5px; + height: 50px; +} + +#bottombar { + background: [% banner_bgcolor %]; + color: blue; + position: fixed; + right: 5px; + left: 5px; + bottom: 5px; + height: 50px; + z-index: 0; +} + +.top_spacer { + height: 0px; + margin: 0px 0px 0px 0px; + padding: 1px 0px 0px 0px; +} + +.spacer { + bottom: 5px; + height: 50px; +} + +#content { + background:#fff; + margin-left: 20px; + margin-right:20px; + margin-top: 80px; +} + + +#logo { + position: fixed; + right: 40px; + bottom: 51px; + width: 130px; + height: 150px; + z-index:3; + background-image: url([% images_directory %]/[% logo_image %]); + background-repeat: no-repeat; +} +/* END index.css */ diff --git a/object_meta_programming_slides/template/tt2/slide.html b/object_meta_programming_slides/template/tt2/slide.html new file mode 100644 index 0000000..6147795 --- /dev/null +++ b/object_meta_programming_slides/template/tt2/slide.html @@ -0,0 +1,12 @@ +<!-- BEGIN slide --> +[% INCLUDE top.html %] +<div id="content"> +<div class="top_spacer"></div> +[% image_html %] +[% slide_content -%] +[%- UNLESS last -%] +<small>continued...</small> +[% END %] +</div> +[% INCLUDE bottom.html %] +<!-- END slide --> diff --git a/object_meta_programming_slides/template/tt2/start.html b/object_meta_programming_slides/template/tt2/start.html new file mode 100644 index 0000000..1d9ac56 --- /dev/null +++ b/object_meta_programming_slides/template/tt2/start.html @@ -0,0 +1,16 @@ +<!-- BEGIN start --> +[% INCLUDE top.html %] +<div id="content"> +<div class="top_spacer"></div> +<center> +<h4>[% presentation_title %]</h4> +<p /> +<h4>[% author_name %]</h4> +<h4>[% author_email %]</h4> +<p /> +<h4>[% presentation_place %]</h4> +<h4>[% presentation_date %]</h4> +</center> +</div> +[% INCLUDE bottom.html %] +<!-- END start --> diff --git a/object_meta_programming_slides/template/tt2/top.html b/object_meta_programming_slides/template/tt2/top.html new file mode 100644 index 0000000..aa7e74c --- /dev/null +++ b/object_meta_programming_slides/template/tt2/top.html @@ -0,0 +1,33 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml11.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>[% slide_heading %]</title> +<meta name="Content-Type" content="text/html; charset=[% character_encoding %]" /> +<meta name="generator" content="[% spork_version %]" /> +<link rel='icon' href='favicon.png' /> +[% FOR css_file = hub.css.files -%] + <link rel="stylesheet" type="text/css" href="[% css_file %]" /> +[% END -%] +<style type="text/css"><!-- +[% INCLUDE slide.css %] +--></style> +<script type="text/javascript"> +[% INCLUDE controls.js %] +</script> +</head> +<body> +<div id="topbar"> +<table width='100%'> +<tr> +<td width="13%">[% presentation_topic %]</td> +<td align="center" width="73%"> + <a accesskey="s" href="start.html">[% presentation_title %]</a> +</td> +<td align="right" width="13%"> + [% slide_num ? "#$slide_num" : ' ' %] +</td> +</tr> +</table> +</div> +<!-- END top --> diff --git a/oscon/moose.xul b/oscon/moose.xul new file mode 100644 index 0000000..9e5a5b7 --- /dev/null +++ b/oscon/moose.xul @@ -0,0 +1,525 @@ +<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="chrome://global/skin/" type="text/css"?><?xml-stylesheet href="takahashi.css" type="text/css"?><page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="presentation" xmlns:html="http:/www.w3.org/1999/xhtml" orient="vertical" onkeypress="Presentation.onKeyPress(event);"> +<html:textarea id="builtinCode" style="visibility: collapse"><![CDATA[ +Moose +---- +A Postmodern +Object System +for Perl 5 +---- +Stevan Little +stevan@cpan.org +http://moose.perl.org/ +---- +What is +Moose? +---- +What is +Class::MOP? +---- +What is +a MOP?? +---- +Meta +Object +Protocol +---- +CLOS +---- +20 year old +LISP +technology +---- +Formalization +of the +object system +---- +How +classes +work +---- +How +methods +work +---- +How objects +are created +... etc. +---- +Class::MOP +is CLOS for +Perl 5 +---- +Class::MOP +is a +formalization +of Perl 5 OO +---- +Clarity & +Structure +---- +Class::MOP is +a platform for +---- +Moose +---- + package Person; + use Moose; + + has name => (is => 'rw'); + has age => (is => 'rw'); + + 1; +---- +turns on +strict & +warnings +---- +Moose::Object +in the @ISA +---- +`has` creates +accessor +called 'name' +---- +`has` creates +accessor +called 'age' +---- +*lots* +of class +metadata +---- + package Person; + use Moose; + + has name => (is => 'rw'); + has age => (is => 'rw'); + + 1; +---- +Types +---- + has name => ( + is => 'rw', + isa => 'Str', + required => 1 + ); +---- + has age => ( + is => 'rw', + isa => 'DateTime::Duration', + lazy => 1, + default => sub { + DateTime::Duration->new + } + ); +---- +Custom +Types +---- + use Moose::Util::TypeConstraints; +---- + subtype 'NonEmptyStr' + => as 'Str' + => where { length $_ > 0 }; +---- + has name => ( + is => 'rw', + isa => 'NonEmptyStr', + required => 1 + ); +---- + my $me = Person->new( + name => 'Stevan', + age => DateTime::Duration->new( + years => 34 + ) + ); +---- + my $me = Person->new; # BOOM! name is required +---- + my $me = Person->new( + name => 'Stevan', + age => 34 + ); # BOOM! age should be DateTime::Duration +---- +Coercions +---- + class_type 'DateTime::Duration'; + coerce 'DateTime::Duration' + => from 'Int' + => via { + DateTime::Duration->new( + years => $_ + ) + }; +---- + has age => ( + is => 'rw', + isa => 'DateTime::Duration', + coerce => 1, + lazy => 1, + default => sub { + DateTime::Duration->new + } + ); +---- + my $me = Person->new( + name => 'Stevan', + age => 34 + ); +---- + coerce 'DateTime::Duration' + => from 'Int' + => via { + DateTime::Duration->new( + years => $_ + ) + } + => from 'HashRef' + => via { + DateTime::Duration->new(%$_) + }; +---- + my $me = Person->new( + name => 'Stevan', + age => { years => 34, months => 11 } + ); +---- + my $me = Person->new( + name => 'Stevan', + age => { years => 34, months => 11 } + ); + + $me->name # 'Stevan' + $me->age # DateTime::Duration object +---- + $me->name('Xoe'); + + $me->age(11); + + $me->age({ years => 11, months => 8 }); + + $me->age(DateTime::Duration->new({ + years => 11, + months => 8 + })); +---- +Delegation +---- + has age => ( + is => 'rw', + isa => 'DateTime::Duration', + coerce => 1, + lazy => 1, + default => sub { + DateTime::Duration->new + }, + handles => { + 'years_old' => 'years' + } + ); +---- + $me->years_old # 34 +---- +Unconventional +Delegation +---- + package Conference; + use Moose; + use MooseX::AttributeHelpers; + + has attendees => ( + metaclass => 'Collection::Array', + is => 'rw', + isa => 'ArrayRef[Person]', + provides => { + push => 'add_attendee', + count => 'number_of_attendees', + }, + ); +---- + my $oscon = Conference->new( + attendees => [ $me, @all_you_guys ] + ); + + $oscon->number_of_attendees; # lots of people + $oscon->add_attendee($some_slacker); # add a late comer +---- +Method Modifiers +---- + before 'add_attendee' => sub { + my ($self, $attendee) = @_; + $self->setup_more_chairs(1); + }; +---- + after 'add_attendee' => sub { + my ($self, $attendee) = @_; + $self->log("Attendee " . $attendee->name . " added"); + }; +---- + around 'add_attendee' => sub { + my ($next, $self, @args) = @_; + ... + my @return = $self->$next(@args); + ... + return @return; + }; +---- +Roles +---- +â +---- +Classes +---- +Roles +do /not/ +inherit. +---- +Inheritance is +â +vertical reuse. +---- +Roles +compose. +---- +Composition is +â +horizontal reuse. +---- +... +---- +When +to use +Roles +---- +My general rule +of thumb is ... +---- +s/MI/Roles/g +---- +When +to /not/ use +Roles +---- +When a class +just makes +more sense. +---- +Roles are /not/ a +replacement for +inheritance. +---- +How Roles +Work +---- +Roles are +orphans. +---- +Roles are +composed. +---- +Local class +overrides role. +---- +Role overrides +inherited class. +---- +Roles can +conflict. +---- +Method conflicts +must be +disambiguated. +---- +Attribute conflicts +cannot be +disambiguated. +---- + package Age; + use Moose::Role; + + # ... all that type stuff + + has age => ( + is => 'rw', + isa => 'DateTime::Duration', + coerce => 1, + lazy => 1, + default => sub { + DateTime::Duration->new + }, + handles => { + 'years_old' => 'years' + } + ); + + 1; +---- + package Person; + use Moose; + + with 'Age'; + + # ... +---- +Conclusion +---- +Moose code is shorter +---- +less code == less bugs +---- +Less testing +---- +Moose/Class::MOP +have +5400 +tests and growing +---- +Why test, when +Moose already does. +---- +More Readable +---- +]]></html:textarea> + +<deck flex="1" id="deck"> + +<vbox flex="1" + onmousemove="Presentation.onMouseMoveOnCanvas(event);"> + <toolbox id="canvasToolbar"> + <toolbar> + <toolbarbutton oncommand="Presentation.home()" label="|<<" + observes="canBack"/> + <toolbarbutton oncommand="Presentation.back()" label="<" + observes="canBack"/> + <toolbarbutton oncommand="Presentation.forward()" label=">" + observes="canForward"/> + <toolbarbutton oncommand="Presentation.end()" label=">>|" + observes="canForward"/> + <toolbarseparator/> + <hbox align="center"> + <textbox id="current_page" size="4" + oninput="if (this.value) Presentation.showPage(parseInt(this.value)-1);"/> + <description value="/"/> + <description id="max_page"/> + </hbox> + <toolbarseparator/> + <vbox flex="2"> + <spacer flex="1"/> + <scrollbar id="scroller" + align="center" orient="horizontal" + oncommand="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));" + onclick="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));" + onmousedown="Presentation.onScrollerDragStart();" + onmousemove="Presentation.onScrollerDragMove();" + onmouseup="Presentation.onScrollerDragDrop();"/> + <spacer flex="1"/> + </vbox> + <toolbarseparator/> + <spacer flex="1"/> + <toolbarseparator/> + <toolbarbutton id="toggleEva" label="Eva" + type="checkbox" + autoCheck="false" + oncommand="Presentation.toggleEvaMode();"/> + <toolbarseparator/> + <toolbarbutton label="Edit" + oncommand="Presentation.toggleEditMode();"/> + <toolbarbutton oncommand="Presentation.reload();" label="Reload"/> + </toolbar> + </toolbox> + <vbox flex="1" id="canvas" + onclick="Presentation.onPresentationClick(event);"> + <spacer flex="1"/> + <hbox flex="1"> + <spacer flex="1"/> + <vbox id="content"/> + <spacer flex="1"/> + </hbox> + <spacer flex="1"/> + </vbox> +</vbox> + + +<vbox flex="1" id="edit"> + <toolbox> + <toolbar> + <toolbarbutton label="New Page" + oncommand="Presentation.addPage()"/> + <spacer flex="1"/> + <toolbarseparator/> + <toolbarbutton label="View" + oncommand="Presentation.toggleEditMode();"/> + <toolbarbutton oncommand="Presentation.reload();" label="Reload"/> + </toolbar> + </toolbox> + <textbox id="textField" flex="1" multiline="true" + oninput="Presentation.onEdit()"/> + <hbox collapsed="true"> + <iframe id="dataLoader" onload="if (window.Presentation) Presentation.onDataLoad();"/> + </hbox> +</vbox> + +</deck> + + +<broadcasterset> + <broadcaster id="canBack"/> + <broadcaster id="canForward"/> +</broadcasterset> + +<commandset> + <command id="cmd_forward" + oncommand="if (Presentation.isPresentationMode) Presentation.forward();"/> + <command id="cmd_back" + oncommand="if (Presentation.isPresentationMode) Presentation.back();"/> + <command id="cmd_home" + oncommand="if (Presentation.isPresentationMode) Presentation.home();"/> + <command id="cmd_end" + oncommand="if (Presentation.isPresentationMode) Presentation.end();"/> +</commandset> +<keyset> + <key keycode="VK_ENTER" command="cmd_forward"/> + <key keycode="VK_RETURN" command="cmd_forward"/> + <key keycode="VK_PAGE_DOWN" command="cmd_forward"/> + <key keycode="VK_RIGHT" command="cmd_forward"/> + <key keycode="VK_DOWN" command="cmd_forward"/> + <!-- key keycode="VK_BACK_SPACE" command="cmd_back"/--> + <key keycode="VK_PAGE_UP" command="cmd_back"/> + <!-- <key keycode="VK_BACK_UP" command="cmd_back"/>--> + <!-- <key keycode="VK_BACK_LEFT" command="cmd_back"/>--> + <key keycode="VK_HOME" command="cmd_home"/> + <key keycode="VK_END" command="cmd_end"/> + <key key="n" modifiers="accel" oncommand="Presentation.addPage();"/> + <key key="r" modifiers="accel" oncommand="window.location.reload();"/> + <key key="e" modifiers="accel" oncommand="Presentation.toggleEditMode();"/> + <key key="a" modifiers="accel" oncommand="Presentation.toggleEvaMode();"/> +</keyset> + + +<script src="takahashi.js" type="application/x-javascript" /> +</page> +<!-- ***** BEGIN LICENSE BLOCK ***** + - Version: MPL 1.1 + - + - The contents of this file are subject to the Mozilla Public License Version + - 1.1 (the "License"); you may not use this file except in compliance with + - the License. You may obtain a copy of the License at + - http://www.mozilla.org/MPL/ + - + - Software distributed under the License is distributed on an "AS IS" basis, + - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + - for the specific language governing rights and limitations under the + - License. + - + - The Original Code is the Takahashi-Method-based Presentation Tool in XUL. + - + - The Initial Developer of the Original Code is SHIMODA Hiroshi. + - Portions created by the Initial Developer are Copyright (C) 2005 + - the Initial Developer. All Rights Reserved. + - + - Contributor(s): SHIMODA Hiroshi <piro@p.club.ne.jp> + - + - ***** END LICENSE BLOCK ***** --> + + diff --git a/oscon/takahashi.css b/oscon/takahashi.css new file mode 100644 index 0000000..591a815 --- /dev/null +++ b/oscon/takahashi.css @@ -0,0 +1,162 @@ +@charset "UTF-8"; + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Takahashi-Method-based Presentation Tool in XUL. + * + * The Initial Developer of the Original Code is SHIMODA Hiroshi. + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): SHIMODA Hiroshi <piro@p.club.ne.jp> + * + * ***** END LICENSE BLOCK ***** */ + +#canvas { + background: black !important; + color: white !important; + /* font-weight: bold; */ + font-family: + "Georgia" + "DejaVu Serif Condensed" + "Arial" + "Bitstream Vera Sans" + "Verdana" + "Apple LiGothic" + "Arial Black" + "Bitstream Vera Sans" + sans-serif !important; +} +#canvas * { + cursor: pointer !important; +} +#canvas image { + width: auto; + height: auto; +} +.link-text { + color: #99CCFF !important; + text-decoration: none !important; +} +.link-text:hover { + color: #CCEEFF !important; +/* border-bottom: dotted 1px; */ +} +.link-text:active { + color: white !important; +} +.s { + text-decoration: line-through; +} +.iu { + text-decoration: underline; + font-style: italic; +} +.ui { +/* text-decoration: underline; */ + font-style: italic; +} +.u { + text-decoration: underline; +} +.i { + font-style: italic; + font-family: "Times New Roman" + "Bitstream Vera Serif" + serif; +} +.c { + font-family: + "Monaco" + "Andale Mono" + "Bitstream Vera Sans Mono" + monospace; +} +.t { + font-style: italic; +} +.tag { + color: #33ff33; +} +.att { + color: #9999cc; +} +.key { + color: #00ffff; +} +.hid { + color: #999999; +} +.hidt { + color: #999999; + font-style: italic; +} +.pre { + font-family: "Monaco" + "Lucida Console" + "Andale Mono" + "Bitstream Vera Sans Mono" + monospace; + padding-bottom: 8px; +} +#canvas[rendering="true"] image { + display: none; +} +#canvas[rendering="true"] *, +#canvas[rendering="true"] .text-link { + color: white !important; +} + + +tabbox, tabpanels, tabpanel { + margin: 0; + padding: 0; +} + + + + +#canvas[eva="true"] { + background: white !important; + color: black !important; + font-family: + "Georgia" + "DejaVu Serif Condensed" + "Apple LiGothic" + "Arial Black" + serif !important; +} +#canvas[eva="true"] .link-text { + color: red !important; + text-decoration: none !important; +} +#canvas[eva="true"] .link-text:hover { + color: pink !important; +} +#canvas[eva="true"] .link-text:active { + color: orange !important; +} +#canvas[rendering="true"] *, +#canvas[rendering="true"] .text-link { + color: black !important; +} + + + + +#canvasToolbar { + position: relative; +} + +.smallfont { font-size: 20pt; } \ No newline at end of file diff --git a/oscon/takahashi.js b/oscon/takahashi.js new file mode 100644 index 0000000..c5d6933 --- /dev/null +++ b/oscon/takahashi.js @@ -0,0 +1,503 @@ +var Presentation = { + init : function(option){ + this.size = 9; + + this._offset = 0; + this.canvas = document.getElementById('canvas'); + this.content = document.getElementById('content'); + this.textbox = document.getElementById('textField'); + this.deck = document.getElementById('deck'); + this.scroller = document.getElementById('scroller'); + + this.toolbar = document.getElementById('canvasToolbar'); + this.toolbarHeight = this.toolbar.boxObject.height; + this.isToolbarHidden = true; + this.toolbar.setAttribute('style', 'margin-top:'+(0-this.toolbarHeight)+'px;margin-bottom:0px;'); + + if(option){ + for(var i in option){this[i] = option[i]} + } + + if (this.readParameter()) { + this.takahashi(); + } + + document.documentElement.focus(); + }, + + takahashi : function(){ + if (!document.title) + document.title = this.data[0].replace(/[\r\n]/g, ' '); + + if(!this.data[this.offset]){ + this.offset = this.data.length-1; + } + document.getElementById("current_page").value = this.offset+1; + document.getElementById("max_page").value = this.data.length; + + this.scroller.setAttribute('maxpos', this.data.length-1); + this.scroller.setAttribute('curpos', this.offset); + + var broadcaster = document.getElementById('canBack'); + if (!this.offset) + broadcaster.setAttribute('disabled', true); + else + broadcaster.removeAttribute('disabled'); + + var broadcaster = document.getElementById('canForward'); + if (this.offset == this.data.length-1) + broadcaster.setAttribute('disabled', true); + else + broadcaster.removeAttribute('disabled'); + + this.canvas.setAttribute('rendering', true); + + var text = this.data[this.offset]. + replace(/^[\r\n]+/g,"").replace(/[\r\n]+$/g,"").replace(/(\r\n|[\r\n])/g,"\n") + .split('\n'); + var range = document.createRange(); + range.selectNodeContents(this.content); + range.deleteContents(); + range.detach(); + + var line; + var newLine; + var uri; + var image_width; + var image_total_width = 0; + var image_height; + var image_total_height = 0; + var image_src; + var code_listing = 0; + + + var labelId = 0; + + for (var i = 0; i < text.length; i++) + { + this.content.appendChild(document.createElement('hbox')); + this.content.lastChild.setAttribute('align', 'center'); + this.content.lastChild.setAttribute('pack', 'center'); + + line = text[i]; + image_width = 0; + image_height = 0; + + if (line.match(/^ /)) { + code_listing = 1; + this.content.lastChild.setAttribute('align', 'left'); + this.content.lastChild.setAttribute('class', 'pre'); + line = line.substring(1) + } + + while (line.match(/^([^\{]+)?(\{\{ima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^\}]*\}\}|\{\{(([^\|]+)?\||)([^\}]+)\}\})(.+)?/)) + { + if (RegExp.$1) { + this.content.lastChild.appendChild(document.createElement('description')); + this.content.lastChild.lastChild.setAttribute('value', RegExp.$1); + } + newLine = line.substring((RegExp.$1+RegExp.$2).length); + + // Images + if (/^([^\{]+)?\{\{ima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^\}]*\}\}/.test(line)) { + this.content.lastChild.appendChild(document.createElement('image')); + image_src = RegExp.$2; + if (image_src.indexOf('http://') < 0 && + image_src.indexOf('https://') < 0) + image_src = this.dataFolder+image_src; + this.content.lastChild.lastChild.setAttribute('src', image_src); + this.content.lastChild.lastChild.setAttribute('width', parseInt(RegExp.$3 || '0')); + this.content.lastChild.lastChild.setAttribute('height', parseInt(RegExp.$4 || '0')); + image_width += parseInt(RegExp.$3 || '0'); + image_height = Math.max(image_height, parseInt(RegExp.$4 || '0')); + } + + // Styles + // else if (/^([^\{]+)?\{\{#([^\|]+)\|([^\}]+)\}\}/.test(line)) { + else if (/^([^\{]+)?\{\{(#([^\|]+)?\|)([^\}]+)\}\}/.test(line)) { + uri = RegExp.$4; + this.content.lastChild.appendChild(document.createElement('description')); + this.content.lastChild.lastChild.setAttribute('value', uri); + this.content.lastChild.lastChild.setAttribute('class', RegExp.$3); + } + + // Links + else if (/^([^\{]+)?\{\{(([^\|]+)?\||)([^\}]+)\}\}/.test(line)) { + uri = RegExp.$4; + if (uri.indexOf('://') < 0) + uri = this.dataFolder+uri; + this.content.lastChild.appendChild(document.createElement('description')); + this.content.lastChild.lastChild.setAttribute('value', RegExp.$3 || RegExp.$4); + this.content.lastChild.lastChild.setAttribute('href', uri); + this.content.lastChild.lastChild.setAttribute('tooltiptext', uri); + this.content.lastChild.lastChild.setAttribute('statustext', uri); + this.content.lastChild.lastChild.setAttribute('class', 'link-text'); + } + + line = newLine; + } + + if (line) { + this.content.lastChild.appendChild(document.createElement('description')); + this.content.lastChild.lastChild.setAttribute('value', line); + } + + image_total_width = Math.max(image_total_width, image_width); + image_total_height += image_height; + } + + this.content.setAttribute('style', 'font-size:10px;'); + + if (this.content.boxObject.width) { + var canvas_w = this.canvas.boxObject.width; + var canvas_h = this.canvas.boxObject.height-image_total_height; + + var content_w = this.content.boxObject.width; + var new_fs = Math.round((canvas_w/content_w) * this.size); + + new_fs = new_fs - (new_fs % 32); + if (code_listing) { new_fs = 48;} + + this.content.setAttribute('style', 'top: 0'); + this.content.setAttribute('style', 'font-size:'+ new_fs + "px"); + + if (this.content.boxObject.width < image_total_width) { + content_w = image_total_width; + new_fs = Math.round((canvas_w/content_w) * this.size); + this.content.setAttribute('style', 'font-size:'+ new_fs + "px"); + } + + var content_h = this.content.boxObject.height; + if(content_h >= canvas_h){ + content_h = this.content.boxObject.height; + new_fs = Math.round((canvas_h/content_h) * new_fs); + this.content.setAttribute('style', 'font-size:'+ new_fs + "px"); + } + } + + + + this.canvas.removeAttribute('rendering'); + }, + + reload : function() { + if (this.dataPath != location.href) { + var path = this.dataPath; + if (location.href.match(/^https?:/)) { + var request = new XMLHttpRequest(); + request.open('GET', path); + request.onload = function() { + Presentation.textbox.value = request.responseText; + Presentation.data = Presentation.textbox.value.split('----'); + + Presentation.takahashi(); + + path = null; + request = null; + }; + request.send(null); + } + else { + document.getElementById('dataLoader').setAttribute('src', 'about:blank'); + window.setTimeout(function() { + document.getElementById('dataLoader').setAttribute('src', path); + path = null; + }, 10); + } + } + else + window.location.reload(); + }, + + forward : function(){ + this.offset++; + this.takahashi(); + }, + back : function(){ + this.offset--; + if(this.offset < 0){this.offset = 0} + this.takahashi(); + }, + home : function(){ + this.offset = 0; + this.takahashi(); + }, + end : function(){ + this.offset = this.data.length-1; + this.takahashi(); + }, + showPage : function(aPageOffset){ + this.offset = aPageOffset ? aPageOffset : 0 ; + this.takahashi(); + }, + + addPage : function() { + if (this.textbox.value && + !this.textbox.value.match(/(\r\n|[\r\n])$/)) + this.textbox.value += '\n'; + this.textbox.value += '----\n'; + this.onEdit(); + }, + + toggleEditMode : function(){ + this.deck.selectedIndex = (this.deck.selectedIndex == 0) ? 1 : 0 ; + }, + toggleEvaMode : function(){ + var check = document.getElementById('toggleEva'); + if (this.canvas.getAttribute('eva') == 'true') { + this.canvas.removeAttribute('eva'); + check.checked = false; + } + else { + this.canvas.setAttribute('eva', true); + check.checked = true; + } + }, + + onPresentationClick : function(aEvent){ + if (!this.isToolbarHidden) + this.showHideToolbar(); + + switch(aEvent.button) + { + case 0: + var uri = aEvent.target.getAttribute('href'); + if (uri) + window.open(uri); + else { + this.forward(); + document.documentElement.focus(); + } + break; + case 2: + this.back(); + document.documentElement.focus(); + break; + default: + break; + } + }, + onScrollerDragStart : function(){ + this.scroller.dragging = true; + }, + onScrollerDragMove : function(){ + if (this.scroller.dragging) + this.showPage(parseInt(this.scroller.getAttribute('curpos'))); + }, + onScrollerDragDrop : function(){ + if (this.scroller.dragging) { + this.showPage(parseInt(this.scroller.getAttribute('curpos'))); + } + this.scroller.dragging = false; + }, + onEdit : function() { + this.data = this.textbox.value.split('----'); + this.takahashi(); + }, + + onKeyPress : function(aEvent) { + switch(aEvent.keyCode) + { + case aEvent.DOM_VK_BACK_SPACE: + if (this.isPresentationMode) { + aEvent.preventBubble(); + aEvent.preventDefault(); + Presentation.back(); + } + break; + default: + break; + } + }, + + + onToolbarArea : false, + toolbarHeight : 0, + toolbarDelay : 300, + toolbarTimer : null, + isToolbarHidden : false, + onMouseMoveOnCanvas : function(aEvent) { + if (this.scroller.dragging) return; + + this.onToolbarArea = (aEvent.clientY < this.toolbarHeight); + + if (this.isToolbarHidden == this.onToolbarArea) { + if (this.toolbarTimer) window.clearTimeout(this.toolbarTimer); + this.toolbarTimer = window.setTimeout('Presentation.onMouseMoveOnCanvasCallback()', this.toolbarDelay); + } + }, + onMouseMoveOnCanvasCallback : function() { + if (this.isToolbarHidden == this.onToolbarArea) + this.showHideToolbar(); + }, + + toolbarAnimationDelay : 100, + toolbarAnimationSteps : 5, + toolbarAnimationInfo : null, + toolbarAnimationTimer : null, + showHideToolbar : function() + { + if (this.toolbarAnimationTimer) window.clearTimeout(this.toolbarAnimationTimer); + + this.toolbarAnimationInfo = { count : 0 }; + if (this.isToolbarHidden) { + this.toolbarAnimationInfo.start = 0; + this.toolbarAnimationInfo.end = this.toolbarHeight; + } + else { + this.toolbarAnimationInfo.start = this.toolbarHeight; + this.toolbarAnimationInfo.end = 0; + } + this.toolbarAnimationInfo.current = 0; + + this.toolbar.setAttribute('style', 'margin-top:'+(0-(this.toolbarHeight-this.toolbarAnimationInfo.start))+'px; margin-bottom:'+(0-this.toolbarAnimationInfo.start)+'px;'); + + this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps); + }, + animateToolbar : function() + { + this.toolbarAnimationInfo.current += parseInt(this.toolbarHeight/this.toolbarAnimationSteps); + + var top, bottom; + if (this.toolbarAnimationInfo.start < this.toolbarAnimationInfo.end) { + top = this.toolbarHeight-this.toolbarAnimationInfo.current; + bottom = this.toolbarAnimationInfo.current; + } + else { + top = this.toolbarAnimationInfo.current; + bottom = this.toolbarHeight-this.toolbarAnimationInfo.current; + } + + top = Math.min(Math.max(top, 0), this.toolbarHeight); + bottom = Math.min(Math.max(bottom, 0), this.toolbarHeight); + + this.toolbar.setAttribute('style', 'margin-top:'+(0-top)+'px; margin-bottom:'+(0-bottom)+'px'); + + if (this.toolbarAnimationInfo.count < this.toolbarAnimationSteps) { + this.toolbarAnimationInfo.count++; + this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps); + } + else + this.isToolbarHidden = !this.isToolbarHidden; + }, + + + + get offset(){ + return this._offset; + }, + set offset(aValue){ + this._offset = parseInt(aValue || 0); + document.documentElement.setAttribute('lastoffset', this.offset); + return this.offset; + }, + + get data(){ + if (!this._data) { + // Make sure you break the text into parts smaller than 4096 + // characters, and name them as indicated. Tweak as required. + // (What a hack. A JS programmer should find a better way.) + // Luc St-Louis, and email is lucs@pobox.com. + + nodes = document.getElementById('builtinCode').childNodes; + content = ''; + for (i in nodes) { + if (nodes[i].nodeValue) { + content = content + nodes[i].nodeValue; + } + } + + this._data = content.split("----"); + } + + return this._data; + }, + set data(aValue){ + this._data = aValue; + return aValue; + }, + + + get isPresentationMode(){ + return (this.deck.selectedIndex == 0); + }, + + + get dataPath(){ + if (!this._dataPath) + this.dataPath = location.href; + return this._dataPath; + }, + set dataPath(aValue){ + var oldDataPath = this._dataPath; + this._dataPath = aValue; + if (oldDataPath != aValue) { + this._dataFolder = this._dataPath.split('?')[0].replace(/[^\/]+$/, ''); + } + return this._dataPath; + }, + + get dataFolder(){ + if (!this._dataFolder) + this.dataPath = this.dataPath; + return this._dataFolder; + }, + set dataFolder(aValue){ + this._dataFolder = aValue; + return this._dataFolder; + }, + + readParameter : function() { + if (location.search) { + var param = location.search.replace(/^\?/, ''); + + if (param.match(/page=([0-9]+)/i)) + this.offset = parseInt(RegExp.$1)-1; + + if (param.match(/edit=(1|true|yes)/i)) + this.toggleEditMode(); + + if (param.match(/eva=(1|true|yes)/i)) + this.toggleEvaMode(); + + if (param.match(/data=([^&;]+)/i)) { + var path = unescape(RegExp.$1); + this.dataPath = path; + if (location.href.match(/^https?:/)) { + var request = new XMLHttpRequest(); + request.open('GET', path); + request.onload = function() { + Presentation.textbox.value = request.responseText; + Presentation.data = Presentation.textbox.value.split('----'); + + Presentation.takahashi(); + }; + request.send(null); + } + else { + document.getElementById('dataLoader').setAttribute('src', path); + } + return false; + } + } + return true; + }, + onDataLoad : function() { + if (!window.frames[0].document.body.hasChildNodes()) return; + var data = window.frames[0].document.body.firstChild.innerHTML; + if (!data) return; + + this.textbox.value = data; + this.data = this.textbox.value.split('----'); + + this.takahashi(); + } +}; + +function init() +{ + window.removeEventListener('load', init, false); + + Presentation.init(); +} +window.addEventListener('load', init, false); diff --git a/ppw_roles_talk/roles.xul b/ppw_roles_talk/roles.xul new file mode 100644 index 0000000..5161b4b --- /dev/null +++ b/ppw_roles_talk/roles.xul @@ -0,0 +1,349 @@ +<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="chrome://global/skin/" type="text/css"?><?xml-stylesheet href="takahashi.css" type="text/css"?><page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="presentation" xmlns:html="http:/www.w3.org/1999/xhtml" orient="vertical" onkeypress="Presentation.onKeyPress(event);"> +<html:textarea id="builtinCode" style="visibility: collapse"><![CDATA[ +Horizontal +Code Reuse +with +Møøse::Role +---- +Stevan Little +stevan.little@iinteractive.com +http://www.iinteractive.com/moose +http://search.cpan.org/~stevan/ +---- +Roles +---- +â +---- +Classes +---- +Roles +do /not/ +inherit. +---- +Inheritance is +â +vertical reuse. +---- +Roles +compose. +---- +Composition is +â +horizontal reuse. +---- +... +---- +When +to use +Roles +---- +My general rule +of thumb is ... +---- +s/MI/Roles/g +---- +When +to /not/ use +Roles +---- +When a class +just makes +more sense. +---- +Roles are /not/ a +replacement for +inheritance. +---- +How Roles +Work +---- +Roles are +orphans. +---- +Roles are +composed. +---- +Local class +overrides role. +---- +Role overrides +inherited class. +---- +Roles can +conflict. +---- +Method conflicts +must be +disambiguated. +---- +Attribute conflicts +cannot be +disambiguated. +---- +How +to use +Roles +---- + package My::Role; + use Moose::Role; + + has my_attr => (is => 'rw'); + + requires 'a_method'; + + sub my_method { ... } +---- + package My::Class; + use Moose; + + with 'My::Role'; + + sub a_method { ... } +---- + my $o = My::Class->new( + my_attr => '...' + ); + + $o->my_method(); +---- +Role +Examples +---- +Behavior +Reuse +---- + package My::App::Conversions; + use Moose::Role; + + sub decimal_to_percentage { ... } + sub percentage_to_decimal { ... } +---- +Attribute +Reuse +---- + package My::App::WithDBICSchema; + use Moose::Role; + + has 'schema' => ( + is => 'ro', + isa => 'DBIx::Class::Schema', + lazy => 1, + default => sub { + My::App::DB->connect(...) + } + ); +---- +Abstract +Interfaces +---- + package My::App::Iterator::Abstract; + use Moose::Role; + + requires 'has_next'; + requires 'next'; + requires 'peek'; +---- +Partial +âClassesâ +---- + package My::App::Report::Base; + use Moose::Role; + + requires 'calculate'; + + sub run { + my $self = shift; + $self->setup; + $self->calculate; + $self->teardown; + } + + sub setup { ... } + sub teardown { ... } +---- +Modules +which use +Roles +---- +MooseX::Getopt +---- + package My::App; + use Moose; + + with 'MooseX::Getopt'; + + has 'foo' => (is => 'rw', isa => 'Int'); + + sub run { ... } + + package main; + My::App->new_with_options->run +---- + stevan>./my_app.pl --foo 10 +---- +MooseX::Storage +---- +MooseX::AttributeHelpers +---- +Thank You +for coming. +---- +And always +remember ... +---- +Roles +â +Classes +]]></html:textarea> + + + + + + + + + + + +<deck flex="1" id="deck"> + +<vbox flex="1" + onmousemove="Presentation.onMouseMoveOnCanvas(event);"> + <toolbox id="canvasToolbar"> + <toolbar> + <toolbarbutton oncommand="Presentation.home()" label="|<<" + observes="canBack"/> + <toolbarbutton oncommand="Presentation.back()" label="<" + observes="canBack"/> + <toolbarbutton oncommand="Presentation.forward()" label=">" + observes="canForward"/> + <toolbarbutton oncommand="Presentation.end()" label=">>|" + observes="canForward"/> + <toolbarseparator/> + <hbox align="center"> + <textbox id="current_page" size="4" + oninput="if (this.value) Presentation.showPage(parseInt(this.value)-1);"/> + <description value="/"/> + <description id="max_page"/> + </hbox> + <toolbarseparator/> + <vbox flex="2"> + <spacer flex="1"/> + <scrollbar id="scroller" + align="center" orient="horizontal" + oncommand="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));" + onclick="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));" + onmousedown="Presentation.onScrollerDragStart();" + onmousemove="Presentation.onScrollerDragMove();" + onmouseup="Presentation.onScrollerDragDrop();"/> + <spacer flex="1"/> + </vbox> + <toolbarseparator/> + <spacer flex="1"/> + <toolbarseparator/> + <toolbarbutton id="toggleEva" label="Eva" + type="checkbox" + autoCheck="false" + oncommand="Presentation.toggleEvaMode();"/> + <toolbarseparator/> + <toolbarbutton label="Edit" + oncommand="Presentation.toggleEditMode();"/> + <toolbarbutton oncommand="Presentation.reload();" label="Reload"/> + </toolbar> + </toolbox> + <vbox flex="1" id="canvas" + onclick="Presentation.onPresentationClick(event);"> + <spacer flex="1"/> + <hbox flex="1"> + <spacer flex="1"/> + <vbox id="content"/> + <spacer flex="1"/> + </hbox> + <spacer flex="1"/> + </vbox> +</vbox> + + +<vbox flex="1" id="edit"> + <toolbox> + <toolbar> + <toolbarbutton label="New Page" + oncommand="Presentation.addPage()"/> + <spacer flex="1"/> + <toolbarseparator/> + <toolbarbutton label="View" + oncommand="Presentation.toggleEditMode();"/> + <toolbarbutton oncommand="Presentation.reload();" label="Reload"/> + </toolbar> + </toolbox> + <textbox id="textField" flex="1" multiline="true" + oninput="Presentation.onEdit()"/> + <hbox collapsed="true"> + <iframe id="dataLoader" onload="if (window.Presentation) Presentation.onDataLoad();"/> + </hbox> +</vbox> + +</deck> + + +<broadcasterset> + <broadcaster id="canBack"/> + <broadcaster id="canForward"/> +</broadcasterset> + +<commandset> + <command id="cmd_forward" + oncommand="if (Presentation.isPresentationMode) Presentation.forward();"/> + <command id="cmd_back" + oncommand="if (Presentation.isPresentationMode) Presentation.back();"/> + <command id="cmd_home" + oncommand="if (Presentation.isPresentationMode) Presentation.home();"/> + <command id="cmd_end" + oncommand="if (Presentation.isPresentationMode) Presentation.end();"/> +</commandset> +<keyset> + <key keycode="VK_ENTER" command="cmd_forward"/> + <key keycode="VK_RETURN" command="cmd_forward"/> + <key keycode="VK_PAGE_DOWN" command="cmd_forward"/> + <key keycode="VK_RIGHT" command="cmd_forward"/> + <key keycode="VK_DOWN" command="cmd_forward"/> + <!-- key keycode="VK_BACK_SPACE" command="cmd_back"/--> + <key keycode="VK_PAGE_UP" command="cmd_back"/> + <!-- <key keycode="VK_BACK_UP" command="cmd_back"/>--> + <!-- <key keycode="VK_BACK_LEFT" command="cmd_back"/>--> + <key keycode="VK_HOME" command="cmd_home"/> + <key keycode="VK_END" command="cmd_end"/> + <key key="n" modifiers="accel" oncommand="Presentation.addPage();"/> + <key key="r" modifiers="accel" oncommand="window.location.reload();"/> + <key key="e" modifiers="accel" oncommand="Presentation.toggleEditMode();"/> + <key key="a" modifiers="accel" oncommand="Presentation.toggleEvaMode();"/> +</keyset> + + +<script src="takahashi.js" type="application/x-javascript" /> +</page> +<!-- ***** BEGIN LICENSE BLOCK ***** + - Version: MPL 1.1 + - + - The contents of this file are subject to the Mozilla Public License Version + - 1.1 (the "License"); you may not use this file except in compliance with + - the License. You may obtain a copy of the License at + - http://www.mozilla.org/MPL/ + - + - Software distributed under the License is distributed on an "AS IS" basis, + - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + - for the specific language governing rights and limitations under the + - License. + - + - The Original Code is the Takahashi-Method-based Presentation Tool in XUL. + - + - The Initial Developer of the Original Code is SHIMODA Hiroshi. + - Portions created by the Initial Developer are Copyright (C) 2005 + - the Initial Developer. All Rights Reserved. + - + - Contributor(s): SHIMODA Hiroshi <piro@p.club.ne.jp> + - + - ***** END LICENSE BLOCK ***** --> + + diff --git a/ppw_roles_talk/takahashi.css b/ppw_roles_talk/takahashi.css new file mode 100644 index 0000000..e001c4a --- /dev/null +++ b/ppw_roles_talk/takahashi.css @@ -0,0 +1,162 @@ +@charset "UTF-8"; + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Takahashi-Method-based Presentation Tool in XUL. + * + * The Initial Developer of the Original Code is SHIMODA Hiroshi. + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): SHIMODA Hiroshi <piro@p.club.ne.jp> + * + * ***** END LICENSE BLOCK ***** */ + +#canvas { + background: black !important; + color: white !important; + /* font-weight: bold; */ + font-family: + "Georgia" + "DejaVu Serif Condensed" + "Arial" + "Bitstream Vera Sans" + "Verdana" + "Apple LiGothic" + "Arial Black" + "Bitstream Vera Sans" + sans-serif !important; +} +#canvas * { + cursor: pointer !important; +} +#canvas image { + width: auto; + height: auto; +} +.link-text { + color: #99CCFF !important; + text-decoration: none !important; +} +.link-text:hover { + color: #CCEEFF !important; +/* border-bottom: dotted 1px; */ +} +.link-text:active { + color: white !important; +} +.s { + text-decoration: line-through; +} +.iu { + text-decoration: underline; + font-style: italic; +} +.ui { +/* text-decoration: underline; */ + font-style: italic; +} +.u { + text-decoration: underline; +} +.i { + font-style: italic; + font-family: "Times New Roman" + "Bitstream Vera Serif" + serif; +} +.c { + font-family: "Anonymous" + "Lucida Console" + "Andale Mono" + "Bitstream Vera Sans Mono" + monospace; +} +.t { + font-style: italic; +} +.tag { + color: #33ff33; +} +.att { + color: #9999cc; +} +.key { + color: #00ffff; +} +.hid { + color: #999999; +} +.hidt { + color: #999999; + font-style: italic; +} +.pre { + font-family: "Anonymous" + "Lucida Console" + "Andale Mono" + "Bitstream Vera Sans Mono" + monospace; + padding-bottom: 8px; +} +#canvas[rendering="true"] image { + display: none; +} +#canvas[rendering="true"] *, +#canvas[rendering="true"] .text-link { + color: white !important; +} + + +tabbox, tabpanels, tabpanel { + margin: 0; + padding: 0; +} + + + + +#canvas[eva="true"] { + background: white !important; + color: black !important; + font-family: + "Georgia" + "DejaVu Serif Condensed" + "Apple LiGothic" + "Arial Black" + serif !important; +} +#canvas[eva="true"] .link-text { + color: red !important; + text-decoration: none !important; +} +#canvas[eva="true"] .link-text:hover { + color: pink !important; +} +#canvas[eva="true"] .link-text:active { + color: orange !important; +} +#canvas[rendering="true"] *, +#canvas[rendering="true"] .text-link { + color: black !important; +} + + + + +#canvasToolbar { + position: relative; +} + +.smallfont { font-size: 20pt; } \ No newline at end of file diff --git a/ppw_roles_talk/takahashi.js b/ppw_roles_talk/takahashi.js new file mode 100644 index 0000000..c5d6933 --- /dev/null +++ b/ppw_roles_talk/takahashi.js @@ -0,0 +1,503 @@ +var Presentation = { + init : function(option){ + this.size = 9; + + this._offset = 0; + this.canvas = document.getElementById('canvas'); + this.content = document.getElementById('content'); + this.textbox = document.getElementById('textField'); + this.deck = document.getElementById('deck'); + this.scroller = document.getElementById('scroller'); + + this.toolbar = document.getElementById('canvasToolbar'); + this.toolbarHeight = this.toolbar.boxObject.height; + this.isToolbarHidden = true; + this.toolbar.setAttribute('style', 'margin-top:'+(0-this.toolbarHeight)+'px;margin-bottom:0px;'); + + if(option){ + for(var i in option){this[i] = option[i]} + } + + if (this.readParameter()) { + this.takahashi(); + } + + document.documentElement.focus(); + }, + + takahashi : function(){ + if (!document.title) + document.title = this.data[0].replace(/[\r\n]/g, ' '); + + if(!this.data[this.offset]){ + this.offset = this.data.length-1; + } + document.getElementById("current_page").value = this.offset+1; + document.getElementById("max_page").value = this.data.length; + + this.scroller.setAttribute('maxpos', this.data.length-1); + this.scroller.setAttribute('curpos', this.offset); + + var broadcaster = document.getElementById('canBack'); + if (!this.offset) + broadcaster.setAttribute('disabled', true); + else + broadcaster.removeAttribute('disabled'); + + var broadcaster = document.getElementById('canForward'); + if (this.offset == this.data.length-1) + broadcaster.setAttribute('disabled', true); + else + broadcaster.removeAttribute('disabled'); + + this.canvas.setAttribute('rendering', true); + + var text = this.data[this.offset]. + replace(/^[\r\n]+/g,"").replace(/[\r\n]+$/g,"").replace(/(\r\n|[\r\n])/g,"\n") + .split('\n'); + var range = document.createRange(); + range.selectNodeContents(this.content); + range.deleteContents(); + range.detach(); + + var line; + var newLine; + var uri; + var image_width; + var image_total_width = 0; + var image_height; + var image_total_height = 0; + var image_src; + var code_listing = 0; + + + var labelId = 0; + + for (var i = 0; i < text.length; i++) + { + this.content.appendChild(document.createElement('hbox')); + this.content.lastChild.setAttribute('align', 'center'); + this.content.lastChild.setAttribute('pack', 'center'); + + line = text[i]; + image_width = 0; + image_height = 0; + + if (line.match(/^ /)) { + code_listing = 1; + this.content.lastChild.setAttribute('align', 'left'); + this.content.lastChild.setAttribute('class', 'pre'); + line = line.substring(1) + } + + while (line.match(/^([^\{]+)?(\{\{ima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^\}]*\}\}|\{\{(([^\|]+)?\||)([^\}]+)\}\})(.+)?/)) + { + if (RegExp.$1) { + this.content.lastChild.appendChild(document.createElement('description')); + this.content.lastChild.lastChild.setAttribute('value', RegExp.$1); + } + newLine = line.substring((RegExp.$1+RegExp.$2).length); + + // Images + if (/^([^\{]+)?\{\{ima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^\}]*\}\}/.test(line)) { + this.content.lastChild.appendChild(document.createElement('image')); + image_src = RegExp.$2; + if (image_src.indexOf('http://') < 0 && + image_src.indexOf('https://') < 0) + image_src = this.dataFolder+image_src; + this.content.lastChild.lastChild.setAttribute('src', image_src); + this.content.lastChild.lastChild.setAttribute('width', parseInt(RegExp.$3 || '0')); + this.content.lastChild.lastChild.setAttribute('height', parseInt(RegExp.$4 || '0')); + image_width += parseInt(RegExp.$3 || '0'); + image_height = Math.max(image_height, parseInt(RegExp.$4 || '0')); + } + + // Styles + // else if (/^([^\{]+)?\{\{#([^\|]+)\|([^\}]+)\}\}/.test(line)) { + else if (/^([^\{]+)?\{\{(#([^\|]+)?\|)([^\}]+)\}\}/.test(line)) { + uri = RegExp.$4; + this.content.lastChild.appendChild(document.createElement('description')); + this.content.lastChild.lastChild.setAttribute('value', uri); + this.content.lastChild.lastChild.setAttribute('class', RegExp.$3); + } + + // Links + else if (/^([^\{]+)?\{\{(([^\|]+)?\||)([^\}]+)\}\}/.test(line)) { + uri = RegExp.$4; + if (uri.indexOf('://') < 0) + uri = this.dataFolder+uri; + this.content.lastChild.appendChild(document.createElement('description')); + this.content.lastChild.lastChild.setAttribute('value', RegExp.$3 || RegExp.$4); + this.content.lastChild.lastChild.setAttribute('href', uri); + this.content.lastChild.lastChild.setAttribute('tooltiptext', uri); + this.content.lastChild.lastChild.setAttribute('statustext', uri); + this.content.lastChild.lastChild.setAttribute('class', 'link-text'); + } + + line = newLine; + } + + if (line) { + this.content.lastChild.appendChild(document.createElement('description')); + this.content.lastChild.lastChild.setAttribute('value', line); + } + + image_total_width = Math.max(image_total_width, image_width); + image_total_height += image_height; + } + + this.content.setAttribute('style', 'font-size:10px;'); + + if (this.content.boxObject.width) { + var canvas_w = this.canvas.boxObject.width; + var canvas_h = this.canvas.boxObject.height-image_total_height; + + var content_w = this.content.boxObject.width; + var new_fs = Math.round((canvas_w/content_w) * this.size); + + new_fs = new_fs - (new_fs % 32); + if (code_listing) { new_fs = 48;} + + this.content.setAttribute('style', 'top: 0'); + this.content.setAttribute('style', 'font-size:'+ new_fs + "px"); + + if (this.content.boxObject.width < image_total_width) { + content_w = image_total_width; + new_fs = Math.round((canvas_w/content_w) * this.size); + this.content.setAttribute('style', 'font-size:'+ new_fs + "px"); + } + + var content_h = this.content.boxObject.height; + if(content_h >= canvas_h){ + content_h = this.content.boxObject.height; + new_fs = Math.round((canvas_h/content_h) * new_fs); + this.content.setAttribute('style', 'font-size:'+ new_fs + "px"); + } + } + + + + this.canvas.removeAttribute('rendering'); + }, + + reload : function() { + if (this.dataPath != location.href) { + var path = this.dataPath; + if (location.href.match(/^https?:/)) { + var request = new XMLHttpRequest(); + request.open('GET', path); + request.onload = function() { + Presentation.textbox.value = request.responseText; + Presentation.data = Presentation.textbox.value.split('----'); + + Presentation.takahashi(); + + path = null; + request = null; + }; + request.send(null); + } + else { + document.getElementById('dataLoader').setAttribute('src', 'about:blank'); + window.setTimeout(function() { + document.getElementById('dataLoader').setAttribute('src', path); + path = null; + }, 10); + } + } + else + window.location.reload(); + }, + + forward : function(){ + this.offset++; + this.takahashi(); + }, + back : function(){ + this.offset--; + if(this.offset < 0){this.offset = 0} + this.takahashi(); + }, + home : function(){ + this.offset = 0; + this.takahashi(); + }, + end : function(){ + this.offset = this.data.length-1; + this.takahashi(); + }, + showPage : function(aPageOffset){ + this.offset = aPageOffset ? aPageOffset : 0 ; + this.takahashi(); + }, + + addPage : function() { + if (this.textbox.value && + !this.textbox.value.match(/(\r\n|[\r\n])$/)) + this.textbox.value += '\n'; + this.textbox.value += '----\n'; + this.onEdit(); + }, + + toggleEditMode : function(){ + this.deck.selectedIndex = (this.deck.selectedIndex == 0) ? 1 : 0 ; + }, + toggleEvaMode : function(){ + var check = document.getElementById('toggleEva'); + if (this.canvas.getAttribute('eva') == 'true') { + this.canvas.removeAttribute('eva'); + check.checked = false; + } + else { + this.canvas.setAttribute('eva', true); + check.checked = true; + } + }, + + onPresentationClick : function(aEvent){ + if (!this.isToolbarHidden) + this.showHideToolbar(); + + switch(aEvent.button) + { + case 0: + var uri = aEvent.target.getAttribute('href'); + if (uri) + window.open(uri); + else { + this.forward(); + document.documentElement.focus(); + } + break; + case 2: + this.back(); + document.documentElement.focus(); + break; + default: + break; + } + }, + onScrollerDragStart : function(){ + this.scroller.dragging = true; + }, + onScrollerDragMove : function(){ + if (this.scroller.dragging) + this.showPage(parseInt(this.scroller.getAttribute('curpos'))); + }, + onScrollerDragDrop : function(){ + if (this.scroller.dragging) { + this.showPage(parseInt(this.scroller.getAttribute('curpos'))); + } + this.scroller.dragging = false; + }, + onEdit : function() { + this.data = this.textbox.value.split('----'); + this.takahashi(); + }, + + onKeyPress : function(aEvent) { + switch(aEvent.keyCode) + { + case aEvent.DOM_VK_BACK_SPACE: + if (this.isPresentationMode) { + aEvent.preventBubble(); + aEvent.preventDefault(); + Presentation.back(); + } + break; + default: + break; + } + }, + + + onToolbarArea : false, + toolbarHeight : 0, + toolbarDelay : 300, + toolbarTimer : null, + isToolbarHidden : false, + onMouseMoveOnCanvas : function(aEvent) { + if (this.scroller.dragging) return; + + this.onToolbarArea = (aEvent.clientY < this.toolbarHeight); + + if (this.isToolbarHidden == this.onToolbarArea) { + if (this.toolbarTimer) window.clearTimeout(this.toolbarTimer); + this.toolbarTimer = window.setTimeout('Presentation.onMouseMoveOnCanvasCallback()', this.toolbarDelay); + } + }, + onMouseMoveOnCanvasCallback : function() { + if (this.isToolbarHidden == this.onToolbarArea) + this.showHideToolbar(); + }, + + toolbarAnimationDelay : 100, + toolbarAnimationSteps : 5, + toolbarAnimationInfo : null, + toolbarAnimationTimer : null, + showHideToolbar : function() + { + if (this.toolbarAnimationTimer) window.clearTimeout(this.toolbarAnimationTimer); + + this.toolbarAnimationInfo = { count : 0 }; + if (this.isToolbarHidden) { + this.toolbarAnimationInfo.start = 0; + this.toolbarAnimationInfo.end = this.toolbarHeight; + } + else { + this.toolbarAnimationInfo.start = this.toolbarHeight; + this.toolbarAnimationInfo.end = 0; + } + this.toolbarAnimationInfo.current = 0; + + this.toolbar.setAttribute('style', 'margin-top:'+(0-(this.toolbarHeight-this.toolbarAnimationInfo.start))+'px; margin-bottom:'+(0-this.toolbarAnimationInfo.start)+'px;'); + + this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps); + }, + animateToolbar : function() + { + this.toolbarAnimationInfo.current += parseInt(this.toolbarHeight/this.toolbarAnimationSteps); + + var top, bottom; + if (this.toolbarAnimationInfo.start < this.toolbarAnimationInfo.end) { + top = this.toolbarHeight-this.toolbarAnimationInfo.current; + bottom = this.toolbarAnimationInfo.current; + } + else { + top = this.toolbarAnimationInfo.current; + bottom = this.toolbarHeight-this.toolbarAnimationInfo.current; + } + + top = Math.min(Math.max(top, 0), this.toolbarHeight); + bottom = Math.min(Math.max(bottom, 0), this.toolbarHeight); + + this.toolbar.setAttribute('style', 'margin-top:'+(0-top)+'px; margin-bottom:'+(0-bottom)+'px'); + + if (this.toolbarAnimationInfo.count < this.toolbarAnimationSteps) { + this.toolbarAnimationInfo.count++; + this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps); + } + else + this.isToolbarHidden = !this.isToolbarHidden; + }, + + + + get offset(){ + return this._offset; + }, + set offset(aValue){ + this._offset = parseInt(aValue || 0); + document.documentElement.setAttribute('lastoffset', this.offset); + return this.offset; + }, + + get data(){ + if (!this._data) { + // Make sure you break the text into parts smaller than 4096 + // characters, and name them as indicated. Tweak as required. + // (What a hack. A JS programmer should find a better way.) + // Luc St-Louis, and email is lucs@pobox.com. + + nodes = document.getElementById('builtinCode').childNodes; + content = ''; + for (i in nodes) { + if (nodes[i].nodeValue) { + content = content + nodes[i].nodeValue; + } + } + + this._data = content.split("----"); + } + + return this._data; + }, + set data(aValue){ + this._data = aValue; + return aValue; + }, + + + get isPresentationMode(){ + return (this.deck.selectedIndex == 0); + }, + + + get dataPath(){ + if (!this._dataPath) + this.dataPath = location.href; + return this._dataPath; + }, + set dataPath(aValue){ + var oldDataPath = this._dataPath; + this._dataPath = aValue; + if (oldDataPath != aValue) { + this._dataFolder = this._dataPath.split('?')[0].replace(/[^\/]+$/, ''); + } + return this._dataPath; + }, + + get dataFolder(){ + if (!this._dataFolder) + this.dataPath = this.dataPath; + return this._dataFolder; + }, + set dataFolder(aValue){ + this._dataFolder = aValue; + return this._dataFolder; + }, + + readParameter : function() { + if (location.search) { + var param = location.search.replace(/^\?/, ''); + + if (param.match(/page=([0-9]+)/i)) + this.offset = parseInt(RegExp.$1)-1; + + if (param.match(/edit=(1|true|yes)/i)) + this.toggleEditMode(); + + if (param.match(/eva=(1|true|yes)/i)) + this.toggleEvaMode(); + + if (param.match(/data=([^&;]+)/i)) { + var path = unescape(RegExp.$1); + this.dataPath = path; + if (location.href.match(/^https?:/)) { + var request = new XMLHttpRequest(); + request.open('GET', path); + request.onload = function() { + Presentation.textbox.value = request.responseText; + Presentation.data = Presentation.textbox.value.split('----'); + + Presentation.takahashi(); + }; + request.send(null); + } + else { + document.getElementById('dataLoader').setAttribute('src', path); + } + return false; + } + } + return true; + }, + onDataLoad : function() { + if (!window.frames[0].document.body.hasChildNodes()) return; + var data = window.frames[0].document.body.firstChild.innerHTML; + if (!data) return; + + this.textbox.value = data; + this.data = this.textbox.value.split('----'); + + this.takahashi(); + } +}; + +function init() +{ + window.removeEventListener('load', init, false); + + Presentation.init(); +} +window.addEventListener('load', init, false); diff --git a/template_test.html b/template_test.html new file mode 100644 index 0000000..2f88fe8 --- /dev/null +++ b/template_test.html @@ -0,0 +1,271 @@ +<html> +<head> +<script language="javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.2.6.js"></script> +<script language="javascript"> + +/* + +COPYRIGHT AND LICENCE + +Copyright (C) 2006-2008 Infinity Interactive, Inc. + +http://www.iinteractive.com + +This library is free software; you can redistribute it +and/or modify it under the same terms as Perl itself. + +*/ + +/**************** Templating Objects ****************/ + +function Param (value) { this.value = value } +Param.prototype.find_and_replace = function (template, selector, value) { + template.find(selector) + .each(function () { jQuery(this).html(value) }) +} +Param.prototype.render = function (template, selector) { + this.find_and_replace(template, selector, this.value); +} + +function Thunk (func) { + this.func = func; +} +Thunk.prototype = new Param (); +Thunk.prototype.render = function (template, selector) { + this.find_and_replace( + template, + selector, + this.func(template, selector) + ); +} + +function MethodThunk (invocant, method_name) { + this.func = function () { return invocant[method_name]() } +} +MethodThunk.prototype = new Thunk (); + +function PropertyThunk (invocant, property_name) { + this.func = function () { return invocant[property_name] } +} +PropertyThunk.prototype = new Thunk (); + +function Collection (params) { + this.css_selector = params['css_selector']; + this.values = params['values']; + this.transformer = params['transformer']; +} +Collection.prototype = new Param (); +Collection.prototype.get_values = function () { + return (this.transformer == undefined) + ? this.values + : jQuery.map(this.values, this.transformer) +} +Collection.prototype.render = function (template, selector) { + var selection = template.find(selector).find(this.css_selector); + var target = selection.parent(); + target.empty(); + jQuery.each( + this.get_values(), + function () { + target.append( + selection.clone(true).process_template(this) + ) + } + ); +} + +function Hierarchy (params) { + this.list_selector = params['list_selector']; + this.item_selector = params['item_selector']; + this.values = params['values']; +} +Hierarchy.prototype = new Param (); +Hierarchy.prototype.get_values = function () { return this.values } +Hierarchy.prototype.render = function (template, selector) { + var selection = template.find(selector); + var list_selection = selection.find(this.list_selector); + var item_selection = selection.find(this.item_selector); + + selection.empty(); + list_selection.empty(); + + var traverse = function (element, tree) { + // build a node ... + var node_element = item_selection.clone(true).process_template( + tree['node'] + ); + element.append(node_element); + // if the node has children then ... + if (tree['children'] != undefined) { + var new_element = list_selection.clone(true); + jQuery.each( + tree['children'], + function () { + traverse(new_element, this); + node_element.append(new_element); + } + ); + } + }; + + // create the root ... + var root_node = list_selection.clone(true); + traverse(root_node, this.get_values()); + selection.append(root_node); +} + +/************* JQuery Plugin *******************/ + +jQuery.fn.extend({ + process_template : function (params) { + var template = this; + jQuery.each( + params, + function (selector, param) { + ((typeof param == 'object') + ? param + : new Param (param)).render(template, selector) + } + ); + return template; + } +}); + +/********************** Paramters ***************************/ + +function User (name) { + this._name = name; +} +User.prototype.name = function () { return this._name } + +function Product (id, name) { + this._id = id; + this.name = name; +} +Product.prototype.get_id = function () { return this._id } + +var params = { + '#logo' : new Thunk (function (t, selector) { + t.find(selector).attr({ + 'src' : 'http://iinteractive.com/images/logo.gif', + 'style' : 'padding: 10px;', + }); + }), + '.username' : new MethodThunk (new User ('Stevan'), "name"), + '#user_quotation' : 'JQuery Rocks', + '.copyright' : new Thunk (function () { return "Copyright (c) " + (new Date ()).getFullYear() }), + '#products' : new Collection ({ + css_selector : '.row', + values : [ + new Product (10, 'Foo'), + new Product (11, 'Bar'), + new Product (12, 'Baz'), + ], + transformer : function (val) { + return { + '.id' : val.get_id(), + '.name' : new PropertyThunk (val, 'name'), + } + } + }), + '#dogs' : new Collection ({ + css_selector : '.table_row', + values : [ + { '.sound' : "Bark" }, + { '.sound' : "Woof" }, + ] + }), + '#cats' : new Hierarchy ({ + list_selector : '.list', + item_selector : '.item', + values : { + node : { '.name' : "Twinkles" }, + children : [ + { node : { '.name' : "Shnuckums" } }, + { + node : { '.name' : "Bilbo" }, + children : [ + { + node : { '.name' : "Dweezil" }, + children : [ + { node : { '.name' : "Tabby" } }, + ] + }, + { node : { '.name' : "Abraxas" } }, + ] + }, + ] + } + }), + '#rooms' : new Hierarchy ({ + list_selector : '.list', + item_selector : '.item', + values : { + node : { '.name' : "Ceiling" }, + children : [ + { node : { '.name' : "Basement" } }, + { + node : { '.name' : "Garage" }, + children : [ + { node : { '.name' : "Root Cellar" } }, + { + node : { '.name' : "Kitchen" }, + children : [ + { node : { '.name' : "Under The Stairs" } }, + ] + }, + { node : { '.name' : "Bathroom" } }, + ] + }, + ] + } + }), +}; + +$(document).ready(function () { + $('body').process_template(params); +}); + +</script> +</head> +<body> +<img id="logo" src="http://l.yimg.com/a/i/ww/beta/y3.gif" border="1" /> +<hr/> +<div class="username">Foo</div> +<hr/> +<p id="user_quotation">Text goes here</p> +<div id="products" style="border: 1px solid grey; width: 250px"> + <div class="row" style="border: 1px solid red; padding: 2px; margin: 2px;"> + <span class="id">ID</span> + <span class="name">NAME</span> + </div> +</div> +<br/> +<table id="dogs" border="1"> + <thead> + <th>Hello</th> + </thead> + <tbody> + <tr class="table_row"> + <td>My dog says <span class="sound">NAME</span></td> + </tr> + </tbody> +</table> +<hr/> +<div id="cats"> + <ul class="list"> + <li class="item">My cat is named <span class="name">NAME</span></li> + </ul> +</div> +<hr/> +<div id="rooms"> + <div class="list" style="padding-left: 10px"> + <div class="item" style="padding-left: 10px">My room is <span class="name">NAME</span></div> + </div> +</div> +<hr/> +<div class="username">Foo</div> +<hr/> +<div class="copyright">Copyleft</div> +</body> +</html>