From 1ecfd131cfa4f1cd67ec3a7d396992f0b5e54582 Mon Sep 17 00:00:00 2001 From: Alan Pearce Date: Sun, 5 Apr 2020 12:23:07 +0200 Subject: Remove presentation slides --- static/talks/fp-js/index.html | 431 ---------------------- static/talks/fp-js/index.org | 226 ------------ static/talks/fp-js/s5-blank.html | 50 --- static/talks/fp-js/ui/default/blank.gif | Bin 49 -> 0 bytes static/talks/fp-js/ui/default/bodybg.gif | Bin 10119 -> 0 bytes static/talks/fp-js/ui/default/framing.css | 23 -- static/talks/fp-js/ui/default/iepngfix.htc | 42 --- static/talks/fp-js/ui/default/opera.css | 7 - static/talks/fp-js/ui/default/outline.css | 15 - static/talks/fp-js/ui/default/pretty.css | 86 ----- static/talks/fp-js/ui/default/print.css | 1 - static/talks/fp-js/ui/default/s5-core.css | 9 - static/talks/fp-js/ui/default/slides.css | 3 - static/talks/fp-js/ui/default/slides.js | 553 ----------------------------- 14 files changed, 1446 deletions(-) delete mode 100644 static/talks/fp-js/index.html delete mode 100644 static/talks/fp-js/index.org delete mode 100644 static/talks/fp-js/s5-blank.html delete mode 100644 static/talks/fp-js/ui/default/blank.gif delete mode 100755 static/talks/fp-js/ui/default/bodybg.gif delete mode 100644 static/talks/fp-js/ui/default/framing.css delete mode 100644 static/talks/fp-js/ui/default/iepngfix.htc delete mode 100644 static/talks/fp-js/ui/default/opera.css delete mode 100644 static/talks/fp-js/ui/default/outline.css delete mode 100644 static/talks/fp-js/ui/default/pretty.css delete mode 100644 static/talks/fp-js/ui/default/print.css delete mode 100644 static/talks/fp-js/ui/default/s5-core.css delete mode 100644 static/talks/fp-js/ui/default/slides.css delete mode 100644 static/talks/fp-js/ui/default/slides.js diff --git a/static/talks/fp-js/index.html b/static/talks/fp-js/index.html deleted file mode 100644 index e90650c..0000000 --- a/static/talks/fp-js/index.html +++ /dev/null @@ -1,431 +0,0 @@ - - - - - - -Functional Programming in JavaScript - - - - - - - - - - - - - - - - -
-
-
- - - - -
-
-
-

Functional Programming in JavaScript

-

-

Alan Pearce

-

alan@alanpearce.eu

-

-
-
-

Table of Contents

-
-
    -
  • 1. Why?
  • -
  • 2. Concepts
  • -
  • 3. Further concepts
  • -
  • 4. First-class functions
  • -
  • 5. Higher-order functions
  • -
  • 6. Higher-order functions (cont.)
  • -
  • 7. Pure functions
  • -
  • 8. Recursion
  • -
  • 9. Partial application
  • -
  • 10. Partial application (cont.)
  • -
  • 11. Currying
  • -
  • 12. Easy Currying
  • -
  • 13. Practical Currying
  • -
  • 14. Functional composition
  • -
  • 15. Functional composition (cont.)
  • -
  • 16. pipe
  • -
  • 17. Point-free programming
  • -
  • 18. Further Resources
  • -
-
-
- -
-

1 Why?

-
-

-Imperative programming is concerned with how -

- -

-Functional programming is concerned with what -

-
-
- -
-

2 Concepts

-
-
    -
  • First-class Functions
  • -
  • Higher-order Functions
  • -
  • Recursion
  • -
  • Pure functions
  • -
  • Currying & Partial Application
  • -
-
-
- -
-

3 Further concepts

-
-
    -
  • Lazy Evaluation
  • -
  • Types & Data Structures
  • -
  • Category Theory
  • -
-
-
- -
-

4 First-class functions

-
-
    -
  • Are values
  • -
  • Have no restriction on their use
  • -
  • Enable the use of callback functions in JavaScript
  • -
- -

- -

- -
-
var fn = function () {
-  return 2
-}
-
-
-
-
- - -
-

5 Higher-order functions

-
-

-Functions that operate on other functions are higher-order functions -

