--- /dev/null
+<?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>
--- /dev/null
+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
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+<public:component>\r
+<public:attach event="onpropertychange" onevent="doFix()" />\r
+\r
+<script>\r
+\r
+// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com\r
+// Free usage permitted as long as this notice remains intact.\r
+\r
+// This must be a path to a blank image. That's all the configuration you need here.\r
+var blankImg = 'ui/default/blank.gif';\r
+\r
+var f = 'DXImageTransform.Microsoft.AlphaImageLoader';\r
+\r
+function filt(s, m) {\r
+ if (filters[f]) {\r
+ filters[f].enabled = s ? true : false;\r
+ if (s) with (filters[f]) { src = s; sizingMethod = m }\r
+ } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")';\r
+}\r
+\r
+function doFix() {\r
+ if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) ||\r
+ (event && !/(background|src)/.test(event.propertyName))) return;\r
+\r
+ if (tagName == 'IMG') {\r
+ if ((/\.png$/i).test(src)) {\r
+ filt(src, 'image'); // was 'scale'\r
+ src = blankImg;\r
+ } else if (src.indexOf(blankImg) < 0) filt();\r
+ } else if (style.backgroundImage) {\r
+ if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) {\r
+ var s = RegExp.$1;\r
+ style.backgroundImage = '';\r
+ filt(s, 'crop');\r
+ } else filt();\r
+ }\r
+}\r
+\r
+doFix();\r
+\r
+</script>\r
+</public:component>
\ No newline at end of file
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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
--- /dev/null
+/* 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;}
+ */
--- /dev/null
+/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */\r.slide, ul {page-break-inside: avoid; visibility: visible !important;}\rh1 {page-break-after: avoid;}\r\rbody {font-size: 12pt; background: white;}\r* {color: black;}\r\r#slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;}\r#slide0 h3 {margin: 0; padding: 0;}\r#slide0 h4 {margin: 0 0 0.5em; padding: 0;}\r#slide0 {margin-bottom: 3em;}\r\rh1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;}\r.extra {background: transparent !important;}\rdiv.extra, pre.extra, .example {font-size: 10pt; color: #333;}\rul.extra a {font-weight: bold;}\rp.example {display: none;}\r\r#header {display: none;}\r#footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;}\r#footer h2, #controls {display: none;}\r\r/* The following rule keeps the layout stuff out of print. Remove at your own risk! */\r.layout, .layout * {display: none !important;}\r
\ No newline at end of file
--- /dev/null
+/* 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;}
--- /dev/null
+@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
--- /dev/null
+// 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
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+<public:component>\r
+<public:attach event="onpropertychange" onevent="doFix()" />\r
+\r
+<script>\r
+\r
+// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com\r
+// Free usage permitted as long as this notice remains intact.\r
+\r
+// This must be a path to a blank image. That's all the configuration you need here.\r
+var blankImg = 'ui/default/blank.gif';\r
+\r
+var f = 'DXImageTransform.Microsoft.AlphaImageLoader';\r
+\r
+function filt(s, m) {\r
+ if (filters[f]) {\r
+ filters[f].enabled = s ? true : false;\r
+ if (s) with (filters[f]) { src = s; sizingMethod = m }\r
+ } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")';\r
+}\r
+\r
+function doFix() {\r
+ if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) ||\r
+ (event && !/(background|src)/.test(event.propertyName))) return;\r
+\r
+ if (tagName == 'IMG') {\r
+ if ((/\.png$/i).test(src)) {\r
+ filt(src, 'image'); // was 'scale'\r
+ src = blankImg;\r
+ } else if (src.indexOf(blankImg) < 0) filt();\r
+ } else if (style.backgroundImage) {\r
+ if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) {\r
+ var s = RegExp.$1;\r
+ style.backgroundImage = '';\r
+ filt(s, 'crop');\r
+ } else filt();\r
+ }\r
+}\r
+\r
+doFix();\r
+\r
+</script>\r
+</public:component>
\ No newline at end of file
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
+ */
--- /dev/null
+/* 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;}
+ */
--- /dev/null
+/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */\r.slide, ul {page-break-inside: avoid; visibility: visible !important;}\rh1 {page-break-after: avoid;}\r\rbody {font-size: 12pt; background: white;}\r* {color: black;}\r\r#slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;}\r#slide0 h3 {margin: 0; padding: 0;}\r#slide0 h4 {margin: 0 0 0.5em; padding: 0;}\r#slide0 {margin-bottom: 3em;}\r\rh1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;}\r.extra {background: transparent !important;}\rdiv.extra, pre.extra, .example {font-size: 10pt; color: #333;}\rul.extra a {font-weight: bold;}\rp.example {display: none;}\r\r#header {display: none;}\r#footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;}\r#footer h2, #controls {display: none;}\r\r/* The following rule keeps the layout stuff out of print. Remove at your own risk! */\r.layout, .layout * {display: none !important;}\r
\ No newline at end of file
--- /dev/null
+/* 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;}
--- /dev/null
+@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
--- /dev/null
+// 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
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<!-- Do not edit this document! The system will likely break if you do. -->\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<title>Notes</title>\r
+<link rel="stylesheet" href="default/notes.css" type="text/css" />\r
+<script type="text/javascript">\r
+// <![CDATA[\r
+ document.onkeyup = opener.keys;\r
+ document.onkeypress = opener.trap;\r
+ document.onclick = opener.clicker;\r
+// ]]>\r
+</script>\r
+</head>\r
+\r
+<body onload="opener.s5NotesWindowLoaded=true;" onunload="opener.s5NotesWindowLoaded=false;">\r
+\r
+\r
+<div class="timers" id="elapsed">\r
+<h1>\r
+<a href="#" onclick="opener.minimizeTimer('elapsed'); return false;">Elapsed Time</a>\r
+</h1>\r
+<ul>\r
+<li>\r
+<h2>Presentation</h2>\r
+<span class="clock" id="elapsed-presentation">00:00:00</span>\r
+</li>\r
+<li>\r
+<h2>Current Slide</h2>\r
+<span class="clock" id="elapsed-slide">00:00:00</span>\r
+</li>\r
+</ul>\r
+<div class="controls">\r
+<a href="#reset-elapsed" onclick="opener.resetElapsedTime(); return false;" title="Reset Elapsed Time">|←</a>\r
+</div>\r
+</div>\r
+\r
+<div class="timers" id="remaining">\r
+<h1>\r
+<a href="#" onclick="opener.minimizeTimer('remaining'); return false;">Remaining Time</a>\r
+</h1>\r
+<p>\r
+<a href="#subtract-remaining" class="control" id="minus" onclick="opener.alterRemainingTime('-5'); return false;" title="Subtract 5 Minutes">-</a>\r
+<span class="clock" id="timeLeft">00:00:00</span>\r
+<a href="#add-remaining" class="control" id="plus" onclick="opener.alterRemainingTime('5'); return false;" title="Add 5 Minutes">+</a>\r
+</p>\r
+<div class="controls">\r
+<form action="#" onsubmit="opener.resetRemainingTime(); return false;">\r
+<input type="text" class="text" id="startFrom" value="0" size="4" maxlength="4" />\r
+<a href="#toggle-remaining" onclick="opener.toggleRemainingTime(); return false;" title="Pause/Run Remaining Time">||</a>\r
+<a href="#reset-remaining" onclick="opener.resetRemainingTime(); return false;" title="Reset Remaining Time">|←</a>\r
+</form>\r
+</div>\r
+</div>\r
+\r
+<h2 id="slide">...</h2>\r
+<div id="notes"></div>\r
+\r
+<h2 id="next">...</h2>\r
+<div id="nextnotes"></div>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+<?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>
--- /dev/null
+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
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+<public:component>\r
+<public:attach event="onpropertychange" onevent="doFix()" />\r
+\r
+<script>\r
+\r
+// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com\r
+// Free usage permitted as long as this notice remains intact.\r
+\r
+// This must be a path to a blank image. That's all the configuration you need here.\r
+var blankImg = 'ui/default/blank.gif';\r
+\r
+var f = 'DXImageTransform.Microsoft.AlphaImageLoader';\r
+\r
+function filt(s, m) {\r
+ if (filters[f]) {\r
+ filters[f].enabled = s ? true : false;\r
+ if (s) with (filters[f]) { src = s; sizingMethod = m }\r
+ } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")';\r
+}\r
+\r
+function doFix() {\r
+ if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) ||\r
+ (event && !/(background|src)/.test(event.propertyName))) return;\r
+\r
+ if (tagName == 'IMG') {\r
+ if ((/\.png$/i).test(src)) {\r
+ filt(src, 'image'); // was 'scale'\r
+ src = blankImg;\r
+ } else if (src.indexOf(blankImg) < 0) filt();\r
+ } else if (style.backgroundImage) {\r
+ if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) {\r
+ var s = RegExp.$1;\r
+ style.backgroundImage = '';\r
+ filt(s, 'crop');\r
+ } else filt();\r
+ }\r
+}\r
+\r
+doFix();\r
+\r
+</script>\r
+</public:component>
\ No newline at end of file
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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
--- /dev/null
+/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */\r.slide, ul {page-break-inside: avoid; visibility: visible !important;}\rh1 {page-break-after: avoid;}\r\rbody {font-size: 12pt; background: white;}\r* {color: black;}\r\r#slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;}\r#slide0 h3 {margin: 0; padding: 0;}\r#slide0 h4 {margin: 0 0 0.5em; padding: 0;}\r#slide0 {margin-bottom: 3em;}\r\rh1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;}\r.extra {background: transparent !important;}\rdiv.extra, pre.extra, .example {font-size: 10pt; color: #333;}\rul.extra a {font-weight: bold;}\rp.example {display: none;}\r\r#header {display: none;}\r#footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;}\r#footer h2, #controls {display: none;}\r\r/* The following rule keeps the layout stuff out of print. Remove at your own risk! */\r.layout, .layout * {display: none !important;}\r
\ No newline at end of file
--- /dev/null
+/* 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;}
--- /dev/null
+@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
--- /dev/null
+// 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
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+<public:component>\r
+<public:attach event="onpropertychange" onevent="doFix()" />\r
+\r
+<script>\r
+\r
+// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com\r
+// Free usage permitted as long as this notice remains intact.\r
+\r
+// This must be a path to a blank image. That's all the configuration you need here.\r
+var blankImg = 'ui/default/blank.gif';\r
+\r
+var f = 'DXImageTransform.Microsoft.AlphaImageLoader';\r
+\r
+function filt(s, m) {\r
+ if (filters[f]) {\r
+ filters[f].enabled = s ? true : false;\r
+ if (s) with (filters[f]) { src = s; sizingMethod = m }\r
+ } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")';\r
+}\r
+\r
+function doFix() {\r
+ if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) ||\r
+ (event && !/(background|src)/.test(event.propertyName))) return;\r
+\r
+ if (tagName == 'IMG') {\r
+ if ((/\.png$/i).test(src)) {\r
+ filt(src, 'image'); // was 'scale'\r
+ src = blankImg;\r
+ } else if (src.indexOf(blankImg) < 0) filt();\r
+ } else if (style.backgroundImage) {\r
+ if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) {\r
+ var s = RegExp.$1;\r
+ style.backgroundImage = '';\r
+ filt(s, 'crop');\r
+ } else filt();\r
+ }\r
+}\r
+\r
+doFix();\r
+\r
+</script>\r
+</public:component>
\ No newline at end of file
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
+ */
+
+
--- /dev/null
+/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */\r.slide, ul {page-break-inside: avoid; visibility: visible !important;}\rh1 {page-break-after: avoid;}\r\rbody {font-size: 12pt; background: white;}\r* {color: black;}\r\r#slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;}\r#slide0 h3 {margin: 0; padding: 0;}\r#slide0 h4 {margin: 0 0 0.5em; padding: 0;}\r#slide0 {margin-bottom: 3em;}\r\rh1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;}\r.extra {background: transparent !important;}\rdiv.extra, pre.extra, .example {font-size: 10pt; color: #333;}\rul.extra a {font-weight: bold;}\rp.example {display: none;}\r\r#header {display: none;}\r#footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;}\r#footer h2, #controls {display: none;}\r\r/* The following rule keeps the layout stuff out of print. Remove at your own risk! */\r.layout, .layout * {display: none !important;}\r
\ No newline at end of file
--- /dev/null
+/* 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;}
--- /dev/null
+@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
--- /dev/null
+// 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
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<!-- Do not edit this document! The system will likely break if you do. -->\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<title>Notes</title>\r
+<link rel="stylesheet" href="default/notes.css" type="text/css" />\r
+<script type="text/javascript">\r
+// <![CDATA[\r
+ document.onkeyup = opener.keys;\r
+ document.onkeypress = opener.trap;\r
+ document.onclick = opener.clicker;\r
+// ]]>\r
+</script>\r
+</head>\r
+\r
+<body onload="opener.s5NotesWindowLoaded=true;" onunload="opener.s5NotesWindowLoaded=false;">\r
+\r
+\r
+<div class="timers" id="elapsed">\r
+<h1>\r
+<a href="#" onclick="opener.minimizeTimer('elapsed'); return false;">Elapsed Time</a>\r
+</h1>\r
+<ul>\r
+<li>\r
+<h2>Presentation</h2>\r
+<span class="clock" id="elapsed-presentation">00:00:00</span>\r
+</li>\r
+<li>\r
+<h2>Current Slide</h2>\r
+<span class="clock" id="elapsed-slide">00:00:00</span>\r
+</li>\r
+</ul>\r
+<div class="controls">\r
+<a href="#reset-elapsed" onclick="opener.resetElapsedTime(); return false;" title="Reset Elapsed Time">|←</a>\r
+</div>\r
+</div>\r
+\r
+<div class="timers" id="remaining">\r
+<h1>\r
+<a href="#" onclick="opener.minimizeTimer('remaining'); return false;">Remaining Time</a>\r
+</h1>\r
+<p>\r
+<a href="#subtract-remaining" class="control" id="minus" onclick="opener.alterRemainingTime('-5'); return false;" title="Subtract 5 Minutes">-</a>\r
+<span class="clock" id="timeLeft">00:00:00</span>\r
+<a href="#add-remaining" class="control" id="plus" onclick="opener.alterRemainingTime('5'); return false;" title="Add 5 Minutes">+</a>\r
+</p>\r
+<div class="controls">\r
+<form action="#" onsubmit="opener.resetRemainingTime(); return false;">\r
+<input type="text" class="text" id="startFrom" value="0" size="4" maxlength="4" />\r
+<a href="#toggle-remaining" onclick="opener.toggleRemainingTime(); return false;" title="Pause/Run Remaining Time">||</a>\r
+<a href="#reset-remaining" onclick="opener.resetRemainingTime(); return false;" title="Reset Remaining Time">|←</a>\r
+</form>\r
+</div>\r
+</div>\r
+\r
+<h2 id="slide">...</h2>\r
+<div id="notes"></div>\r
+\r
+<h2 id="next">...</h2>\r
+<div id="nextnotes"></div>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+<?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 ***** -->
+
+
--- /dev/null
+<?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 ***** -->
+
+
--- /dev/null
+@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
--- /dev/null
+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);
--- /dev/null
+<?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>
--- /dev/null
+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
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+<public:component>\r
+<public:attach event="onpropertychange" onevent="doFix()" />\r
+\r
+<script>\r
+\r
+// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com\r
+// Free usage permitted as long as this notice remains intact.\r
+\r
+// This must be a path to a blank image. That's all the configuration you need here.\r
+var blankImg = 'ui/default/blank.gif';\r
+\r
+var f = 'DXImageTransform.Microsoft.AlphaImageLoader';\r
+\r
+function filt(s, m) {\r
+ if (filters[f]) {\r
+ filters[f].enabled = s ? true : false;\r
+ if (s) with (filters[f]) { src = s; sizingMethod = m }\r
+ } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")';\r
+}\r
+\r
+function doFix() {\r
+ if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) ||\r
+ (event && !/(background|src)/.test(event.propertyName))) return;\r
+\r
+ if (tagName == 'IMG') {\r
+ if ((/\.png$/i).test(src)) {\r
+ filt(src, 'image'); // was 'scale'\r
+ src = blankImg;\r
+ } else if (src.indexOf(blankImg) < 0) filt();\r
+ } else if (style.backgroundImage) {\r
+ if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) {\r
+ var s = RegExp.$1;\r
+ style.backgroundImage = '';\r
+ filt(s, 'crop');\r
+ } else filt();\r
+ }\r
+}\r
+\r
+doFix();\r
+\r
+</script>\r
+</public:component>
\ No newline at end of file
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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
--- /dev/null
+/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */\r.slide, ul {page-break-inside: avoid; visibility: visible !important;}\rh1 {page-break-after: avoid;}\r\rbody {font-size: 12pt; background: white;}\r* {color: black;}\r\r#slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;}\r#slide0 h3 {margin: 0; padding: 0;}\r#slide0 h4 {margin: 0 0 0.5em; padding: 0;}\r#slide0 {margin-bottom: 3em;}\r\rh1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;}\r.extra {background: transparent !important;}\rdiv.extra, pre.extra, .example {font-size: 10pt; color: #333;}\rul.extra a {font-weight: bold;}\rp.example {display: none;}\r\r#header {display: none;}\r#footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;}\r#footer h2, #controls {display: none;}\r\r/* The following rule keeps the layout stuff out of print. Remove at your own risk! */\r.layout, .layout * {display: none !important;}\r
\ No newline at end of file
--- /dev/null
+/* 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;}
--- /dev/null
+@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
--- /dev/null
+// 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
--- /dev/null
+/* 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;}
+*/
--- /dev/null
+<public:component>\r
+<public:attach event="onpropertychange" onevent="doFix()" />\r
+\r
+<script>\r
+\r
+// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com\r
+// Free usage permitted as long as this notice remains intact.\r
+\r
+// This must be a path to a blank image. That's all the configuration you need here.\r
+var blankImg = 'ui/default/blank.gif';\r
+\r
+var f = 'DXImageTransform.Microsoft.AlphaImageLoader';\r
+\r
+function filt(s, m) {\r
+ if (filters[f]) {\r
+ filters[f].enabled = s ? true : false;\r
+ if (s) with (filters[f]) { src = s; sizingMethod = m }\r
+ } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")';\r
+}\r
+\r
+function doFix() {\r
+ if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) ||\r
+ (event && !/(background|src)/.test(event.propertyName))) return;\r
+\r
+ if (tagName == 'IMG') {\r
+ if ((/\.png$/i).test(src)) {\r
+ filt(src, 'image'); // was 'scale'\r
+ src = blankImg;\r
+ } else if (src.indexOf(blankImg) < 0) filt();\r
+ } else if (style.backgroundImage) {\r
+ if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) {\r
+ var s = RegExp.$1;\r
+ style.backgroundImage = '';\r
+ filt(s, 'crop');\r
+ } else filt();\r
+ }\r
+}\r
+\r
+doFix();\r
+\r
+</script>\r
+</public:component>
\ No newline at end of file
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
+ */
--- /dev/null
+/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */\r.slide, ul {page-break-inside: avoid; visibility: visible !important;}\rh1 {page-break-after: avoid;}\r\rbody {font-size: 12pt; background: white;}\r* {color: black;}\r\r#slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;}\r#slide0 h3 {margin: 0; padding: 0;}\r#slide0 h4 {margin: 0 0 0.5em; padding: 0;}\r#slide0 {margin-bottom: 3em;}\r\rh1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;}\r.extra {background: transparent !important;}\rdiv.extra, pre.extra, .example {font-size: 10pt; color: #333;}\rul.extra a {font-weight: bold;}\rp.example {display: none;}\r\r#header {display: none;}\r#footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;}\r#footer h2, #controls {display: none;}\r\r/* The following rule keeps the layout stuff out of print. Remove at your own risk! */\r.layout, .layout * {display: none !important;}\r
\ No newline at end of file
--- /dev/null
+/* 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;}
--- /dev/null
+@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
--- /dev/null
+// 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
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<!-- Do not edit this document! The system will likely break if you do. -->\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<title>Notes</title>\r
+<link rel="stylesheet" href="default/notes.css" type="text/css" />\r
+<script type="text/javascript">\r
+// <![CDATA[\r
+ document.onkeyup = opener.keys;\r
+ document.onkeypress = opener.trap;\r
+ document.onclick = opener.clicker;\r
+// ]]>\r
+</script>\r
+</head>\r
+\r
+<body onload="opener.s5NotesWindowLoaded=true;" onunload="opener.s5NotesWindowLoaded=false;">\r
+\r
+\r
+<div class="timers" id="elapsed">\r
+<h1>\r
+<a href="#" onclick="opener.minimizeTimer('elapsed'); return false;">Elapsed Time</a>\r
+</h1>\r
+<ul>\r
+<li>\r
+<h2>Presentation</h2>\r
+<span class="clock" id="elapsed-presentation">00:00:00</span>\r
+</li>\r
+<li>\r
+<h2>Current Slide</h2>\r
+<span class="clock" id="elapsed-slide">00:00:00</span>\r
+</li>\r
+</ul>\r
+<div class="controls">\r
+<a href="#reset-elapsed" onclick="opener.resetElapsedTime(); return false;" title="Reset Elapsed Time">|←</a>\r
+</div>\r
+</div>\r
+\r
+<div class="timers" id="remaining">\r
+<h1>\r
+<a href="#" onclick="opener.minimizeTimer('remaining'); return false;">Remaining Time</a>\r
+</h1>\r
+<p>\r
+<a href="#subtract-remaining" class="control" id="minus" onclick="opener.alterRemainingTime('-5'); return false;" title="Subtract 5 Minutes">-</a>\r
+<span class="clock" id="timeLeft">00:00:00</span>\r
+<a href="#add-remaining" class="control" id="plus" onclick="opener.alterRemainingTime('5'); return false;" title="Add 5 Minutes">+</a>\r
+</p>\r
+<div class="controls">\r
+<form action="#" onsubmit="opener.resetRemainingTime(); return false;">\r
+<input type="text" class="text" id="startFrom" value="0" size="4" maxlength="4" />\r
+<a href="#toggle-remaining" onclick="opener.toggleRemainingTime(); return false;" title="Pause/Run Remaining Time">||</a>\r
+<a href="#reset-remaining" onclick="opener.resetRemainingTime(); return false;" title="Reset Remaining Time">|←</a>\r
+</form>\r
+</div>\r
+</div>\r
+\r
+<h2 id="slide">...</h2>\r
+<div id="notes"></div>\r
+\r
+<h2 id="next">...</h2>\r
+<div id="nextnotes"></div>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+
+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;
+}
+
--- /dev/null
+<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>
+
--- /dev/null
+<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>
--- /dev/null
+<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>
--- /dev/null
+<?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>
+
--- /dev/null
+----
+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}
--- /dev/null
+----
+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}
--- /dev/null
+################################################################################
+# 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
+
--- /dev/null
+# 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
--- /dev/null
+/*
+ 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;}
+
--- /dev/null
+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 }
--- /dev/null
+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 }
--- /dev/null
+<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>
--- /dev/null
+<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>
--- /dev/null
+<!-- 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 -->
--- /dev/null
+<!-- 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 -->
--- /dev/null
+<!-- BEGIN slide -->
+<div class="slide">
+[% image_html %]
+[% slide_content %]
+[%- UNLESS last -%]
+<small>continued...</small>
+[% END %]
+</div>
+<!-- END slide -->
--- /dev/null
+/* 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;}
+*/
+
--- /dev/null
+<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>
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
+
--- /dev/null
+<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>
+
--- /dev/null
+/*
+ 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;}
+
--- /dev/null
+/*
+ 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;}
+
--- /dev/null
+/* 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;}
--- /dev/null
+/* 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;}
+
--- /dev/null
+// 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);}
--- /dev/null
+@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 */
+
--- /dev/null
+// 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;
+
+
+
+
--- /dev/null
+<!-- 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>
+
--- /dev/null
+// 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
--- /dev/null
+<!-- 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 -->
--- /dev/null
+/* 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 */
--- /dev/null
+<!-- 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 -->
--- /dev/null
+<!-- 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 -->
--- /dev/null
+
+<!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 -->
--- /dev/null
+<?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 ***** -->
+
+
--- /dev/null
+@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
--- /dev/null
+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);
--- /dev/null
+<?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 ***** -->
+
+
--- /dev/null
+@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
--- /dev/null
+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);
--- /dev/null
+<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>