- -

- -

- -
-
var succ = function (x) {
-  return x + 1
-}
-
-var arr = [1, 2, 3, 4]
-
-arr.map(succ)
-
-
- -

-Here, Array.prototype.map is the higher-order function -

-
-
- -
-

6 Higher-order functions (cont.)

-
-

-Functions that return functions are also higher-order functions -

- -

- -

- -
-
function adder (n) {
-  return function (x) {
-    return n + x
-  }
-}
-
-var add1 = adder(1)
-
-
- -

-adder is a higher-order function -

-
-
- -
-

7 Pure functions

-
-

-Functions without side-effects -

- -
-
var succ = (x) => x + 1
-
-console.log(succ(succ(1)))
-
-// could be optimised away by a compiler, e.g.:
-
-console.log(3)
-
-
-
-
- -
-

8 Recursion

-
-

-Functions that call themselves -

- -
-
function fibonacci (n) {
-  switch (n) {
-    case 0:
-    case 1:
-      return 1
-    default: 
-      return fibonacci(n - 1) + fibonacci(n - 2)
-  }
-}
-
-
-
-
- -
-

9 Partial application

-
-

-The infamous Function.prototype.bind in JavaScript -

- -
-
function add (x, y) {
-  return x + y
-}
-
-var add1 = add.bind(add, 1)
-
-add1(3) // = 4
-
-
-
-
- -
-

10 Partial application (cont.)

-
-

-After ES6 introduced arrow functions, partial application has become -more popular -

- -
-
var add = x => y => x + y
-
-
-
-
- -
-

11 Currying

-
-

-Related to partial application, but more implicit and general -

- -

-Translates 1 function of arity n to n functions of arity 1 -

- -
-
function volume (w, d, h) {
-  return w * d * h
-}
-
-var vol = curry(volume)
-vol(10)(20)(30)
-// is strictly equivalent to
-volume(10, 20, 30)
-
-
-
-
- -
-

12 Easy Currying

-
-

-In order to make currying (and partial application) easier to use, -move the most important argument to a function to the end: -

- -
-
var badMap = (arr, fn) => arr.map(fn)
-var goodMap = (fn, arr) => arr.map(fn)
-var curriedBadMap = curry(badmap)
-var curriedGoodMap = curry(goodMap)
-
-var goodDoubleArray = goodMap(x => x * 2)
-var badDoubleArray = badMap(_, x => x * 2)
-
-
- -

-The bad version requires the curry function to support a magic -placeholder argument and doesn't look as clean. -

-
-
- -
-

13 Practical Currying

-
-

-Currying is not automatic in JavaScript, as in other languages -

- -

-External tools aren't (so far) able to statically analyse curried -functions -

- -

-Solution: Don't expose curried functions -Instead, write functions as if currying were automatic -

- -

-If consumers want to curry, they can. If they don't, their editor or -language server will show them the arguments -

-
-
- -
-

14 Functional composition

-
-

-Creating functions from other functions -

- -

-Usually provided by compose (right-to-left) and pipe (left-to-right) -

- -

-A very simple definition of compose for only two functions would look like this -

- -
-
function compose (f, g) {
-  return function (...args) {
-    return f(g(...args))
-  }
-}
-
-
-
-
- -
-

15 Functional composition (cont.)

-
-
-
var plusOne = x => x + 1
-var timesTwo = x => x * 2
-
-var plusOneTimesTwo = compose(timesTwo, plusOne)
-var timesTwoPlusOne = compose(plusOne, timesTwo)
-
-nextDoubled(3) // = (3 + 1) * 2 = 8
-doubledPlusOne(3) // = (3 * 2) + 1 = 7
-
-
-
-
- -
-

16 pipe

-
-

-What about pipe? -

- -

-pipe does the same thing, but runs the functions the other way around -

- -

-pipe(f, g) is the same as compose(g, f) -

-
-
- -
-

17 Point-free programming

-
-

-With currying and higher-order functions, we (often) don't need to declare function arguments -

- -
-
var modulo = a => b => b % a
-var eq = a => b => a === b
-
-var isEven = x => eq(0)(modulo(2)(x))
-var isEvenPointFree = compose(eq(0), modulo(2))
-
-
-
-
- -
-

18 Further Resources

-
- -
-
- - -
- - diff --git a/static/talks/fp-js/index.org b/static/talks/fp-js/index.org deleted file mode 100644 index 8a4bf6c..0000000 --- a/static/talks/fp-js/index.org +++ /dev/null @@ -1,226 +0,0 @@ -#+TITLE: Functional Programming in JavaScript -#+PROPERTY: :html-toplevel-hlevel 1 -#+PROPERTY: :with-toc 0 -* Why? - -Imperative programming is concerned with *how* - -Functional programming is concerned with *what* - -* Concepts - - - First-class Functions - - Higher-order Functions - - Recursion - - Pure functions - - Currying & Partial Application - -* Further concepts - - - Lazy Evaluation - - Types & Data Structures - - Category Theory - -* First-class functions - - - Have no restriction on their use - - Are values - - Enable the use of callback functions in JavaScript - - - -#+BEGIN_SRC js -const fn = function () { - return 2 -} -#+END_SRC - - -* Higher-order functions - -Functions that operate on other functions are higher-order functions - - - -#+BEGIN_SRC js -const succ = function (x) { - return x + 1 -} - -const arr = [1, 2, 3, 4] - -arr.map(succ) -#+END_SRC - -Here, =Array.prototype.map= is the higher-order function - -* Higher-order functions (cont.) - -Functions that return functions are also higher-order functions - - - -#+BEGIN_SRC js -function adder (n) { - return function (x) { - return n + x - } -} - -const add1 = adder(1) -#+END_SRC - -=adder= is a higher-order function - -* Pure functions - -Functions without side-effects - -#+BEGIN_SRC js -const succ = (x) => x + 1 - -console.log(succ(succ(1))) - -// could be optimised away by a compiler, e.g.: - -console.log(3) -#+END_SRC - -* Recursion - -Functions that call themselves - -#+BEGIN_SRC js -function fibonacci (n) { - switch (n) { - case 0: - case 1: - return 1 - default: - return fibonacci(n - 1) + fibonacci(n - 2) - } -} -#+END_SRC - -* Partial application - -The infamous =Function.prototype.bind= in JavaScript - -#+BEGIN_SRC js -function add (x, y) { - return x + y -} - -const add1 = add.bind(add, 1) - -add1(3) // = 4 -#+END_SRC - -* Partial application (cont.) - -After ES6 introduced arrow functions, partial application has become -more popular - -#+BEGIN_SRC js -const add = x => y => x + y -#+END_SRC - -* Currying - -Related to partial application, but more implicit and general - -Translates */1/ function of arity /n/* to */n/ functions of arity /1/* - -#+BEGIN_SRC js -function volume (w, d, h) { - return w * d * h -} - -const vol = curry(volume) -vol(10)(20)(30) -// is strictly equivalent to -volume(10, 20, 30) -#+END_SRC - -* Easy Currying - -In order to make currying (and partial application) easier to use, -move the *most important* argument to a function to the end: - -#+BEGIN_SRC js -const badMap = (arr, fn) => arr.map(fn) -const goodMap = (fn, arr) => arr.map(fn) -const curriedBadMap = curry(badmap) -const curriedGoodMap = curry(goodMap) - -const goodDoubleArray = goodMap(x => x * 2) -const badDoubleArray = badMap(_, x => x * 2) -#+END_SRC - -The bad version requires the curry function to support a magic -placeholder argument and doesn't look as clean. - -* Practical Currying - -Currying is not automatic in JavaScript, as in other languages - -External tools don't (currently) to statically analyse curried -functions - -Solution: Don't expose curried functions -Instead, write functions as if currying were automatic - -* Functional composition - -Creating functions from other functions - -Usually provided by =compose= (right-to-left) and =pipe= (left-to-right) - -A very simple definition of =compose= for only two functions would look like this - -#+BEGIN_SRC js -function compose (f, g) { - return function (...args) { - return f(g(...args)) - } -} -#+END_SRC - -* Functional composition (cont.) - -#+BEGIN_SRC js -const plusOne = x => x + 1 -const timesTwo = x => x * 2 - -const plusOneTimesTwo = compose(timesTwo, plusOne) -const timesTwoPlusOne = compose(plusOne, timesTwo) - -nextDoubled(3) // = (3 + 1) * 2 = 8 -timesTwoPlusOne(3) // = (3 * 2) + 1 = 7 -#+END_SRC - -* pipe - -What about =pipe=? - -=pipe= does the same thing, but runs the functions the other way around - -=pipe(f, g)= is the same as =compose(g, f)= - -* Point-free programming - -With currying and higher-order functions, we (often) don't need to declare function arguments - -#+BEGIN_SRC js -const modulo = a => b => b % a -const eq = a => b => a === b - -const isEven = x => eq(0)(modulo(2)(x)) -const isEvenPointFree = compose(eq(0), modulo(2)) -#+END_SRC - -* Further Resources - -- [[https://drboolean.gitbooks.io/mostly-adequate-guide/content/][Mostly adequate guide to FP (in javascript)]] -- [[http://ramdajs.com/][Ramda]], a general-purpose FP library -- [[https://sanctuary.js.org/][Sanctuary]], a JavaScript library for Haskellers diff --git a/static/talks/fp-js/s5-blank.html b/static/talks/fp-js/s5-blank.html deleted file mode 100644 index 0d126c7..0000000 --- a/static/talks/fp-js/s5-blank.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - -Functional Programming - - - - - - - - - - - - - - - - - - - -
-
-
- - - -
- - -
- -
-

Functional Programming

-

in JavaScript

-

Alan Pearce

-
- - -
- - - diff --git a/static/talks/fp-js/ui/default/blank.gif b/static/talks/fp-js/ui/default/blank.gif deleted file mode 100644 index 75b945d..0000000 Binary files a/static/talks/fp-js/ui/default/blank.gif and /dev/null differ diff --git a/static/talks/fp-js/ui/default/bodybg.gif b/static/talks/fp-js/ui/default/bodybg.gif deleted file mode 100755 index 5f448a1..0000000 Binary files a/static/talks/fp-js/ui/default/bodybg.gif and /dev/null differ diff --git a/static/talks/fp-js/ui/default/framing.css b/static/talks/fp-js/ui/default/framing.css deleted file mode 100644 index 14d8509..0000000 --- a/static/talks/fp-js/ui/default/framing.css +++ /dev/null @@ -1,23 +0,0 @@ -/* 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 {position: absolute; bottom: 0; right: 0; width: 100%; - margin: 0;} -#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; z-index: 10;} -html>body #currentSlide {position: fixed;} - -/* -div#header {background: #FCC;} -div#footer {background: #CCF;} -div#controls {background: #BBD;} -div#currentSlide {background: #FFC;} -*/ diff --git a/static/talks/fp-js/ui/default/iepngfix.htc b/static/talks/fp-js/ui/default/iepngfix.htc deleted file mode 100644 index bba2db7..0000000 --- a/static/talks/fp-js/ui/default/iepngfix.htc +++ /dev/null @@ -1,42 +0,0 @@ - - - - - \ No newline at end of file diff --git a/static/talks/fp-js/ui/default/opera.css b/static/talks/fp-js/ui/default/opera.css deleted file mode 100644 index 9e9d2a3..0000000 --- a/static/talks/fp-js/ui/default/opera.css +++ /dev/null @@ -1,7 +0,0 @@ -/* DO NOT CHANGE THESE unless you really want to break Opera Show */ -.slide { - visibility: visible !important; - position: static !important; - page-break-before: always; -} -#slide0 {page-break-before: avoid;} diff --git a/static/talks/fp-js/ui/default/outline.css b/static/talks/fp-js/ui/default/outline.css deleted file mode 100644 index 62db519..0000000 --- a/static/talks/fp-js/ui/default/outline.css +++ /dev/null @@ -1,15 +0,0 @@ -/* don't change this unless you want the layout stuff to show up in the outline view! */ - -.layout div, #footer *, #controlForm * {display: none;} -#footer, #controls, #controlForm, #navLinks, #toggle { - display: block; visibility: visible; margin: 0; padding: 0;} -#toggle {float: right; padding: 0.5em;} -html>body #toggle {position: fixed; top: 0; right: 0;} - -/* making the outline look pretty-ish */ - -#slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;} -#slide0 h1 {padding-top: 1.5em;} -.slide h1 {margin: 1.5em 0 0; padding-top: 0.25em; - border-top: 1px solid #888; border-bottom: 1px solid #AAA;} -#toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;} diff --git a/static/talks/fp-js/ui/default/pretty.css b/static/talks/fp-js/ui/default/pretty.css deleted file mode 100644 index 3d3acef..0000000 --- a/static/talks/fp-js/ui/default/pretty.css +++ /dev/null @@ -1,86 +0,0 @@ -/* Following are the presentation styles -- edit away! */ - -body {background: #FFF url(bodybg.gif) -16px 0 no-repeat; color: #000; font-size: 2em;} -: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: 50%; bottom: 0; - width: 50%; - text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;} -html>body div#controls {position: fixed; padding: 0 0 1em 0; - top: auto;} -div#controls form {position: absolute; bottom: 0; right: 0; width: 100%; - margin: 0; padding: 0;} -#controls #navLinks a {padding: 0; margin: 0 0.5em; - background: #005; border: none; color: #779; - cursor: pointer;} -#controls #navList {height: 1em;} -#controls #navList #jumplist {position: absolute; bottom: 0; right: 0; background: #DDD; color: #227;} - -#currentSlide {text-align: center; font-size: 0.5em; color: #449;} - -#slide0 {padding-top: 3.5em; font-size: 90%;} -#slide0 h1 {position: static; margin: 1em 0 0; padding: 0; - font: bold 2em Helvetica, sans-serif; white-space: normal; - color: #000; background: transparent;} -#slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;} -#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;} -#slide0 h4 {margin-top: 0; font-size: 1em;} - -ul.urls {list-style: none; display: inline; margin: 0;} -.urls li {display: inline; margin: 0;} -.note {display: none;} -.external {border-bottom: 1px dotted gray;} -html>body .external {border-bottom: none;} -.external:after {content: " \274F"; font-size: smaller; color: #77B;} - -.incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;} -img.incremental {visibility: hidden;} -.slide .current {color: #B02;} - - -/* diagnostics - -li:after {content: " [" attr(class) "]"; color: #F88;} - */ \ No newline at end of file diff --git a/static/talks/fp-js/ui/default/print.css b/static/talks/fp-js/ui/default/print.css deleted file mode 100644 index e7a71d1..0000000 --- a/static/talks/fp-js/ui/default/print.css +++ /dev/null @@ -1 +0,0 @@ -/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */ .slide, ul {page-break-inside: avoid; visibility: visible !important;} h1 {page-break-after: avoid;} body {font-size: 12pt; background: white;} * {color: black;} #slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;} #slide0 h3 {margin: 0; padding: 0;} #slide0 h4 {margin: 0 0 0.5em; padding: 0;} #slide0 {margin-bottom: 3em;} h1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;} .extra {background: transparent !important;} div.extra, pre.extra, .example {font-size: 10pt; color: #333;} ul.extra a {font-weight: bold;} p.example {display: none;} #header {display: none;} #footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;} #footer h2, #controls {display: none;} /* The following rule keeps the layout stuff out of print. Remove at your own risk! */ .layout, .layout * {display: none !important;} \ No newline at end of file diff --git a/static/talks/fp-js/ui/default/s5-core.css b/static/talks/fp-js/ui/default/s5-core.css deleted file mode 100644 index 86444e0..0000000 --- a/static/talks/fp-js/ui/default/s5-core.css +++ /dev/null @@ -1,9 +0,0 @@ -/* 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 {display: none;} -.layout {display: block;} -.slide, .hideme, .incremental {visibility: hidden;} -#slide0 {visibility: visible;} diff --git a/static/talks/fp-js/ui/default/slides.css b/static/talks/fp-js/ui/default/slides.css deleted file mode 100644 index 0786d7d..0000000 --- a/static/talks/fp-js/ui/default/slides.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url(s5-core.css); /* required to make the slide show run at all */ -@import url(framing.css); /* sets basic placement and size of slide components */ -@import url(pretty.css); /* stuff that makes the slides look better than blah */ \ No newline at end of file diff --git a/static/talks/fp-js/ui/default/slides.js b/static/talks/fp-js/ui/default/slides.js deleted file mode 100644 index 38fe853..0000000 --- a/static/talks/fp-js/ui/default/slides.js +++ /dev/null @@ -1,553 +0,0 @@ -// S5 v1.1 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 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) 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 = '' + snum + '<\/span> ' + - '\/<\/span> ' + - '' + (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('*','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; - } - 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.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' + - '