├── previous_presentations
├── .gitignore
├── dag1
│ ├── README.md
│ ├── slides
│ │ ├── img
│ │ │ ├── functional-map.png
│ │ │ ├── iterative-map.png
│ │ │ └── plot-languages.png
│ │ ├── font
│ │ │ ├── 0AKsP294HTD-nvJgucYTaIbN6UDyHWBl620a-IRfuBk.woff
│ │ │ └── YDAoLskQQ5MOAgvHUQCcLRTHiN2BPBirwIkMLKUspj4.woff
│ │ └── remark-styling.css
│ ├── package.json
│ └── agenda.md
└── dag2
│ ├── big-case
│ ├── .gitignore
│ ├── baconchat.png
│ ├── browser
│ │ ├── config.js
│ │ └── lib
│ │ │ ├── webrtc.js
│ │ │ ├── helpers.js
│ │ │ └── chat.js
│ ├── static
│ │ ├── assets
│ │ │ └── bacon.png
│ │ └── index.html
│ ├── style
│ │ ├── colors.less
│ │ ├── main.less
│ │ ├── mixins.less
│ │ └── reset.less
│ ├── static-server.js
│ ├── lib
│ │ └── users.js
│ ├── package.json
│ ├── server.js
│ ├── README.md
│ └── gulpfile.js
│ ├── slides
│ ├── img
│ │ ├── batman.gif
│ │ ├── avengers2.gif
│ │ └── kevin_bacon.gif
│ ├── lib
│ │ ├── font
│ │ │ ├── league_gothic_license
│ │ │ ├── league_gothic-webfont.eot
│ │ │ ├── league_gothic-webfont.ttf
│ │ │ └── league_gothic-webfont.woff
│ │ ├── js
│ │ │ ├── html5shiv.js
│ │ │ ├── classList.js
│ │ │ └── head.min.js
│ │ └── css
│ │ │ └── zenburn.css
│ ├── plugin
│ │ ├── markdown
│ │ │ ├── example.md
│ │ │ └── example.html
│ │ ├── print-pdf
│ │ │ └── print-pdf.js
│ │ ├── postmessage
│ │ │ ├── postmessage.js
│ │ │ └── example.html
│ │ ├── remotes
│ │ │ └── remotes.js
│ │ ├── math
│ │ │ └── math.js
│ │ ├── notes-server
│ │ │ ├── client.js
│ │ │ ├── index.js
│ │ │ └── notes.html
│ │ └── notes
│ │ │ └── notes.js
│ └── css
│ │ ├── presentation.css
│ │ └── theme
│ │ ├── template
│ │ ├── settings.scss
│ │ ├── mixins.scss
│ │ └── theme.scss
│ │ ├── source
│ │ ├── night.scss
│ │ ├── serif.scss
│ │ ├── simple.scss
│ │ ├── sky.scss
│ │ ├── default.scss
│ │ ├── beige.scss
│ │ ├── moon.scss
│ │ └── solarized.scss
│ │ ├── README.md
│ │ ├── night.css
│ │ ├── serif.css
│ │ ├── simple.css
│ │ └── moon.css
│ ├── small-case
│ ├── recordapp.png
│ ├── package.json
│ ├── api.js
│ ├── readme.md
│ ├── style.css
│ ├── index.html
│ └── app.js
│ └── agenda.md
├── README.md
├── assets
├── github.png
├── font
│ ├── fontello.eot
│ ├── fontello.ttf
│ ├── fontello.woff
│ ├── LICENSE.txt
│ └── fontello.svg
├── logo.svg
└── component-tree.svg
├── index.html
├── _sass
├── _forms.scss
├── _next-nav.scss
├── globals
│ ├── _size.scss
│ ├── _colors.scss
│ ├── _mixins.scss
│ └── _reset.scss
├── _graph.scss
├── _columns.scss
├── main.scss
├── _content.scss
├── font
│ ├── _fontello.scss
│ └── _animation.scss
├── _header.scss
├── _window.scss
└── _syntax-highlighting.scss
├── scripts
├── components
│ ├── component.js
│ ├── editor.js
│ ├── run-result.js
│ └── codemirror-editor.js
├── entry.js
├── vendor
│ ├── codemirror-kimbie-dark.css
│ └── codemirror-base16-mocha-dark.css
└── playground-reporter.js
├── _includes
├── footer.html
└── head.html
├── _config.yml
├── notes.md
├── .gitignore
├── webpack.js
├── package.json
├── _workshop
├── 08-done.js
├── 03-2-higher-order.js
├── 02-1-applicative.js
├── 00-introduction.js
├── 03-1-factories.js
├── 02-6-point-free.js
├── 02-5-lodash.js
├── 01-2-arguments.js
├── 01-1-context.js
├── 01-3-prototype.js
├── 02-7-context.js
├── 03-3-functions-with-functions.js
├── 03-5-arity.js
├── 02-3-filter.js
├── 02-2-map.js
├── 03-4-fluent.js
├── 02-4-reduce.js
└── 04-2-functions-from-functions.js
├── gulpfile.js
├── css
└── vendor
│ └── base16-mocha-dark.css
└── _layouts
└── workshop.html
/previous_presentations/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [Workshop](http://bekk.github.io/functional-js/workshop/)
2 |
--------------------------------------------------------------------------------
/previous_presentations/dag1/README.md:
--------------------------------------------------------------------------------
1 | Open `1_intro.js` to get started.
2 |
--------------------------------------------------------------------------------
/assets/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/assets/github.png
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/.gitignore:
--------------------------------------------------------------------------------
1 | static/bundle.js
2 | static/main.css
3 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | ---
3 |
4 | Go to workshop
5 |
--------------------------------------------------------------------------------
/assets/font/fontello.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/assets/font/fontello.eot
--------------------------------------------------------------------------------
/assets/font/fontello.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/assets/font/fontello.ttf
--------------------------------------------------------------------------------
/assets/font/fontello.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/assets/font/fontello.woff
--------------------------------------------------------------------------------
/_sass/_forms.scss:
--------------------------------------------------------------------------------
1 | form { margin: 0; }
2 | // prevent ios zoom on focus
3 | input[type=text], textarea { font-size: 1rem; }
4 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/img/batman.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/previous_presentations/dag2/slides/img/batman.gif
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/baconchat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/previous_presentations/dag2/big-case/baconchat.png
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/img/avengers2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/previous_presentations/dag2/slides/img/avengers2.gif
--------------------------------------------------------------------------------
/previous_presentations/dag2/small-case/recordapp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/previous_presentations/dag2/small-case/recordapp.png
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/img/kevin_bacon.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/previous_presentations/dag2/slides/img/kevin_bacon.gif
--------------------------------------------------------------------------------
/previous_presentations/dag1/slides/img/functional-map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/previous_presentations/dag1/slides/img/functional-map.png
--------------------------------------------------------------------------------
/previous_presentations/dag1/slides/img/iterative-map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/previous_presentations/dag1/slides/img/iterative-map.png
--------------------------------------------------------------------------------
/previous_presentations/dag1/slides/img/plot-languages.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/previous_presentations/dag1/slides/img/plot-languages.png
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/lib/font/league_gothic_license:
--------------------------------------------------------------------------------
1 | SIL Open Font License (OFL)
2 | http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL
3 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/browser/config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | ws: 'ws://baconchat.herokuapp.com:80/',
3 | ajax: 'http://baconchat.herokuapp.com/users'
4 | };
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/static/assets/bacon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/previous_presentations/dag2/big-case/static/assets/bacon.png
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/style/colors.less:
--------------------------------------------------------------------------------
1 |
2 |
3 | @black: #1d1d1d;
4 | @white: #f1f1f1;
5 | @red: #fd5157;
6 | @background: #e5e5e5;
7 | @linkColorHover: lighten( @red, 20% );
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/lib/font/league_gothic-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/previous_presentations/dag2/slides/lib/font/league_gothic-webfont.eot
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/lib/font/league_gothic-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/previous_presentations/dag2/slides/lib/font/league_gothic-webfont.ttf
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/lib/font/league_gothic-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/previous_presentations/dag2/slides/lib/font/league_gothic-webfont.woff
--------------------------------------------------------------------------------
/_sass/_next-nav.scss:
--------------------------------------------------------------------------------
1 | @import "globals/mixins";
2 |
3 | .docs-prevnext {
4 | margin: 20px 0;
5 | @include clearfix;
6 | }
7 | .docs-prev {
8 | float: left;
9 | }
10 | .docs-next {
11 | float: right;
12 | }
--------------------------------------------------------------------------------
/scripts/components/component.js:
--------------------------------------------------------------------------------
1 | var omniscient = require('omniscient');
2 |
3 | const jsx = true;
4 | const component = omniscient.withDefaults({ jsx });
5 |
6 | // component.debug();
7 |
8 | export default component;
9 |
--------------------------------------------------------------------------------
/previous_presentations/dag1/slides/font/0AKsP294HTD-nvJgucYTaIbN6UDyHWBl620a-IRfuBk.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/previous_presentations/dag1/slides/font/0AKsP294HTD-nvJgucYTaIbN6UDyHWBl620a-IRfuBk.woff
--------------------------------------------------------------------------------
/previous_presentations/dag1/slides/font/YDAoLskQQ5MOAgvHUQCcLRTHiN2BPBirwIkMLKUspj4.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bekk/functional-js/HEAD/previous_presentations/dag1/slides/font/YDAoLskQQ5MOAgvHUQCcLRTHiN2BPBirwIkMLKUspj4.woff
--------------------------------------------------------------------------------
/_sass/globals/_size.scss:
--------------------------------------------------------------------------------
1 | $column-sidebar-width: 31%;
2 | $column-sidebar-margin: 1rem;
3 |
4 | $first-breakpoint-width: 650px;
5 | $remove-graphics-width: 870px;
6 | $minify-header-width: 630px;
7 | $min-width: 350px;
8 |
9 | $header-height: 0px;
10 |
--------------------------------------------------------------------------------
/_includes/footer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/lib/js/html5shiv.js:
--------------------------------------------------------------------------------
1 | document.createElement('header');
2 | document.createElement('nav');
3 | document.createElement('section');
4 | document.createElement('article');
5 | document.createElement('aside');
6 | document.createElement('footer');
7 | document.createElement('hgroup');
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/static-server.js:
--------------------------------------------------------------------------------
1 | var http = require('http'),
2 | ecstatic = require('ecstatic'),
3 |
4 | port = process.env.PORT || 3000,
5 | staticDir = __dirname + '/static';
6 |
7 | http.createServer(ecstatic({
8 | root: staticDir
9 | })).listen(port);
10 | console.log('Started server on port', port);
--------------------------------------------------------------------------------
/previous_presentations/dag2/small-case/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "baconjs": "^0.7.22",
4 | "beefy": "^2.1.1",
5 | "ecstatic": "^0.5.4",
6 | "jquery": "^2.1.1",
7 | "lodash": "^2.4.1",
8 | "q": "^1.0.1"
9 | },
10 | "scripts": {
11 | "start": "beefy app.js --index=index.html --open --live"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/plugin/markdown/example.md:
--------------------------------------------------------------------------------
1 | # Markdown Demo
2 |
3 |
4 |
5 | ## External 1.1
6 |
7 | Content 1.1
8 |
9 | Note: This will only appear in the speaker notes window.
10 |
11 |
12 | ## External 1.2
13 |
14 | Content 1.2
15 |
16 |
17 |
18 | ## External 2
19 |
20 | Content 2.1
21 |
22 |
23 |
24 | ## External 3.1
25 |
26 | Content 3.1
27 |
28 |
29 | ## External 3.2
30 |
31 | Content 3.2
32 |
--------------------------------------------------------------------------------
/assets/font/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Font license info
2 |
3 |
4 | ## Font Awesome
5 |
6 | Copyright (C) 2012 by Dave Gandy
7 |
8 | Author: Dave Gandy
9 | License: SIL ()
10 | Homepage: http://fortawesome.github.com/Font-Awesome/
11 |
12 |
13 | ## Fontelico
14 |
15 | Copyright (C) 2012 by Fontello project
16 |
17 | Author: Crowdsourced, for Fontello project
18 | License: SIL (http://scripts.sil.org/OFL)
19 | Homepage: http://fontello.com
20 |
21 |
22 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | # Site settings
2 | title: Functional JavaScript Workshop
3 | description: Workshop for teaching Functional Programming with JavaScript
4 | baseurl: "/functional-js" # the subpath of your site, e.g. /blog/
5 | url: "http://bekkopen.github.io/" # the base hostname & protocol for your site
6 |
7 | version: 3.1.0
8 |
9 | # Build settings
10 | markdown: kramdown
11 |
12 | exclude:
13 | - node_modules
14 |
15 | collections:
16 | workshop:
17 | output: true
18 | output_ext: html
19 | collection: workshop
20 | permalink: /workshop/:path/
21 |
22 | permalink: pretty
23 |
24 | kramdown:
25 | input: GFM
26 | hard_wrap: false
27 |
--------------------------------------------------------------------------------
/notes.md:
--------------------------------------------------------------------------------
1 | Notes:
2 |
3 | - Normaliser hva som skal endres (ikke måtte endre på testene feks)
4 | - Mer visuell kobling mellom test og test-resultat
5 | - Droppe prototype-oppgavene
6 | - Bedre beskrivelse på testene med multiplikasjon
7 | - map+filter-oppgave mangler skikkelig "it", samt har en skriveleif "ilter" (mangler f)
8 | - Presisere hvilken filter-funksjon som skal brukes (ikke Array.prototype.filter.call)
9 | - Paa reduce-eksempel, burde vi skrive ut tilsvarende for-lokke?
10 | - Beskrive fluent bedre, spesielt mtp function decorators
11 | - Bedre initial values på ting som skal lages (ikke tom funksjon for ting som skal bli variabler, feks partialRight)
12 |
--------------------------------------------------------------------------------
/scripts/components/editor.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import omniscient from 'omniscient';
3 |
4 | import component from './component';
5 | import CodeMirrorEditor from './codemirror-editor';
6 | import RunCode from './run-code';
7 |
8 | export default component(function Editor ({ source }, { isLarge, timers }) {
9 |
10 | return
11 |
12 |
16 |
17 |
18 |
22 |
23 |
;
24 | });
25 |
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | _site
6 | .sass-cache
7 |
8 |
9 | .DS_Store
10 |
11 | # Runtime data
12 | pids
13 | *.pid
14 | *.seed
15 |
16 | # Directory for instrumented libs generated by jscoverage/JSCover
17 | lib-cov
18 |
19 | # Coverage directory used by tools like istanbul
20 | coverage
21 |
22 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
23 | .grunt
24 |
25 | # Compiled binary addons (http://nodejs.org/api/addons.html)
26 | build/Release
27 |
28 | # Dependency directory
29 | # Commenting this out is preferred by some people, see
30 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
31 | node_modules
32 |
33 | # Users Environment Variables
34 | .lock-wscript
35 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/style/main.less:
--------------------------------------------------------------------------------
1 | @import "reset.less";
2 | @import "colors.less";
3 | @import "mixins.less";
4 |
5 | * {
6 | -webkit-box-sizing: border-box;
7 | -moz-box-sizing: border-box;
8 | box-sizing: border-box;
9 | }
10 |
11 | html, body {
12 | height: 100%;
13 | overflow: hidden;
14 | }
15 |
16 | body {
17 | background: @background;
18 | font-family: Helvetica, Arial;
19 | }
20 |
21 |
22 | a:link, a:visited {
23 | color: @red;
24 | }
25 |
26 | a:hover, a:active {
27 | color: @linkColorHover;
28 | }
29 |
30 | .helper-box {
31 | height: 1px;
32 | width: 1px;
33 | display: block;
34 | margin: 0;
35 | padding: 0;
36 | overflow: hidden;
37 |
38 | video {
39 | height: @inputSize;
40 | }
41 | }
42 |
43 | @import "chat.less";
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/lib/users.js:
--------------------------------------------------------------------------------
1 | var remove = require('lodash-node/modern/arrays/remove');
2 |
3 | var onlineUsers = [];
4 |
5 | module.exports = {
6 | route: function (req, res) {
7 | if (req.method !== "GET" || !/^\/users$/i.test(req.url)) {
8 | return false;
9 | }
10 |
11 | var users = JSON.stringify(onlineUsers);
12 | res.writeHead(200, {
13 | 'Content-Length': users.length,
14 | 'Content-Type': 'application/json'
15 | });
16 | res.end(users);
17 | return true;
18 | },
19 |
20 | add: function (user) {
21 | return onlineUsers.push({
22 | username: user
23 | });
24 | },
25 |
26 | remove: function (username) {
27 | remove(onlineUsers, function (user) {
28 | return user.username === username;
29 | });
30 | }
31 | }
--------------------------------------------------------------------------------
/webpack.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 |
3 | module.exports = function (options) {
4 | return {
5 | plugins: options.watch ? [] : [],
6 | watch: options.watch,
7 | module: {
8 | loaders: [
9 | {
10 | test: /\.js$/,
11 | exclude: /node_modules/,
12 | loaders: [
13 | // 'react-hot',
14 | '6to5-loader'
15 | //'6to5-loader?experimental&optional=selfContained' // http://6to5.org/docs/usage/experimental/
16 | ]
17 | },
18 | {
19 | test: /\.less$/,
20 | loaders: [
21 | "style-loader",
22 | "css-loader",
23 | "autoprefixer-loader?browsers=last 2 version",
24 | "less-loader?strictMath&cleancss"
25 | ]
26 | }
27 | ]
28 | }
29 | };
30 | };
31 |
--------------------------------------------------------------------------------
/scripts/entry.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import immstruct from 'immstruct';
3 |
4 | import Editor from './components/editor';
5 |
6 | const runnables = document.querySelectorAll('.editor');
7 | for (let i = 0; i < runnables.length; i++) {
8 | const runnable = runnables[i];
9 |
10 | const textarea = runnable.querySelector('textarea');
11 | const source = textarea.value;
12 | runnable.removeChild(textarea);
13 |
14 | const isLarge = runnable.dataset.isLarge;
15 | createEditorRenderLoop(runnable, source, isLarge);
16 | }
17 |
18 | function createEditorRenderLoop (container, source, isLarge) {
19 |
20 | const data = immstruct({ source });
21 | const timers = { intervals: [], timeouts: [] };
22 | const render = () =>
23 | React.render(
24 | ,
27 | container);
28 |
29 | data.on('swap', () => render());
30 | render();
31 | }
32 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/css/presentation.css:
--------------------------------------------------------------------------------
1 | /* Data flow example */
2 | .slides .dataflow-example {
3 | background: url("../img/data_flow.svg") left top no-repeat;
4 | position: relative;
5 | width: 900px;
6 | height: 364px;
7 | margin: 0 auto;
8 | }
9 |
10 | .node,
11 | .node-result {
12 | border: 0;
13 | background: none;
14 | color: #fff;
15 | position: absolute;
16 | font-size: 2em;
17 | width: 100px;
18 | outline: 0;
19 | text-align: center;
20 | }
21 |
22 | .node-a {
23 | top: 50px;
24 | left: 25px;
25 | }
26 |
27 | .node-b {
28 | bottom: 36px;
29 | left: 25px;
30 | }
31 |
32 | .node-d {
33 | top: 30px;
34 | left: 385px;
35 | }
36 |
37 | .node-c {
38 | bottom: 96px;
39 | left: 385px;
40 | }
41 |
42 | .node-result {
43 | top: calc(50% - 40px);
44 | right: 15px;
45 | }
46 |
47 | .reveal h2.black {
48 | color: #1b1b1b;
49 | }
50 |
51 | .reveal code {
52 | display: inline-block;
53 | background: #666;
54 | padding: 5px 10px;
55 | border-radius: 2px;
56 | }
--------------------------------------------------------------------------------
/_sass/_graph.scss:
--------------------------------------------------------------------------------
1 | @import "./globals/colors";
2 |
3 | .graphNode--blue {
4 | fill: $color-topNode;
5 |
6 | -webkit-animation-name: 'pulse_animation';
7 | -webkit-animation-duration: 2500ms;
8 | -webkit-animation-iteration-count: infinite;
9 | -webkit-animation-timing-function: linear;
10 | -webkit-transform-origin:70% 70%;
11 | }
12 |
13 |
14 | .graphEdge--fade,
15 | .graphNode--fade {
16 | -webkit-animation-name: 'fade_animation';
17 | -webkit-animation-duration: 5000ms;
18 | -webkit-animation-iteration-count: infinite;
19 | -webkit-animation-timing-function: linear;
20 | }
21 |
22 | @-webkit-keyframes pulse_animation {
23 | 0% { -webkit-transform: scale(1); }
24 | 50% { -webkit-transform: scale(.95); }
25 | 100% { -webkit-transform: scale(1); }
26 | }
27 |
28 | @-webkit-keyframes fade_animation {
29 | 0% { opacity: 1; }
30 | 20% { opacity: .9; }
31 | 30% { opacity: .2; }
32 | 50% { opacity: .2; }
33 | 60% { opacity: .2; }
34 | 70% { opacity: .2; }
35 | 100% { opacity: 1; }
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/previous_presentations/dag1/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "scripts": {
3 | "1": "tape 1_intro.js | tap-bail | tap-spec",
4 | "2": "tape 2_applicative.js | tap-bail | tap-spec",
5 | "3": "tape 3_functions.js | tap-bail | tap-spec",
6 | "4": "tape 4_partially.js | tap-bail | tap-spec",
7 | "5": "tape 5_curry_compose.js | tap-bail | tap-spec",
8 | "6": "tape 6_immutability.js | tap-bail | tap-spec",
9 | "7": "tape 7_collections.js | tap-bail | tap-spec",
10 | "test": "tape 1_intro.js 2_applicative.js 3_functions.js 4_partially.js 5_curry_compose.js 6_immutability.js 7_collections.js | tap-bail | tap-spec",
11 | "solutions": "tape solutions/1_intro.js solutions/2_applicative.js solutions/3_functions.js solutions/4_partially.js solutions/5_curry_compose.js solutions/6_immutability.js solutions/7_collections.js | tap-bail | tap-spec"
12 | },
13 | "dependencies": {
14 | "immutable": "^2.0.16",
15 | "lodash": "^2.4.1",
16 | "tap-bail": "0.0.0",
17 | "tap-spec": "^0.2.1",
18 | "tape": "^2.14.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bacon-chat",
3 | "version": "2.0.0",
4 | "description": "",
5 | "main": "server.js",
6 | "dependencies": {
7 | "baconjs": "^0.7.22",
8 | "ecstatic": "^0.5.4",
9 | "humanize": "0.0.9",
10 | "jquery": "^2.1.1",
11 | "lodash-node": "^2.4.1",
12 | "socket.io": "^1.0.6",
13 | "socket.io-client": "^1.0.6"
14 | },
15 | "browserify": {
16 | "transform": [
17 | "es6-arrow-function"
18 | ]
19 | },
20 | "devDependencies": {
21 | "browserify": "^5.10.1",
22 | "es6-arrow-function": "^0.3.1",
23 | "gulp": "^3.8.7",
24 | "gulp-autoprefixer": "0.0.9",
25 | "gulp-less": "^1.3.5",
26 | "gulp-notify": "^1.5.0",
27 | "vinyl-source-stream": "^0.1.1",
28 | "watchify": "^1.0.2"
29 | },
30 | "scripts": {
31 | "build": "gulp",
32 | "watch": "gulp watch",
33 | "serve": "node static-server.js",
34 | "test": "echo \"Error: no test specified\" && exit 1"
35 | },
36 | "author": "",
37 | "license": "ISC"
38 | }
39 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/css/theme/template/settings.scss:
--------------------------------------------------------------------------------
1 | // Base settings for all themes that can optionally be
2 | // overridden by the super-theme
3 |
4 | // Background of the presentation
5 | $backgroundColor: #2b2b2b;
6 |
7 | // Primary/body text
8 | $mainFont: 'Lato', sans-serif;
9 | $mainFontSize: 36px;
10 | $mainColor: #eee;
11 |
12 | // Headings
13 | $headingMargin: 0 0 20px 0;
14 | $headingFont: 'League Gothic', Impact, sans-serif;
15 | $headingColor: #eee;
16 | $headingLineHeight: 0.9em;
17 | $headingLetterSpacing: 0.02em;
18 | $headingTextTransform: uppercase;
19 | $headingTextShadow: 0px 0px 6px rgba(0,0,0,0.2);
20 | $heading1TextShadow: $headingTextShadow;
21 |
22 | // Links and actions
23 | $linkColor: #13DAEC;
24 | $linkColorHover: lighten( $linkColor, 20% );
25 |
26 | // Text selection
27 | $selectionBackgroundColor: #FF5E99;
28 | $selectionColor: #fff;
29 |
30 | // Generates the presentation background, can be overridden
31 | // to return a background image or gradient
32 | @mixin bodyBackground() {
33 | background: $backgroundColor;
34 | }
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/plugin/print-pdf/print-pdf.js:
--------------------------------------------------------------------------------
1 | /**
2 | * phantomjs script for printing presentations to PDF.
3 | *
4 | * Example:
5 | * phantomjs print-pdf.js "http://lab.hakim.se/reveal-js?print-pdf" reveal-demo.pdf
6 | *
7 | * By Manuel Bieh (https://github.com/manuelbieh)
8 | */
9 |
10 | // html2pdf.js
11 | var page = new WebPage();
12 | var system = require( 'system' );
13 |
14 | page.viewportSize = {
15 | width: 1024,
16 | height: 768
17 | };
18 |
19 | page.paperSize = {
20 | format: 'letter',
21 | orientation: 'landscape',
22 | margin: {
23 | left: '0',
24 | right: '0',
25 | top: '0',
26 | bottom: '0'
27 | }
28 | };
29 |
30 | var revealFile = system.args[1] || 'index.html?print-pdf';
31 | var slideFile = system.args[2] || 'slides.pdf';
32 |
33 | if( slideFile.match( /\.pdf$/gi ) === null ) {
34 | slideFile += '.pdf';
35 | }
36 |
37 | console.log( 'Printing PDF...' );
38 |
39 | page.open( revealFile, function( status ) {
40 | console.log( 'Printed succesfully' );
41 | page.render( slideFile );
42 | phantom.exit();
43 | } );
44 |
45 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "omniscientjs.github.io",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "build": "gulp",
8 | "watch": "gulp watch"
9 | },
10 | "engines": {
11 | "node": "0.10.x"
12 | },
13 | "author": "",
14 | "license": "mit",
15 | "dependencies": {
16 | "6to5": "^3.3.2",
17 | "6to5-core": "^3.6.5",
18 | "6to5-loader": "^3.0.0",
19 | "autoprefixer-loader": "^1.1.0",
20 | "chai": "^2.0.0",
21 | "codemirror": "^5.0.0",
22 | "css-loader": "^0.9.1",
23 | "gulp-if": "^1.2.5",
24 | "immstruct": "^1.4.0",
25 | "immutable": "^3.6.2",
26 | "less": "^2.4.0",
27 | "less-loader": "^2.0.0",
28 | "lodash": "^2.0.0",
29 | "mocha": "^2.1.0",
30 | "omniscient": "^3.1.0",
31 | "react": "^0.12.2",
32 | "style-loader": "^0.8.3",
33 | "vinyl-named": "^1.1.0",
34 | "webpack": "^1.5.3"
35 | },
36 | "devDependencies": {
37 | "gulp": "^3.8.11",
38 | "gulp-autoprefixer": "^2.1.0",
39 | "gulp-sass": "^1.3.3",
40 | "gulp-webpack": "^1.2.0"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/_includes/head.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/_sass/globals/_colors.scss:
--------------------------------------------------------------------------------
1 | // Color palette
2 | $color-blue-darkest: #2C3E50;
3 | $color-blue-dark: #2980B9;
4 | $color-blue-normal: #3498DB;
5 | $color-blue-light: #0EC2DB;
6 | $color-organge-normal: #E74C3C;
7 |
8 | $color-omniscient-blue: #0098C6;
9 |
10 | $color-white-bg: #fafafa;
11 | $color-darkGray-background: $color-white-bg;
12 | $color-white-fontColor: #2d2d2d;
13 |
14 | $color-header-border: $color-blue-light;
15 | $color-header-background: $color-omniscient-blue;
16 | $color-header-background--bottom: lighten($color-blue-darkest, 10%);
17 | $color-header-background--small: $color-omniscient-blue;
18 |
19 | $color-header-linkColor: $color-white-bg;
20 |
21 |
22 | // Graph colors:
23 |
24 | $color-topNode: $color-blue-darkest;
25 |
26 | $color-infoBoxes: $color-white-bg;
27 |
28 | $color-leftNav: $color-blue-darkest;
29 | $color-leftNav-header: $color-blue-darkest;
30 |
31 | $color-table-white: #fff;
32 | $color-table-zebra: lighten($color-organge-normal, 40%);
33 |
34 | // Links
35 |
36 | $color-links: $color-blue-normal;
37 | $color-links--hover: darken($color-links, 15%);
38 | $color-links--active: darken($color-links, 25%);
39 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/server.js:
--------------------------------------------------------------------------------
1 | var http = require('http'),
2 | ecstatic = require('ecstatic'),
3 | users = require('./lib/users'),
4 |
5 | port = process.env.PORT || 5001,
6 | staticDir = __dirname + '/static',
7 |
8 | app = http.createServer(serverHandler),
9 | io = require('socket.io').listen(app);
10 |
11 | app.listen(port);
12 | console.log('Started server on port', port);
13 |
14 | function serverHandler (req, res) {
15 | if (users.route(req, res)) {
16 | return;
17 | }
18 | return ecstatic({
19 | root: staticDir
20 | })(req, res);
21 | };
22 |
23 | io.sockets.on('connection', function (socket) {
24 | var username = null;
25 |
26 | socket.on('message', function (data) {
27 | if (!username) return;
28 | socket.broadcast.emit('message', data);
29 | });
30 |
31 | socket.on('join', function (data) {
32 | users.add(data);
33 | username = data;
34 | socket.broadcast.emit('join', data);
35 | });
36 |
37 | socket.on('disconnect', function() {
38 | if (!username) return;
39 | users.remove(username);
40 | socket.broadcast.emit('part', username);
41 | });
42 | });
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/css/theme/source/night.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Black theme for reveal.js.
3 | *
4 | * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
5 | */
6 |
7 |
8 | // Default mixins and settings -----------------
9 | @import "../template/mixins";
10 | @import "../template/settings";
11 | // ---------------------------------------------
12 |
13 |
14 | // Include theme-specific fonts
15 | @import url(https://fonts.googleapis.com/css?family=Montserrat:700);
16 | @import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic,700italic);
17 |
18 |
19 | // Override theme settings (see ../template/settings.scss)
20 | $backgroundColor: #111;
21 |
22 | $mainFont: 'Open Sans', sans-serif;
23 | $linkColor: #e7ad52;
24 | $linkColorHover: lighten( $linkColor, 20% );
25 | $headingFont: 'Montserrat', Impact, sans-serif;
26 | $headingTextShadow: none;
27 | $headingLetterSpacing: -0.03em;
28 | $headingTextTransform: none;
29 | $selectionBackgroundColor: #e7ad52;
30 | $mainFontSize: 30px;
31 |
32 |
33 | // Theme template ------------------------------
34 | @import "../template/theme";
35 | // ---------------------------------------------
--------------------------------------------------------------------------------
/_sass/_columns.scss:
--------------------------------------------------------------------------------
1 | @import "globals/size";
2 |
3 | .column {
4 | margin-left: calc(#{$column-sidebar-width} + #{$column-sidebar-margin + 1});
5 | }
6 |
7 | .nav-left {
8 | float: left;
9 | width: $column-sidebar-width;
10 | margin-right: $column-sidebar-margin;
11 |
12 | font-size: 0.9rem;
13 | }
14 | .nav-left ul,
15 | .nav-left ol {
16 | padding: 0;
17 | padding-left: 10px;
18 | list-style-type: none;
19 | }
20 | .nav-left h3 {
21 | margin: 0;
22 | }
23 | .nav-left > :not(:first-child) {
24 | margin-top: 30px;
25 | }
26 | .nav-left h3 a {
27 | font-size: 1.2rem;
28 | font-weight: 100;
29 | color: $color-leftNav-header;
30 |
31 | text-transform: uppercase;
32 | display: block;
33 | }
34 |
35 | .nav-left {
36 | ul, ol {
37 | a {
38 | display: block;
39 | padding: 5px 0;
40 |
41 | color: $color-leftNav;
42 |
43 | transition: all 300ms;
44 |
45 | &:hover {
46 | color: lighten($color-leftNav, 40%);
47 | }
48 | }
49 | }
50 | }
51 |
52 | @media (max-width: $first-breakpoint-width) {
53 | .nav-left {
54 | display: none;
55 | }
56 | .column {
57 | margin-left: 0;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/plugin/postmessage/postmessage.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | simple postmessage plugin
4 |
5 | Useful when a reveal slideshow is inside an iframe.
6 | It allows to call reveal methods from outside.
7 |
8 | Example:
9 | var reveal = window.frames[0];
10 |
11 | // Reveal.prev();
12 | reveal.postMessage(JSON.stringify({method: 'prev', args: []}), '*');
13 | // Reveal.next();
14 | reveal.postMessage(JSON.stringify({method: 'next', args: []}), '*');
15 | // Reveal.slide(2, 2);
16 | reveal.postMessage(JSON.stringify({method: 'slide', args: [2,2]}), '*');
17 |
18 | Add to the slideshow:
19 |
20 | dependencies: [
21 | ...
22 | { src: 'plugin/postmessage/postmessage.js', async: true, condition: function() { return !!document.body.classList; } }
23 | ]
24 |
25 | */
26 |
27 | (function (){
28 |
29 | window.addEventListener( "message", function ( event ) {
30 | var data = JSON.parse( event.data ),
31 | method = data.method,
32 | args = data.args;
33 |
34 | if( typeof Reveal[method] === 'function' ) {
35 | Reveal[method].apply( Reveal, data.args );
36 | }
37 | }, false);
38 |
39 | }());
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/css/theme/source/serif.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * A simple theme for reveal.js presentations, similar
3 | * to the default theme. The accent color is brown.
4 | *
5 | * This theme is Copyright (C) 2012-2013 Owen Versteeg, http://owenversteeg.com - it is MIT licensed.
6 | */
7 |
8 |
9 | // Default mixins and settings -----------------
10 | @import "../template/mixins";
11 | @import "../template/settings";
12 | // ---------------------------------------------
13 |
14 |
15 |
16 | // Override theme settings (see ../template/settings.scss)
17 | $mainFont: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
18 | $mainColor: #000;
19 | $headingFont: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
20 | $headingColor: #383D3D;
21 | $headingTextShadow: none;
22 | $headingTextTransform: none;
23 | $backgroundColor: #F0F1EB;
24 | $linkColor: #51483D;
25 | $linkColorHover: lighten( $linkColor, 20% );
26 | $selectionBackgroundColor: #26351C;
27 |
28 | .reveal a:not(.image) {
29 | line-height: 1.3em;
30 | }
31 |
32 |
33 | // Theme template ------------------------------
34 | @import "../template/theme";
35 | // ---------------------------------------------
36 |
--------------------------------------------------------------------------------
/_workshop/08-done.js:
--------------------------------------------------------------------------------
1 | ---
2 | layout: workshop
3 | collection: workshop
4 | title: Done
5 | section: 7
6 | prev: 07-collections
7 | name: 08-done
8 | slides:
9 | info: |
10 | We have now been on a ride through some of the interesting parts of
11 | functional programming. You have seen some code that doesn't look much like
12 | the JavaScript we normally write. We have also seen that the same code has
13 | interesting properties, such as less focus on state and mutability.
14 | Hopefully you have learned something along the way.
15 |
16 | To wrap up what we have seen today -- basically, functional programming
17 | achieve reuse at a coarser-grained level than object-oriented programming,
18 | extracting common machinery with parameterized behavior. Most applications
19 | do things with lists of elements, so a functional approach is to build reuse
20 | mechanisms around the idea of lists plus contextualized, portable code.
21 |
22 | Btw, want to learn more?
23 |
24 | [https://leanpub.com/javascript-allonge/read](https://leanpub.com/javascript-allonge/read)
25 | and
26 | [http://shop.oreilly.com/product/0636920028857.do](http://shop.oreilly.com/product/0636920028857.do)
27 | ---
28 | // THE END!
29 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/plugin/postmessage/example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/_workshop/03-2-higher-order.js:
--------------------------------------------------------------------------------
1 | ---
2 | layout: workshop
3 | collection: workshop
4 | title: Higher order functions
5 | section: 3
6 | prev: 03-1-factories
7 | name: 03-2-higher-order
8 | next: 03-3-functions-with-functions
9 | slides:
10 | info: |
11 | Sometimes we want to take a function as an argument. Functions that take
12 | other functions as arguments are called higher order functions.
13 | ---
14 | // PROBLEM: Create a once factory that receives a function that
15 | // will at most be called once. If already run, return the result
16 | // of the first invocation on every succeeding invocation.
17 |
18 | function once(fn) {
19 | }
20 |
21 | describe('once', function() {
22 | var win = once(function(name) {
23 | return name + ' is winning';
24 | });
25 |
26 | it('should declare a winner the first time', function() {
27 | var result = win('kim');
28 | expect(result).to.equal('kim is winning');
29 | });
30 |
31 | it('should not change winner if invoked multiple times', function() {
32 | var result = win('stian');
33 | expect(result).to.equal('kim is winning');
34 | });
35 |
36 | // And we have now decorated a function, i.e. wrapped an existing functions
37 | // with new functionality.
38 | });
39 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/small-case/api.js:
--------------------------------------------------------------------------------
1 | var Q = require('q');
2 |
3 | var random = function (min, max) {
4 | return (Math.random() * (max - min)) + min;
5 | };
6 |
7 | var recordCollection = [
8 | {
9 | "album": "Crystal Logic",
10 | "artist": "Manilla Road",
11 | "year": "1983",
12 | "genre": "Epic Heavy/Power Metal"
13 | },
14 | {
15 | "album": "Funeral Circle",
16 | "artist": "Funeral Circle",
17 | "year": "2013",
18 | "genre": "Doom Metal"
19 | }
20 | ];
21 |
22 | module.exports.records = function () {
23 | var deferred = Q.defer();
24 |
25 | setTimeout(function () {
26 | if(Math.random() < 0.15) {
27 | deferred.reject(new Error('Whops, there was a communication problem'));
28 | } else {
29 | deferred.resolve(recordCollection);
30 | }
31 | }, random(100, 1000));
32 |
33 | return deferred.promise;
34 | };
35 |
36 | module.exports.newRecord = function (record) {
37 | var deferred = Q.defer();
38 |
39 | setTimeout(function () {
40 | if(Math.random() < 0.15) {
41 | deferred.reject(new Error('Whops, there was a communication problem'));
42 | } else {
43 | deferred.resolve(record);
44 | }
45 | }, random(100, 1000));
46 |
47 | return deferred.promise;
48 | }
--------------------------------------------------------------------------------
/_sass/main.scss:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 | @import "globals/reset";
4 | @import "globals/colors";
5 | @import "globals/size";
6 |
7 | @import url(http://fonts.googleapis.com/css?family=Khula:400,700,600,300);
8 |
9 | body {
10 | font-family: 'Khula', sans-serif;
11 | background: $color-darkGray-background;
12 | color: $color-white-fontColor;
13 | padding: 0 5%;
14 | }
15 |
16 | * {
17 | box-sizing: border-box;
18 | }
19 |
20 | @media (max-width: $first-breakpoint-width) {
21 | .link--github {
22 | display: none;
23 | }
24 | }
25 |
26 | .anchor-link {
27 | display: block;
28 | position: relative;
29 | top: -$header-height;
30 | visibility: hidden;
31 | }
32 |
33 | a:link, a:visited {
34 | color: $color-links;
35 | text-decoration: none;
36 | }
37 |
38 | a:hover {
39 | color: $color-links--hover;
40 | }
41 |
42 | a:active {
43 | color: $color-links--active;
44 | }
45 |
46 |
47 | ul, ol {
48 | list-style-position: inside;
49 | padding-left: 20px;
50 | }
51 |
52 | .info {
53 | max-width: 65%;
54 | }
55 |
56 | @import "header";
57 | @import "graph";
58 | @import "window";
59 | @import "content";
60 | @import "columns";
61 | @import "next-nav";
62 | @import "forms";
63 |
64 | // Fonts
65 | @import "font/animation";
66 | @import "font/fontello";
67 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/browser/lib/webrtc.js:
--------------------------------------------------------------------------------
1 | var Bacon = require('baconjs');
2 | const INTERVAL_TIME_MS = 1000;
3 |
4 | navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
5 |
6 | var error = function () {
7 | console.log("error getting camera");
8 | };
9 |
10 | module.exports = function (options) {
11 | var bus;
12 | var elVideo = options.elVideo;
13 | var elSnapshot = options.elSnapshot;
14 | var intervalTime = options.intervalTime || INTERVAL_TIME_MS;
15 |
16 | if (!elVideo || !elSnapshot) throw new Error('Invalid arguments given');
17 |
18 | bus = new Bacon.Bus;
19 | navigator.getUserMedia({ video: true}, function(stream) {
20 | elVideo.src = window.URL.createObjectURL(stream);
21 |
22 | setInterval(function () {
23 | bus.push(getData(elVideo, elSnapshot));
24 | }, intervalTime);
25 | }, error);
26 |
27 | return bus;
28 | };
29 |
30 | function getData (elVideo, elSnapshot) {
31 | var c;
32 |
33 | elSnapshot.width = elVideo.clientWidth;
34 | elSnapshot.height = elVideo.clientHeight;
35 |
36 | c = elSnapshot.getContext("2d");
37 | c.drawImage(elVideo, 0, 0, elSnapshot.width, elSnapshot.height);
38 | return elSnapshot.toDataURL("image/png");
39 | }
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/README.md:
--------------------------------------------------------------------------------
1 | # Case: Making Bacon Chat with WebRTC integration
2 |
3 | Start the project by cloning the repo, change directory to `big-case`,
4 | and install dependencies:
5 |
6 | ```
7 | npm install
8 | ```
9 |
10 |
11 | ## Running project
12 |
13 | You'll have 3 commands to help you out:
14 |
15 |
16 | ### Starting a static file server at http://localhost:3000
17 | ```
18 | npm run serve
19 | ```
20 |
21 |
22 | ### Building all less and JS
23 | ```
24 | npm run build
25 | ```
26 |
27 |
28 | ### Building all less and JS on file change (watching)
29 | ```
30 | npm run watch
31 | ```
32 |
33 |
34 | ## Working on the case.
35 |
36 | The implementation should be done in [/browser/main.js](./browser/main.js).
37 |
38 | There are some helper modules found in [/browser/lib](./browser/lib):
39 |
40 | - [/browser/lib/chat.js](./browser/lib/chat.js): EventEmitter handling all Chat communication
41 | - [/browser/lib/webrtc.js](./browser/lib/webrtc.js): Converts WebRTC to an FRP EventSource
42 | - [/browser/lib/helpers.js](./browser/lib/helpers.js): Collection of helpers (regexes, templates etc)
43 |
44 |
45 |
46 | ### Result
47 |
48 | We are building a chat for talking about bacon in any size of form:
49 |
50 | 
51 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/style/mixins.less:
--------------------------------------------------------------------------------
1 | .clearfix() {
2 | *zoom: 1;
3 |
4 | &:before,
5 | &:after {
6 | content: " ";
7 | display: table;
8 | }
9 |
10 | &:after {
11 | clear: both;
12 | }
13 | }
14 |
15 | .height-minus (@height: 100%, @margin: 40px) {
16 | height: -moz-calc(@height ~"-" @margin);
17 | max-height: -moz-calc(@height ~"-" @margin);
18 | height: -webkit-calc(@height ~"-" @margin);
19 | max-height: -webkit-calc(@height ~"-" @margin);
20 | height: calc(@height ~"-" @margin);
21 | max-height: calc(@height ~"-" @margin);
22 | }
23 |
24 | .width-minus (@width 100%, @margin: 40px) {
25 | width: -moz-calc(@width ~"-" @margin);
26 | width: -webkit-calc(@width ~"-" @margin);
27 | width: calc(@width ~"-" @margin);
28 | max-width: -moz-calc(@width ~"-" @margin);
29 | max-width: -webkit-calc(@width ~"-" @margin);
30 | max-width: calc(@width ~"-" @margin);
31 | }
32 |
33 | .drop-shadow(@x-axis: 0, @y-axis: 1px, @blur: 2px, @alpha: 0.5) {
34 | -webkit-box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha);
35 | -moz-box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha);
36 | box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha);
37 | }
38 | .rounded(@radius: 2px) {
39 | -webkit-border-radius: @radius;
40 | -moz-border-radius: @radius;
41 | border-radius: @radius;
42 | }
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/css/theme/source/simple.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * A simple theme for reveal.js presentations, similar
3 | * to the default theme. The accent color is darkblue.
4 | *
5 | * This theme is Copyright (C) 2012 Owen Versteeg, https://github.com/StereotypicalApps. It is MIT licensed.
6 | * reveal.js is Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
7 | */
8 |
9 |
10 | // Default mixins and settings -----------------
11 | @import "../template/mixins";
12 | @import "../template/settings";
13 | // ---------------------------------------------
14 |
15 |
16 |
17 | // Include theme-specific fonts
18 | @import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700);
19 | @import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
20 |
21 |
22 | // Override theme settings (see ../template/settings.scss)
23 | $mainFont: 'Lato', sans-serif;
24 | $mainColor: #000;
25 | $headingFont: 'News Cycle', Impact, sans-serif;
26 | $headingColor: #000;
27 | $headingTextShadow: none;
28 | $headingTextTransform: none;
29 | $backgroundColor: #fff;
30 | $linkColor: #00008B;
31 | $linkColorHover: lighten( $linkColor, 20% );
32 | $selectionBackgroundColor: rgba(0, 0, 0, 0.99);
33 |
34 |
35 |
36 | // Theme template ------------------------------
37 | @import "../template/theme";
38 | // ---------------------------------------------
--------------------------------------------------------------------------------
/previous_presentations/dag2/small-case/readme.md:
--------------------------------------------------------------------------------
1 | # Case: Making a simple Record Collection App
2 |
3 | Start the project by cloning the repo, change directory to `small-case`,
4 | and install dependencies:
5 |
6 | ```
7 | npm install
8 | ```
9 |
10 |
11 | ## Running project
12 |
13 | You only need to run one command, it will take care of everything and open the
14 | approperiate page in your browser.
15 |
16 | ```
17 | npm start
18 | ```
19 |
20 |
21 | ## Working on the case.
22 |
23 | The implementation should be done in [/app.js](./app.js).
24 |
25 | A mock API has been written for this case, and is located in
26 | [/api.js](./api.js). It has the following methods:
27 |
28 | - **records()** Returns a promise which resolves to the contents of the record collection.
29 | - **newRecord(record)** Returns a promise which resolves to the newly added record.
30 |
31 | Both methods can be rejected with an Error.
32 |
33 | ### Result
34 |
35 | The result should be a fully functional app for storing records in memory.
36 |
37 | - It should validate each field and the whole form
38 | - It should fetch the existing records
39 | - It should add new records to the existing records (in memory only)
40 | - It should show spinners for async tasks
41 | - It should display error-messages
42 |
43 | 
44 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/css/theme/source/sky.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Sky theme for reveal.js.
3 | *
4 | * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
5 | */
6 |
7 |
8 | // Default mixins and settings -----------------
9 | @import "../template/mixins";
10 | @import "../template/settings";
11 | // ---------------------------------------------
12 |
13 |
14 |
15 | // Include theme-specific fonts
16 | @import url(https://fonts.googleapis.com/css?family=Quicksand:400,700,400italic,700italic);
17 | @import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700);
18 |
19 |
20 | // Override theme settings (see ../template/settings.scss)
21 | $mainFont: 'Open Sans', sans-serif;
22 | $mainColor: #333;
23 | $headingFont: 'Quicksand', sans-serif;
24 | $headingColor: #333;
25 | $headingLetterSpacing: -0.08em;
26 | $headingTextShadow: none;
27 | $backgroundColor: #f7fbfc;
28 | $linkColor: #3b759e;
29 | $linkColorHover: lighten( $linkColor, 20% );
30 | $selectionBackgroundColor: #134674;
31 |
32 | // Fix links so they are not cut off
33 | .reveal a:not(.image) {
34 | line-height: 1.3em;
35 | }
36 |
37 | // Background generator
38 | @mixin bodyBackground() {
39 | @include radial-gradient( #add9e4, #f7fbfc );
40 | }
41 |
42 |
43 |
44 | // Theme template ------------------------------
45 | @import "../template/theme";
46 | // ---------------------------------------------
47 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/browser/lib/helpers.js:
--------------------------------------------------------------------------------
1 | var $ = require('jquery'),
2 | bacon = require('baconjs'),
3 | chat = require('./chat'),
4 | template = require('lodash-node/modern/utilities/template'),
5 | messageTemplate = template($('#messageTemplate').html()),
6 | usersTemplate = template($('#usersTemplate').html()),
7 | partingTemplate = template($('#partingTemplate').html()),
8 | errorTemplate = template($('#errorTemplate').html());
9 |
10 | var joinRegex = /^\/j(?:oin)?\s+([\w]+)/i;
11 |
12 | module.exports.sum = function (acc, message) {
13 | return acc + message;
14 | };
15 |
16 | module.exports.toUserObject = function (username) {
17 | return {
18 | username: username
19 | };
20 | };
21 |
22 | module.exports.resetForm = function() {
23 | $("#input-message").val("").trigger("keyup");
24 | };
25 |
26 | var isJoinMessage = module.exports.isJoinMessage = function (val) {
27 | return joinRegex.test(val);
28 | };
29 | module.exports.notJoinMessage = function (val) {
30 | return !isJoinMessage(val);
31 | };
32 |
33 | module.exports.toUsername = function (val) {
34 | return joinRegex.exec(val)[1];
35 | };
36 |
37 | module.exports.renderOnline = function (allUsers) {
38 | return allUsers.map(usersTemplate);
39 | };
40 |
41 | module.exports.template = {
42 | message: messageTemplate,
43 | users: usersTemplate,
44 | parting: partingTemplate,
45 | error: errorTemplate
46 | };
--------------------------------------------------------------------------------
/scripts/vendor/codemirror-kimbie-dark.css:
--------------------------------------------------------------------------------
1 | /*
2 | Name: Kimbie (dark)
3 | Author: Jan T. Sott
4 | License: Creative Commons Attribution-ShareAlike 4.0 Unported License
5 | URL: https://github.com/idleberg/Kimbie-CodeMirror
6 | */
7 |
8 | .cm-s-kimbie-dark.CodeMirror {background: #141414; color: #e4c6a5;}
9 | .cm-s-kimbie-dark div.CodeMirror-selected {background: #5e452b !important;}
10 | .cm-s-kimbie-dark .CodeMirror-gutters {background: #141414; border-right: 0px;}
11 | .cm-s-kimbie-dark .CodeMirror-linenumber {color: #a57a4c;}
12 | .cm-s-kimbie-dark .CodeMirror-cursor {border-left: 1px solid #d6baad !important;}
13 |
14 | .cm-s-kimbie-dark span.cm-comment {color: #088649;}
15 | .cm-s-kimbie-dark span.cm-atom {color: #98676a;}
16 | .cm-s-kimbie-dark span.cm-number {color: #98676a;}
17 |
18 | .cm-s-kimbie-dark span.cm-property, .cm-s-kimbie-dark span.cm-attribute {color: #889b4a;}
19 | .cm-s-kimbie-dark span.cm-keyword {color: #dc3958;}
20 | .cm-s-kimbie-dark span.cm-string {color: #f06431;}
21 |
22 | .cm-s-kimbie-dark span.cm-variable {color: #889b4a;}
23 | .cm-s-kimbie-dark span.cm-variable-2 {color: #8ab1b0;}
24 | .cm-s-kimbie-dark span.cm-def {color: #f79a32;}
25 | .cm-s-kimbie-dark span.cm-error {background: #dc3958; color: #d6baad;}
26 | .cm-s-kimbie-dark span.cm-bracket {color: #e4c6a5;}
27 | .cm-s-kimbie-dark span.cm-tag {color: #dc3958;}
28 | .cm-s-kimbie-dark span.cm-link {color: #98676a;}
29 |
30 | .cm-s-kimbie-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
31 |
32 |
--------------------------------------------------------------------------------
/_sass/_content.scss:
--------------------------------------------------------------------------------
1 | @import "./globals/mixins";
2 | @import "./globals/colors";
3 |
4 | .mainContent {
5 | @include width-constraint;
6 | margin-top: 30px;
7 | display: block;
8 |
9 | &.playground {
10 | @include width-constraint-large;
11 | }
12 | }
13 |
14 | .mainContent h1,
15 | .mainContent h2,
16 | .mainContent h3 {
17 | font-size: 2rem;
18 | margin-bottom: 10px;
19 | font-weight: 100;
20 | position: relative;
21 | word-wrap: break-word;
22 |
23 | color: $color-organge-normal;
24 | }
25 | .mainContent h1 {
26 | margin-top: 50px;
27 | margin-top: 0;
28 | }
29 | .mainContent h2 {
30 | font-size: 1.5rem;
31 | }
32 | .mainContent h3 {
33 | font-size: 1.4rem;
34 | }
35 |
36 | .mainContent p {
37 | line-height: 1.7rem;
38 | }
39 |
40 | .mainContent table {
41 | width: 100%;
42 | margin: 10px 0;
43 | background: $color-table-white;
44 |
45 | td, th {
46 | padding: 5px;
47 | }
48 |
49 | tr:nth-child(odd) td {
50 | background: $color-table-zebra;
51 | }
52 | }
53 |
54 |
55 | .playground h1,
56 | .playground h2,
57 | .playground h3 {
58 | margin-top: 1rem;
59 | }
60 |
61 | .mainContent p {
62 | margin-bottom: 20px;
63 | }
64 |
65 | .mainContent img {
66 | max-width: 100%;
67 | }
68 |
69 | .edit-page-link {
70 | position: absolute;
71 | top: -0.8rem;
72 | right: 0;
73 | font-size: 0.7rem;
74 | }
75 |
76 | .fromMarkdown pre code {
77 | margin-bottom: 30px;
78 | }
79 |
80 | p img {
81 | background: #fff;
82 | }
83 |
84 | .column ul,
85 | .column ol {
86 | margin: 20px 0;
87 | }
88 |
--------------------------------------------------------------------------------
/scripts/playground-reporter.js:
--------------------------------------------------------------------------------
1 | module.exports = PlaygroundReporter;
2 |
3 | function PlaygroundReporter (runner) {
4 | var self = this
5 | , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 }
6 | , failures = this.failures = [];
7 |
8 | if (!runner) return;
9 | this.runner = runner;
10 |
11 | runner.stats = stats;
12 |
13 | runner.on('start', function () {
14 | stats.start = new Date;
15 | });
16 |
17 | runner.on('suite', function (suite) {
18 | stats.suites = stats.suites || 0;
19 | suite.root || stats.suites++;
20 | });
21 |
22 | runner.on('test end', function (test) {
23 | stats.tests = stats.tests || 0;
24 | stats.tests++;
25 | });
26 |
27 | runner.on('pass', function (test) {
28 | stats.passes = stats.passes || 0;
29 |
30 | var medium = test.slow() / 2;
31 | test.speed = test.duration > test.slow()
32 | ? 'slow'
33 | : test.duration > medium
34 | ? 'medium'
35 | : 'fast';
36 |
37 | stats.passes++;
38 | });
39 |
40 | runner.on('fail', function (test, err) {
41 | stats.failures = stats.failures || 0;
42 | stats.failures++;
43 | test.err = err;
44 | failures.push(test);
45 | });
46 |
47 | runner.on('end', function () {
48 | stats.end = new Date;
49 | stats.duration = new Date - stats.start;
50 | });
51 |
52 | runner.on('pending', function () {
53 | stats.pending++;
54 | });
55 | }
56 |
57 | PlaygroundReporter.prototype.done = function (failures, fn) {
58 | return fn(this, failures);
59 | };
60 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/small-case/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 | body {
5 | font-family: 'sans-serif';
6 | }
7 |
8 | form div:last-child {
9 | text-align: center;
10 | }
11 |
12 | label {
13 | display: inline-block;
14 | min-width: 15%;
15 | }
16 |
17 | .error {
18 | padding: 0.25em 1em;
19 | background: red;
20 | color: #000;
21 | width: 75%;
22 | border: 3px inset darkred;
23 | border-radius: 5px;
24 | }
25 |
26 | .add {
27 | width: 45%;
28 | margin-right: 5%;
29 | float: left;
30 | }
31 |
32 | .list {
33 | width: 50%;
34 | float: left;
35 | }
36 |
37 | .loader-small {
38 | height: 10px;
39 | width: 10px;
40 | border-radius: 20px;
41 | border: 3px solid #fff;
42 | border-left-color: transparent;
43 | border-top-color: #000;
44 | border-bottom-color: #000;
45 | border-right-color: transparent;
46 | margin-left: 5px;
47 | display: inline-block;
48 | animation: rotation 1s linear infinite;
49 | }
50 |
51 | .loader {
52 | position: relative;
53 | height: 50px;
54 | width: 50px;
55 | left: 25%;
56 | margin-top: 20px;
57 | border-radius: 75px;
58 | border: 3px solid #fff;
59 | border-left-color: transparent;
60 | border-top-color: #000;
61 | border-bottom-color: #000;
62 | border-right-color: transparent;
63 | animation: rotation 1s linear infinite;
64 | }
65 |
66 | @keyframes rotation {
67 | 0% {
68 | transform: rotate(0deg);
69 | }
70 |
71 | 50% {
72 | transform: rotate(180deg);
73 | }
74 |
75 | 100% {
76 | transform: rotate(360deg);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/lib/js/classList.js:
--------------------------------------------------------------------------------
1 | /*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js*/
2 | if(typeof document!=="undefined"&&!("classList" in document.createElement("a"))){(function(j){var a="classList",f="prototype",m=(j.HTMLElement||j.Element)[f],b=Object,k=String[f].trim||function(){return this.replace(/^\s+|\s+$/g,"")},c=Array[f].indexOf||function(q){var p=0,o=this.length;for(;p 1%', 'ie 8', 'ie 7']))
22 | .pipe(gulp.dest('_site/css'))
23 | .pipe(gulp.dest('css'));
24 | });
25 |
26 | gulp.task('js', js({}));
27 | gulp.task('js-watch', js({ watch: true }));
28 |
29 | gulp.task('watch', ['default'], function () {
30 | gulp.watch([
31 | '!scripts/*.build.js',
32 | 'scripts/**.js',
33 | 'scripts/**/*.js',
34 |
35 | ], ['js-watch']);
36 | gulp.watch('_sass/**/*.scss', ['sass']);
37 | gulp.watch([
38 | // 'scripts/**/*.js',
39 | '_workshop/*.js',
40 | '**/*.html',
41 | '!_site/**/*',
42 | '**/*.md'], ['jekyll-build']);
43 | });
44 |
45 | gulp.task('default', ['sass', 'jekyll-build', 'js']);
46 |
47 | function js (options) {
48 | return function () {
49 | return gulp.src('scripts/entry.js')
50 | .pipe(named(function (file) {
51 | return path.basename(file.path, path.extname(file.path)) + '.build';
52 | }))
53 | .pipe(webpack(require('./webpack')(options)))
54 | .pipe(gulpif(options.watch, gulp.dest('_site/scripts/'), gulp.dest('scripts/')));
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/gulpfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var gulp = require('gulp');
3 | var browserify = require('browserify');
4 | var watchify = require('watchify');
5 | var source = require('vinyl-source-stream');
6 | var notify = require('gulp-notify');
7 | var less = require('gulp-less');
8 | var path = require('path');
9 | var autoprefixer = require('gulp-autoprefixer');
10 |
11 | var css = './style/**/*.less';
12 | var js = __dirname + '/browser/main.js';
13 |
14 | var bundle = function (bundler) {
15 | return bundler.bundle()
16 | .on('error', notify.onError('Browserification failed! <%= error.message %>'))
17 | .pipe(source('bundle.js'))
18 | .pipe(gulp.dest(__dirname + '/static/'))
19 | .pipe(notify('Browserification done'));
20 | };
21 |
22 | gulp.task('js', function () {
23 | var bundler = browserify(js, { debug: true });
24 | return bundle(browserify(js));
25 | });
26 |
27 | gulp.task('js-watch', function () {
28 | var args = watchify.args;
29 | args.debug = true;
30 | var b = browserify(js, args);
31 | var bundler = watchify(b);
32 | bundler.on('update', bundle.bind(this, bundler));
33 | return bundle(bundler);
34 | });
35 |
36 | gulp.task('less', function () {
37 | gulp.src('./style/main.less')
38 | .pipe(less({
39 | paths: [ path.join(__dirname, 'style', 'includes') ]
40 | }))
41 | .on('error', notify.onError('Error with less! <%= error.message %>'))
42 | .pipe(autoprefixer({ cascade: true }))
43 | .pipe(gulp.dest('./static/'))
44 | .pipe(notify({
45 | message: 'Less compiled',
46 | onLast: true
47 | }));
48 | });
49 |
50 | // Rerun the task when a file changes
51 | gulp.task('watch', ['js-watch'], function() {
52 | gulp.watch(css, ['less']);
53 | });
54 |
55 |
56 | gulp.task('default', ['less', 'js']);
--------------------------------------------------------------------------------
/scripts/vendor/codemirror-base16-mocha-dark.css:
--------------------------------------------------------------------------------
1 | /*
2 | * https://github.com/idleberg/base16-codemirror/blob/master/base16-mocha-dark.css
3 | *
4 | Name: Base16 Mocha Dark
5 | Author: Chris Kempson (http://chriskempson.com)
6 | CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
7 | Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
8 | */
9 |
10 | .cm-s-base16-mocha-dark.CodeMirror {background: #3B3228; color: #e9e1dd;}
11 | .cm-s-base16-mocha-dark div.CodeMirror-selected {background: #534636 !important;}
12 | .cm-s-base16-mocha-dark .CodeMirror-gutters {background: #3B3228; border-right: 0px;}
13 | .cm-s-base16-mocha-dark .CodeMirror-linenumber {color: #7e705a;}
14 | .cm-s-base16-mocha-dark .CodeMirror-cursor {border-left: 1px solid #b8afad !important;}
15 |
16 | .cm-s-base16-mocha-dark span.cm-comment {color: #bb9584;}
17 | .cm-s-base16-mocha-dark span.cm-atom {color: #a89bb9;}
18 | .cm-s-base16-mocha-dark span.cm-number {color: #a89bb9;}
19 |
20 | .cm-s-base16-mocha-dark span.cm-property, .cm-s-base16-mocha-dark span.cm-attribute {color: #beb55b;}
21 | .cm-s-base16-mocha-dark span.cm-keyword {color: #cb6077;}
22 | .cm-s-base16-mocha-dark span.cm-string {color: #f4bc87;}
23 |
24 | .cm-s-base16-mocha-dark span.cm-variable {color: #beb55b;}
25 | .cm-s-base16-mocha-dark span.cm-variable-2 {color: #8ab3b5;}
26 | .cm-s-base16-mocha-dark span.cm-def {color: #d28b71;}
27 | .cm-s-base16-mocha-dark span.cm-error {background: #cb6077; color: #b8afad;}
28 | .cm-s-base16-mocha-dark span.cm-bracket {color: #e9e1dd;}
29 | .cm-s-base16-mocha-dark span.cm-tag {color: #cb6077;}
30 | .cm-s-base16-mocha-dark span.cm-link {color: #a89bb9;}
31 |
32 | .cm-s-base16-mocha-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
33 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/css/theme/source/beige.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Beige theme for reveal.js.
3 | *
4 | * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
5 | */
6 |
7 |
8 | // Default mixins and settings -----------------
9 | @import "../template/mixins";
10 | @import "../template/settings";
11 | // ---------------------------------------------
12 |
13 |
14 |
15 | // Include theme-specific fonts
16 | @font-face {
17 | font-family: 'League Gothic';
18 | src: url('../../lib/font/league_gothic-webfont.eot');
19 | src: url('../../lib/font/league_gothic-webfont.eot?#iefix') format('embedded-opentype'),
20 | url('../../lib/font/league_gothic-webfont.woff') format('woff'),
21 | url('../../lib/font/league_gothic-webfont.ttf') format('truetype'),
22 | url('../../lib/font/league_gothic-webfont.svg#LeagueGothicRegular') format('svg');
23 |
24 | font-weight: normal;
25 | font-style: normal;
26 | }
27 |
28 | @import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
29 |
30 |
31 | // Override theme settings (see ../template/settings.scss)
32 | $mainColor: #333;
33 | $headingColor: #333;
34 | $headingTextShadow: none;
35 | $backgroundColor: #f7f3de;
36 | $linkColor: #8b743d;
37 | $linkColorHover: lighten( $linkColor, 20% );
38 | $selectionBackgroundColor: rgba(79, 64, 28, 0.99);
39 | $heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15);
40 |
41 | // Background generator
42 | @mixin bodyBackground() {
43 | @include radial-gradient( rgba(247,242,211,1), rgba(255,255,255,1) );
44 | }
45 |
46 |
47 |
48 | // Theme template ------------------------------
49 | @import "../template/theme";
50 | // ---------------------------------------------
--------------------------------------------------------------------------------
/_workshop/02-6-point-free.js:
--------------------------------------------------------------------------------
1 | ---
2 | layout: workshop
3 | collection: workshop
4 | title: Point-free style
5 | section: 2
6 | prev: 02-5-lodash
7 | name: 02-6-point-free
8 | next: 02-7-context
9 | slides:
10 | info: |
11 | Every time we see the arguments "match up" and are passed
12 | through to the function in the callback, as with the `x`
13 | below, we do not need to create the callback function at all.
14 | That means that this:
15 |
16 | ```
17 | _.filter(collection, function(x) {
18 | return exists(x);
19 | });
20 | ```
21 |
22 | is the same as:
23 |
24 | ```
25 | _.filter(collection, exists);
26 | ```
27 |
28 | This is called point-free style, we will see quite a bit of this today!
29 | (There are some things to think about. We will look at those later.)
30 | ---
31 | describe('point-free style', function() {
32 |
33 | function exists(x) {
34 | return x != null; // i.e. the x is neither `null` nor `undefined`
35 | }
36 |
37 | function truthy(x) {
38 | return exists(x) && x !== false;
39 | }
40 |
41 | var values = ['user', null, false, 0, 'test', 1];
42 |
43 | it('lets us pass functions as references if they have matching arguments', function() {
44 | var result = values.filter(exists);
45 | expect(result).to.deep.equal(['user', false, 0, 'test', 1]);
46 | });
47 |
48 | it('works with many different functions', function() {
49 | var result = values.filter(truthy);
50 | expect(result).to.deep.equal(['user', 0, 'test', 1]);
51 | });
52 |
53 | });
54 |
55 | // PROBLEM: Sum the array using `_.reduce`, following a point-free style.
56 | // (You might need to create a helper function)
57 |
58 | describe('point-free _.reduce', function() {
59 | it('works as normal _.reduce', function() {
60 | var nums = [1,2,3,4,5];
61 |
62 | var sum = null;
63 |
64 | expect(sum).to.equal(15);
65 | });
66 | });
67 |
--------------------------------------------------------------------------------
/scripts/components/run-result.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import component from './component';
3 |
4 | export default component(function Result ({ stats, failures, errorResult }) {
5 |
6 | const tests = stats.get('tests'),
7 | passes = tests && stats.get('passes'),
8 | pending = tests && stats.get('pending'),
9 | failed = tests && stats.get('failures');
10 |
11 | const passesSummary = passes
12 | ? {passes} of {tests} test{tests > 1 ? 's' : ''} passed
13 | : null;
14 |
15 | const pendingPrefix = (passes && pending) ? ', ' : '';
16 |
17 | const pendingSummary = pending
18 | ? {pending} pending
19 | : null;
20 |
21 | const failedPrefix = failed
22 | ? (passes || pending) ? ', ' : ''
23 | : null;
24 |
25 | const failedSummary = failed
26 | ? (passes || pending)
27 | ? {failed} failed!
28 | : {failed} of {tests} test{tests > 1 ? 's' : ''} failed!
29 | : null;
30 |
31 | const testResults = failures.toArray().map(test => {
32 | const suiteTitle = test.parent ? test.parent.title : '';
33 | return ✘ {suiteTitle} {test.title}
{test.err.message}
34 | });
35 |
36 | const punctuation = !failed ? '.' : '';
37 |
38 | const errors = errorResult.deref();
39 |
40 | return
41 | {tests
42 | ?
{passesSummary}{pendingPrefix}{pendingSummary}{failedPrefix}{failedSummary}{punctuation}
43 | : null}
44 | {tests
45 | ?
{testResults}
46 | : null }
47 | {errors
48 | ?
49 | : null}
50 |
;
51 | });
52 |
53 |
54 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/plugin/math/math.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A plugin which enables rendering of math equations inside
3 | * of reveal.js slides. Essentially a thin wrapper for MathJax.
4 | *
5 | * @author Hakim El Hattab
6 | */
7 | var RevealMath = window.RevealMath || (function(){
8 |
9 | var options = Reveal.getConfig().math || {};
10 | options.mathjax = options.mathjax || 'http://cdn.mathjax.org/mathjax/latest/MathJax.js';
11 | options.config = options.config || 'TeX-AMS_HTML-full';
12 |
13 | loadScript( options.mathjax + '?config=' + options.config, function() {
14 |
15 | MathJax.Hub.Config({
16 | messageStyle: 'none',
17 | tex2jax: { inlineMath: [['$','$'],['\\(','\\)']] },
18 | skipStartupTypeset: true
19 | });
20 |
21 | // Typeset followed by an immediate reveal.js layout since
22 | // the typesetting process could affect slide height
23 | MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub ] );
24 | MathJax.Hub.Queue( Reveal.layout );
25 |
26 | // Reprocess equations in slides when they turn visible
27 | Reveal.addEventListener( 'slidechanged', function( event ) {
28 |
29 | MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, event.currentSlide ] );
30 |
31 | } );
32 |
33 | } );
34 |
35 | function loadScript( url, callback ) {
36 |
37 | var head = document.querySelector( 'head' );
38 | var script = document.createElement( 'script' );
39 | script.type = 'text/javascript';
40 | script.src = url;
41 |
42 | // Wrapper for callback to make sure it only fires once
43 | var finish = function() {
44 | if( typeof callback === 'function' ) {
45 | callback.call();
46 | callback = null;
47 | }
48 | }
49 |
50 | script.onload = finish;
51 |
52 | // IE
53 | script.onreadystatechange = function() {
54 | if ( this.readyState === 'loaded' ) {
55 | finish();
56 | }
57 | }
58 |
59 | // Normal browsers
60 | head.appendChild( script );
61 |
62 | }
63 |
64 | })();
65 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/agenda.md:
--------------------------------------------------------------------------------
1 | # Utkast til agenda for dag 2
2 |
3 | ## Motivasjon og teoretisk bakgrunn
4 | Ansvarlig: **Felles**
5 |
6 | - Repetisjon av funksjonell programmering (KJ eller Kjetil)
7 | - Motivasjon til FRP (Stian)
8 | - Introduksjon til reactive programming (Mikael)
9 | - Introduksjon til teoretisk FRP (Mikael)
10 |
11 | **(Pause)**
12 |
13 | ## Introduksjon av praktisk FRP
14 | Ansvarlig: **Stian**
15 |
16 | - Nevne forskjellige implementasjoner
17 | - Introdusere Bacon.js (Praktisk I)
18 | - Innkapsling av reaktive datatyper
19 | - Fra event target eller fra data (constant, interval, fromArray)
20 | - Property vs EventStream
21 | - Forskjeller
22 | - Hvordan bytte mellom dem
23 | - Subscribers
24 | - Lazy i utgangspunktet
25 | - onValue og doAction
26 | - log særtilfelle (legger til subscriber!)
27 | - Bacon Love: Introductory
28 | - Gjennomgang av LF
29 |
30 | **(Pause)**
31 |
32 | ## Praktisk FRP
33 | Ansvarlig: **Mikael**
34 |
35 | - Gjennomgang av basic kombinatorer
36 | - Map og Filter
37 | - Fold/Scan/Reduce
38 | - Merge/Combine
39 | - Templates
40 | - Bruke properties som verdier i kombinatorer
41 | - Bacon Love: Combinators
42 | - Gjennomgang av LF
43 |
44 | **(Pause)**
45 |
46 | ## Avansert praktisk FRP del 1
47 | Ansvarlig: **Mikael**
48 |
49 | - Avanserte teknikker for å kombinere reaktive datatyper
50 | - and/or
51 | - sampleby
52 | - debounce/throttle/take/skip
53 | - flatMap
54 | - Bacon Love: Advanced
55 | - Gjennomgang av LF
56 |
57 | **(Pause)**
58 |
59 | ## Avansert pratisk FRP del 2
60 | Ansvarlig: **Stian**
61 |
62 | - Eventuell teori?
63 | - Bacon Love: Beyond
64 | - Gjennomgang av LF
65 | - Enkel case: CRUD-form
66 |
67 | **(Pause)**
68 |
69 | ## Avansert case
70 | Ansvarlig: **Mikael**
71 |
72 | - Presentere case
73 | - Bacon chat?
74 | - Løsing av case.
75 | - LF av case
76 | - Videreutvikling av case basert på forslag/idéer eller egne innslag.
77 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/plugin/notes-server/client.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | // don't emit events from inside the previews themselves
3 | if ( window.location.search.match( /receiver/gi ) ) { return; }
4 |
5 | var socket = io.connect(window.location.origin);
6 | var socketId = Math.random().toString().slice(2);
7 |
8 | console.log('View slide notes at ' + window.location.origin + '/notes/' + socketId);
9 | window.open(window.location.origin + '/notes/' + socketId, 'notes-' + socketId);
10 |
11 | // Fires when a fragment is shown
12 | Reveal.addEventListener( 'fragmentshown', function( event ) {
13 | var fragmentData = {
14 | fragment : 'next',
15 | socketId : socketId
16 | };
17 | socket.emit('fragmentchanged', fragmentData);
18 | } );
19 |
20 | // Fires when a fragment is hidden
21 | Reveal.addEventListener( 'fragmenthidden', function( event ) {
22 | var fragmentData = {
23 | fragment : 'previous',
24 | socketId : socketId
25 | };
26 | socket.emit('fragmentchanged', fragmentData);
27 | } );
28 |
29 | // Fires when slide is changed
30 | Reveal.addEventListener( 'slidechanged', function( event ) {
31 | var nextindexh;
32 | var nextindexv;
33 | var slideElement = event.currentSlide;
34 |
35 | if (slideElement.nextElementSibling && slideElement.parentNode.nodeName == 'SECTION') {
36 | nextindexh = event.indexh;
37 | nextindexv = event.indexv + 1;
38 | } else {
39 | nextindexh = event.indexh + 1;
40 | nextindexv = 0;
41 | }
42 |
43 | var notes = slideElement.querySelector('aside.notes');
44 | var slideData = {
45 | notes : notes ? notes.innerHTML : '',
46 | indexh : event.indexh,
47 | indexv : event.indexv,
48 | nextindexh : nextindexh,
49 | nextindexv : nextindexv,
50 | socketId : socketId,
51 | markdown : notes ? typeof notes.getAttribute('data-markdown') === 'string' : false
52 |
53 | };
54 |
55 | socket.emit('slidechanged', slideData);
56 | } );
57 | }());
58 |
--------------------------------------------------------------------------------
/_workshop/02-5-lodash.js:
--------------------------------------------------------------------------------
1 | ---
2 | layout: workshop
3 | collection: workshop
4 | title: Using helper liberaries
5 | section: 2
6 | prev: 02-4-reduce
7 | name: 02-5-lodash
8 | next: 02-6-point-free
9 | slides:
10 | info: |
11 | In the examples we have seen so far, we have used methods that live
12 | on an array. We are now going to switch tactics and focus more on
13 | functions instead of methods. For example, in addition to
14 | `Array.prototype.reduce`, there exists a `reduce` functions in
15 | libraries such as Lo-Dash and Underscore. One of the primary values
16 | of using these functions instead is composability. We are going to
17 | look more on what exactly that means later. Another great thing is
18 | that some of these functions are more powerful that the methods on
19 | arrays.
20 |
21 | In this course we will use Lo-Dash, which will be accessible through the `_`
22 | global (however, we could also have chosen Underscore instead).
23 | ---
24 |
25 | describe('_.reduce', function() {
26 | // We'll start by going back to reduce. As for the built-in reduce,
27 | // _.reduce does not need a starting value. (Reduce without an initial
28 | // value is actually a fold, and in fact, in Lo-Dash _.reduce is aliased
29 | // to _.foldl, i.e. fold from the left.)
30 |
31 | function join(arr, chr) {
32 | return _.reduce(arr, function(memo, str) {
33 | return memo + chr + str;
34 | });
35 | }
36 |
37 | it('works the same way as the array method', function() {
38 | var result = join(['a','b','c'], ':');
39 | expect(result).to.equal('a:b:c');
40 | });
41 |
42 | });
43 |
44 | // PROBLEM: Determine the longest word using _.reduce
45 |
46 | function longest(arr) {
47 | }
48 |
49 | describe('longest', function() {
50 |
51 | it('finds the longest word in a collection', function() {
52 |
53 | var result = longest(['test', 'kim', 'winning', 'lol']);
54 | expect(result).to.equal('winning');
55 |
56 | });
57 | });
58 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/small-case/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | FRP CRUD Case
6 |
7 |
8 |
9 | Welcome to my awesome record collection
10 | A sample application for keeping track of records.
11 |
12 |
13 |
Add Record
14 |
46 |
47 |
48 |
Registered Records
49 |
50 |
51 |
52 |
53 |
Failed to get records from server
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/_workshop/01-2-arguments.js:
--------------------------------------------------------------------------------
1 | ---
2 | layout: workshop
3 | collection: workshop
4 | title: A functions arguments
5 | section: 1
6 | prev: 01-1-context
7 | name: 01-2-arguments
8 | next: 01-3-prototype
9 | slides:
10 | info: |
11 | Arguments are what makes functions interesting. Being able to pass data and
12 | information to a function in order to change its result is important.
13 | ---
14 | function helloTo(thing) {
15 | return this + ' says hello ' + thing;
16 | }
17 |
18 | function argCount() {
19 | return arguments.length;
20 | }
21 | describe('a functions arguments', function() {
22 | // Inside a function you will always have access to `arguments`,
23 | // which is an array-like object that contains all the arguments
24 | // passed to the function.
25 |
26 | it('can be counted', function() {
27 | var result = argCount(1, 2, 3);
28 | expect(result).to.equal(3);
29 | });
30 |
31 | // JavaScript is not strict about the number of
32 | // arguments, so you can for example include more parameters than
33 | // the function expects:
34 |
35 | it('are not strict in number', function() {
36 | var result = helloTo.call('kim', 'world', 'or', 'maybe', 'bekk');
37 | expect(result).to.equal('kim says hello world');
38 | });
39 |
40 | // But JavaScript is strict with the count of arguments regardless of
41 | // wether the argument was used or not.
42 |
43 | it('has a strict count', function() {
44 | var result = argCount(null, 2, 3);
45 | expect(result).to.equal(2);
46 | });
47 |
48 | });
49 |
50 | function multiplyFirst() {
51 | // PROBLEM:
52 | // Multiply `this` and the first argument,
53 | // without specifying any parameters
54 | }
55 |
56 | describe('multiplyFirst', function() {
57 |
58 | it('1*1=1', function() {
59 | var result = multiplyFirst.call(1,1);
60 | expect(result).to.equal(1);
61 | });
62 |
63 | it('2*5=10', function() {
64 | var result = multiplyFirst.call(2,5);
65 | expect(result).to.equal(10);
66 | });
67 | });
68 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/css/theme/source/moon.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Solarized Dark theme for reveal.js.
3 | * Author: Achim Staebler
4 | */
5 |
6 |
7 | // Default mixins and settings -----------------
8 | @import "../template/mixins";
9 | @import "../template/settings";
10 | // ---------------------------------------------
11 |
12 |
13 |
14 | // Include theme-specific fonts
15 | @font-face {
16 | font-family: 'League Gothic';
17 | src: url('../../lib/font/league_gothic-webfont.eot');
18 | src: url('../../lib/font/league_gothic-webfont.eot?#iefix') format('embedded-opentype'),
19 | url('../../lib/font/league_gothic-webfont.woff') format('woff'),
20 | url('../../lib/font/league_gothic-webfont.ttf') format('truetype'),
21 | url('../../lib/font/league_gothic-webfont.svg#LeagueGothicRegular') format('svg');
22 |
23 | font-weight: normal;
24 | font-style: normal;
25 | }
26 |
27 | @import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
28 |
29 | /**
30 | * Solarized colors by Ethan Schoonover
31 | */
32 | html * {
33 | color-profile: sRGB;
34 | rendering-intent: auto;
35 | }
36 |
37 | // Solarized colors
38 | $base03: #002b36;
39 | $base02: #073642;
40 | $base01: #586e75;
41 | $base00: #657b83;
42 | $base0: #839496;
43 | $base1: #93a1a1;
44 | $base2: #eee8d5;
45 | $base3: #fdf6e3;
46 | $yellow: #b58900;
47 | $orange: #cb4b16;
48 | $red: #dc322f;
49 | $magenta: #d33682;
50 | $violet: #6c71c4;
51 | $blue: #268bd2;
52 | $cyan: #2aa198;
53 | $green: #859900;
54 |
55 | // Override theme settings (see ../template/settings.scss)
56 | $mainColor: $base1;
57 | $headingColor: $base2;
58 | $headingTextShadow: none;
59 | $backgroundColor: $base03;
60 | $linkColor: $blue;
61 | $linkColorHover: lighten( $linkColor, 20% );
62 | $selectionBackgroundColor: $magenta;
63 |
64 |
65 |
66 | // Theme template ------------------------------
67 | @import "../template/theme";
68 | // ---------------------------------------------
69 |
--------------------------------------------------------------------------------
/_sass/font/_fontello.scss:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'fontello';
3 | src: url('../assets/font/fontello.eot?22358951');
4 | src: url('../assets/font/fontello.eot?22358951#iefix') format('embedded-opentype'),
5 | url('../assets/font/fontello.woff?22358951') format('woff'),
6 | url('../assets/font/fontello.ttf?22358951') format('truetype'),
7 | url('../assets/font/fontello.svg?22358951#fontello') format('svg');
8 | font-weight: normal;
9 | font-style: normal;
10 | }
11 | /* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
12 | /* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
13 | /*
14 | @media screen and (-webkit-min-device-pixel-ratio:0) {
15 | @font-face {
16 | font-family: 'fontello';
17 | src: url('../font/fontello.svg?22358951#fontello') format('svg');
18 | }
19 | }
20 | */
21 |
22 | [class^="icon-"]:before, [class*=" icon-"]:before {
23 | font-family: "fontello";
24 | font-style: normal;
25 | font-weight: normal;
26 | speak: none;
27 |
28 | display: inline-block;
29 | text-decoration: inherit;
30 | width: 1em;
31 | margin-right: .2em;
32 | text-align: center;
33 | /* opacity: .8; */
34 |
35 | /* For safety - reset parent styles, that can break glyph codes*/
36 | font-variant: normal;
37 | text-transform: none;
38 |
39 | /* fix buttons height, for twitter bootstrap */
40 | line-height: 1em;
41 |
42 | /* Animation center compensation - margins should be symmetric */
43 | /* remove if not needed */
44 | margin-left: .2em;
45 |
46 | /* you can be more comfortable with increased icons size */
47 | /* font-size: 120%; */
48 |
49 | /* Uncomment for 3D effect */
50 | /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
51 | }
52 |
53 | .icon-twitter:before { content: '\e800'; } /* '' */
54 | .icon-fork:before { content: '\e801'; } /* '' */
55 | .icon-spin2:before { content: '\e802'; } /* '' */
56 | .icon-github-circled:before { content: '\e803'; } /* '' */
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | BaconChat
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
BaconChat
16 |
17 |
18 |
22 |
23 |
26 |
32 |
33 |
34 |
45 |
52 |
59 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/plugin/notes-server/index.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var fs = require('fs');
3 | var io = require('socket.io');
4 | var _ = require('underscore');
5 | var Mustache = require('mustache');
6 |
7 | var app = express.createServer();
8 | var staticDir = express.static;
9 |
10 | io = io.listen(app);
11 |
12 | var opts = {
13 | port : 1947,
14 | baseDir : __dirname + '/../../'
15 | };
16 |
17 | io.sockets.on('connection', function(socket) {
18 | socket.on('slidechanged', function(slideData) {
19 | socket.broadcast.emit('slidedata', slideData);
20 | });
21 | socket.on('fragmentchanged', function(fragmentData) {
22 | socket.broadcast.emit('fragmentdata', fragmentData);
23 | });
24 | });
25 |
26 | app.configure(function() {
27 | [ 'css', 'js', 'images', 'plugin', 'lib' ].forEach(function(dir) {
28 | app.use('/' + dir, staticDir(opts.baseDir + dir));
29 | });
30 | });
31 |
32 | app.get("/", function(req, res) {
33 | res.writeHead(200, {'Content-Type': 'text/html'});
34 | fs.createReadStream(opts.baseDir + '/index.html').pipe(res);
35 | });
36 |
37 | app.get("/notes/:socketId", function(req, res) {
38 |
39 | fs.readFile(opts.baseDir + 'plugin/notes-server/notes.html', function(err, data) {
40 | res.send(Mustache.to_html(data.toString(), {
41 | socketId : req.params.socketId
42 | }));
43 | });
44 | // fs.createReadStream(opts.baseDir + 'notes-server/notes.html').pipe(res);
45 | });
46 |
47 | // Actually listen
48 | app.listen(opts.port || null);
49 |
50 | var brown = '\033[33m',
51 | green = '\033[32m',
52 | reset = '\033[0m';
53 |
54 | var slidesLocation = "http://localhost" + ( opts.port ? ( ':' + opts.port ) : '' );
55 |
56 | console.log( brown + "reveal.js - Speaker Notes" + reset );
57 | console.log( "1. Open the slides at " + green + slidesLocation + reset );
58 | console.log( "2. Click on the link your JS console to go to the notes page" );
59 | console.log( "3. Advance through your slides and your notes will advance automatically" );
60 |
--------------------------------------------------------------------------------
/_workshop/01-1-context.js:
--------------------------------------------------------------------------------
1 | ---
2 | layout: workshop
3 | collection: workshop
4 | title: A functions context
5 | section: 1
6 | prev: ''
7 | name: 01-1-context
8 | next: 01-2-arguments
9 | slides:
10 | info: |
11 | It is time to get started. This workshop will start with some of the basics of
12 | JavaScript, with scope and context, to ensure that you fully understand how
13 | functions work in JavaScript.
14 |
15 | We start with how context works when using functions in JavaScript.
16 | ---
17 | //A couple of functions that we will work with during this exercise
18 |
19 | function hello() {
20 | return this + ' says hello';
21 | }
22 |
23 | describe('a functions context', function() {
24 | // In JavaScript we can dynamically choose the value of `this`
25 | // using several techniques. Today we will focus on some of these,
26 | // starting with `call` and `apply`.
27 |
28 | it('is undefined by default', function() {
29 | //call function to observe default behavior
30 | var result = null;
31 | expect(result).to.equal('undefined says hello');
32 | });
33 |
34 | // `call` calls a function with a given `this` value as the first
35 | // parameter, then arguments provided individually:
36 | //
37 | // func.call(this, arg1, arg2, ...)
38 | it('can change when using call', function() {
39 | //change context of `hello` by using `call`
40 | var result = hello();
41 | expect(result).to.equal('kim says hello');
42 | });
43 |
44 | // `apply` calls a function with a given `this` value as the first
45 | // parameter, then arguments provided as an array
46 | //
47 | // func.apply(this, [arg1, arg2, ...])
48 | it('can change when using apply', function() {
49 | //change context of `hello` by using `apply`
50 | var result = hello();
51 | expect(result).to.equal('kim says hello');
52 | });
53 |
54 | });
55 | // If you want to learn more about function invocation in
56 | // JavaScript, I recommend reading:
57 | // http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/
58 |
--------------------------------------------------------------------------------
/_workshop/01-3-prototype.js:
--------------------------------------------------------------------------------
1 | ---
2 | layout: workshop
3 | collection: workshop
4 | title: Functions and prototypes
5 | section: 1
6 | prev: 01-2-arguments
7 | name: 01-3-prototype
8 | next: 02-1-applicative
9 | slides:
10 | info: |
11 | Prototypes are another core concept in JavaScript. Functions and prototypes
12 | interact in many interesting ways.
13 |
14 | There will not be much about prototypes in this workshop, but
15 | there is one thing it is important to understand, especially when
16 | working with `arguments`: In JavaScript you can borrow existing
17 | functions that live on a prototype.
18 | ---
19 | var User = function(age) {
20 | this.age = age;
21 | };
22 |
23 | User.prototype.getAge = function() {
24 | return this.age;
25 | };
26 |
27 | describe('prototype-functions', function() {
28 |
29 | it('are usually bound to the context of an object', function() {
30 | var user = new User(25);
31 | var age = user.getAge();
32 |
33 | expect(age).to.equal(25);
34 | });
35 |
36 | // However, in JavaScript we can actually invoke `getAge` without
37 | // creating an instance of `User`.
38 |
39 | // We can say that we are "borrowing" the getAge function
40 | // from the User prototype.
41 | it('can be borrowed and have their context bound at will', function() {
42 | var age = User.prototype.getAge.call({ age: 35 });
43 | expect(age).to.equal(35);
44 | });
45 |
46 | });
47 |
48 | // PROBLEM:
49 | // Create a function that "borrow" `Array.prototype.slice`
50 | // and returns all the arguments given, except the first.
51 |
52 | // NOTE: This has changed in ES2015 (aka ES6), but it is
53 | // still a useful exercise.
54 |
55 | function rest() {
56 | }
57 |
58 | describe('rest', function() {
59 |
60 | it('should return all arguments except the first one', function() {
61 | var result = rest(1);
62 | expect(result).to.deep.equal([]);
63 | });
64 |
65 | it('should return all arguments except the first one', function() {
66 | var result = rest(1, 2, 3);
67 | expect(result).to.deep.equal([2, 3]);
68 | });
69 |
70 | });
71 |
--------------------------------------------------------------------------------
/_workshop/02-7-context.js:
--------------------------------------------------------------------------------
1 | ---
2 | layout: workshop
3 | collection: workshop
4 | title: Applicative functions with context
5 | section: 2
6 | prev: 02-6-point-free
7 | name: 02-7-context
8 | next: 03-1-factories
9 | slides:
10 | info: |
11 | Sometimes you want to use map, filter, reduce or other functions
12 | inside an object and you want want to access something on
13 | `this`. Thankfully this is very simple on _.filter and friends --
14 | just add the context, i.e. what you want `this` to be, as the
15 | last parameter.
16 | ---
17 | describe('filter with context', function() {
18 | var ages = [20, 30, 75, 156, 200];
19 |
20 | var people = {
21 | maxAge: 120,
22 | validAges: function(ages) {
23 |
24 | return _.filter(ages, function(age) {
25 | return age < this.maxAge;
26 | }, this);
27 |
28 | // here we specified that we want `this` inside the function in the
29 | // filter be the same as `this` is inside the current function
30 |
31 | }
32 | };
33 |
34 | it('works by passing a context to the lodash-function which it can bind to', function() {
35 | var result = people.validAges(ages);
36 |
37 | expect(result).to.deep.equal([20, 30, 75]);
38 | });
39 | });
40 |
41 | describe('our filter with context', function() {
42 |
43 | // PROBLEM: Fix our filter implementation below so it handles the
44 | // specified context
45 |
46 | var filter = function(items, fn, context) {
47 | var arr = [];
48 | for (var i = 0; i < items.length; i++) {
49 | if (fn(items[i], i)) {
50 | arr.push(items[i]);
51 | }
52 | }
53 | return arr;
54 | }
55 |
56 | var ages = [20, 30, 75, 156, 200];
57 |
58 | var people = {
59 | maxAge: 120,
60 | validAges: function(ages) {
61 | return filter(ages, function(age) {
62 | return age < this.maxAge;
63 | }, this);
64 | }
65 | };
66 |
67 | it('works when we pass a context that we bind the function to', function() {
68 | var result = people.validAges(ages);
69 | expect(result).to.deep.equal([20, 30, 75]);
70 | });
71 |
72 | });
73 |
--------------------------------------------------------------------------------
/css/vendor/base16-mocha-dark.css:
--------------------------------------------------------------------------------
1 | /*
2 | * https://github.com/idleberg/base16-highlight.js/blob/master/base16-mocha.dark.css
3 |
4 | Name: Base16 Mocha Dark
5 | Author: Chris Kempson (http://chriskempson.com)
6 |
7 | highlight.js v8.0 template by Jan T. Sott (https://github.com/idleberg/base16-highlight.js)
8 | Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
9 |
10 | */
11 |
12 | /* Mocha Comment */
13 | .hljs-comment,
14 | .hljs-title {
15 | color: #b8afad;
16 | }
17 |
18 | /* Mocha Red */
19 | .hljs-variable,
20 | .hljs-attribute,
21 | .hljs-tag,
22 | .hljs-regexp,
23 | .ruby .hljs-constant,
24 | .xml .hljs-tag .hljs-title,
25 | .xml .hljs-pi,
26 | .xml .hljs-doctype,
27 | .html .hljs-doctype,
28 | .css .hljs-id,
29 | .css .hljs-class,
30 | .css .hljs-pseudo {
31 | color: #cb6077;
32 | }
33 |
34 | /* Mocha Orange */
35 | .hljs-number,
36 | .hljs-preprocessor,
37 | .hljs-built_in,
38 | .hljs-literal,
39 | .hljs-params,
40 | .hljs-constant {
41 | color: #d28b71;
42 | }
43 |
44 | /* Mocha Yellow */
45 | .ruby .hljs-class .hljs-title,
46 | .css .hljs-rules .hljs-attribute {
47 | color: #f4bc87;
48 | }
49 |
50 | /* Mocha Green */
51 | .hljs-string,
52 | .hljs-value,
53 | .hljs-inheritance,
54 | .hljs-header,
55 | .ruby .hljs-symbol,
56 | .xml .hljs-cdata {
57 | color: #beb55b;
58 | }
59 |
60 | /* Mocha Aqua */
61 | .css .hljs-hexcolor {
62 | color:: #7bbda4;
63 | }
64 |
65 | /* Mocha Blue */
66 | .hljs-function,
67 | .python .hljs-decorator,
68 | .python .hljs-title,
69 | .ruby .hljs-function .hljs-title,
70 | .ruby .hljs-title .hljs-keyword,
71 | .perl .hljs-sub,
72 | .javascript .hljs-title,
73 | .coffeescript .hljs-title {
74 | color: #8ab3b5;
75 | }
76 |
77 | /* Mocha Purple */
78 | .hljs-keyword,
79 | .javascript .hljs-function {
80 | color: #a89bb9;
81 | }
82 |
83 | .hljs {
84 | display: block;
85 | background: #3B3228;
86 | color: #d0c8c6;
87 | padding: 0.5em;
88 | }
89 |
90 | .coffeescript .javascript,
91 | .javascript .xml,
92 | .tex .hljs-formula,
93 | .xml .javascript,
94 | .xml .vbscript,
95 | .xml .css,
96 | .xml .hljs-cdata {
97 | opacity: 0.5;
98 | }
99 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/browser/lib/chat.js:
--------------------------------------------------------------------------------
1 |
2 | var io = require('socket.io-client');
3 | var EventEmitter = require('events').EventEmitter;
4 | var inherits = require('util').inherits;
5 | var humanize = require('humanize');
6 | var config = require('../config');
7 | var toArray = require('lodash-node/modern/collections/toArray');
8 |
9 | var reemit = function (client, type) {
10 | return function () {
11 | var args = toArray(arguments);
12 | args.unshift(type)
13 | client.emit.apply(client, args);
14 | };
15 | };
16 |
17 | var Chat = function () {
18 | this.connected = false;
19 | var client = this;
20 | client.socket = io(config.ws);
21 |
22 | client.socket.on('connect', function(){
23 | client.connected = true;
24 | client.emit('connected');
25 | });
26 | client.socket.on('message', reemit(client, 'message'));
27 | client.socket.on('part', reemit(client, 'part'));
28 | client.socket.on('join', reemit(client, 'join'));
29 | return client;
30 | };
31 | inherits(Chat, EventEmitter);
32 |
33 | Chat.prototype.join = function (username) {
34 | if (!this.connected) {
35 | this.emit('error', new Error('Not connected yet.'));
36 | return this;
37 | }
38 | if (this.username) {
39 | this.emit('error', new Error('Already connected and logged in as ' + this.username));
40 | return this;
41 | }
42 |
43 | this.username = username;
44 | this.socket.emit('join', username);
45 | this.emit('join', username);
46 | return this;
47 | };
48 |
49 | Chat.prototype.message = function (obj) {
50 | if (!this.connected || !this.username) {
51 | this.emit('error', new Error('Not connected yet. Join by using /join '));
52 | return this;
53 | }
54 | if (!obj.message) {
55 | this.emit('error', new Error('No message given.'));
56 | return this;
57 | }
58 | var data = {
59 | username: this.username,
60 | message: obj.message,
61 | picture: obj.picture,
62 | time: humanize.date('d.m.Y - H:i:s')
63 | };
64 | this.socket.emit('message', data);
65 | this.emit('message', data);
66 | return this;
67 | };
68 |
69 | var chat = module.exports = new Chat();
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/css/theme/source/solarized.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Solarized Light theme for reveal.js.
3 | * Author: Achim Staebler
4 | */
5 |
6 |
7 | // Default mixins and settings -----------------
8 | @import "../template/mixins";
9 | @import "../template/settings";
10 | // ---------------------------------------------
11 |
12 |
13 |
14 | // Include theme-specific fonts
15 | @font-face {
16 | font-family: 'League Gothic';
17 | src: url('../../lib/font/league_gothic-webfont.eot');
18 | src: url('../../lib/font/league_gothic-webfont.eot?#iefix') format('embedded-opentype'),
19 | url('../../lib/font/league_gothic-webfont.woff') format('woff'),
20 | url('../../lib/font/league_gothic-webfont.ttf') format('truetype'),
21 | url('../../lib/font/league_gothic-webfont.svg#LeagueGothicRegular') format('svg');
22 |
23 | font-weight: normal;
24 | font-style: normal;
25 | }
26 |
27 | @import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
28 |
29 |
30 | /**
31 | * Solarized colors by Ethan Schoonover
32 | */
33 | html * {
34 | color-profile: sRGB;
35 | rendering-intent: auto;
36 | }
37 |
38 | // Solarized colors
39 | $base03: #002b36;
40 | $base02: #073642;
41 | $base01: #586e75;
42 | $base00: #657b83;
43 | $base0: #839496;
44 | $base1: #93a1a1;
45 | $base2: #eee8d5;
46 | $base3: #fdf6e3;
47 | $yellow: #b58900;
48 | $orange: #cb4b16;
49 | $red: #dc322f;
50 | $magenta: #d33682;
51 | $violet: #6c71c4;
52 | $blue: #268bd2;
53 | $cyan: #2aa198;
54 | $green: #859900;
55 |
56 | // Override theme settings (see ../template/settings.scss)
57 | $mainColor: $base00;
58 | $headingColor: $base01;
59 | $headingTextShadow: none;
60 | $backgroundColor: $base3;
61 | $linkColor: $blue;
62 | $linkColorHover: lighten( $linkColor, 20% );
63 | $selectionBackgroundColor: $magenta;
64 |
65 | // Background generator
66 | // @mixin bodyBackground() {
67 | // @include radial-gradient( rgba($base3,1), rgba(lighten($base3, 20%),1) );
68 | // }
69 |
70 |
71 |
72 | // Theme template ------------------------------
73 | @import "../template/theme";
74 | // ---------------------------------------------
75 |
--------------------------------------------------------------------------------
/_workshop/03-3-functions-with-functions.js:
--------------------------------------------------------------------------------
1 | ---
2 | layout: workshop
3 | collection: workshop
4 | title: Functions with functions
5 | section: 3
6 | prev: 03-2-higher-order
7 | name: 03-3-functions-with-functions
8 | next: 03-4-fluent
9 | slides:
10 | info: |
11 | In JavaScript you can actually add functions onto existing
12 | functions. This can create sweet APIs. Let us look at an example.
13 |
14 | I have seen this pattern in many code bases:
15 |
16 | ```
17 | if (debug) console.log('some text');
18 | ```
19 |
20 | When you want to show debug information you set debug to `true`. You of
21 | course need to always remember to write that `if` everywhere in your
22 | code. Let us create a create a better API.
23 | ---
24 | // PROBLEM: We want to guard a function, so that it only calls
25 | // through to the function we pass in once we have called `start`
26 | // on the guard. (See below for the tests to understand how this is
27 | // supposed to work.)
28 |
29 | function guard(fn) {
30 | var guard = function() {
31 | };
32 |
33 | // in JavaScript you can actually add
34 | // functions to existing functions
35 |
36 | guard.start = function() {
37 | };
38 |
39 | return guard;
40 | };
41 |
42 | describe('guard', function() {
43 | // Let's now guard a debug helper. To make it a little bit simpler
44 | // to test, we return a message instead of calling console.log or similar.
45 |
46 | var callCount = 0;
47 | var debug = guard(function(msg) {
48 | callCount += 1;
49 | return msg;
50 | });
51 |
52 | it('should not return anything if not started', function() {
53 | var result = debug('test 1');
54 | expect(callCount).to.equal(0);
55 | expect(result).to.equal(undefined);
56 | });
57 |
58 | it('should not return anything if not started even when invoked multiple times', function() {
59 | var result = debug('test 2');
60 | expect(callCount).to.equal(0);
61 | expect(result).to.equal(undefined);
62 | });
63 |
64 | it('should return if started', function() {
65 | // open up the guard
66 | debug.start();
67 |
68 | var result = debug('test 3');
69 | expect(callCount).to.equal(1);
70 | expect(result).to.equal('test 3');
71 | });
72 |
73 | });
74 |
--------------------------------------------------------------------------------
/_sass/font/_animation.scss:
--------------------------------------------------------------------------------
1 | /*
2 | Animation example, for spinners
3 | */
4 | .animate-spin {
5 | -moz-animation: spin 2s infinite linear;
6 | -o-animation: spin 2s infinite linear;
7 | -webkit-animation: spin 2s infinite linear;
8 | animation: spin 2s infinite linear;
9 | display: inline-block;
10 | }
11 | @-moz-keyframes spin {
12 | 0% {
13 | -moz-transform: rotate(0deg);
14 | -o-transform: rotate(0deg);
15 | -webkit-transform: rotate(0deg);
16 | transform: rotate(0deg);
17 | }
18 |
19 | 100% {
20 | -moz-transform: rotate(359deg);
21 | -o-transform: rotate(359deg);
22 | -webkit-transform: rotate(359deg);
23 | transform: rotate(359deg);
24 | }
25 | }
26 | @-webkit-keyframes spin {
27 | 0% {
28 | -moz-transform: rotate(0deg);
29 | -o-transform: rotate(0deg);
30 | -webkit-transform: rotate(0deg);
31 | transform: rotate(0deg);
32 | }
33 |
34 | 100% {
35 | -moz-transform: rotate(359deg);
36 | -o-transform: rotate(359deg);
37 | -webkit-transform: rotate(359deg);
38 | transform: rotate(359deg);
39 | }
40 | }
41 | @-o-keyframes spin {
42 | 0% {
43 | -moz-transform: rotate(0deg);
44 | -o-transform: rotate(0deg);
45 | -webkit-transform: rotate(0deg);
46 | transform: rotate(0deg);
47 | }
48 |
49 | 100% {
50 | -moz-transform: rotate(359deg);
51 | -o-transform: rotate(359deg);
52 | -webkit-transform: rotate(359deg);
53 | transform: rotate(359deg);
54 | }
55 | }
56 | @-ms-keyframes spin {
57 | 0% {
58 | -moz-transform: rotate(0deg);
59 | -o-transform: rotate(0deg);
60 | -webkit-transform: rotate(0deg);
61 | transform: rotate(0deg);
62 | }
63 |
64 | 100% {
65 | -moz-transform: rotate(359deg);
66 | -o-transform: rotate(359deg);
67 | -webkit-transform: rotate(359deg);
68 | transform: rotate(359deg);
69 | }
70 | }
71 | @keyframes spin {
72 | 0% {
73 | -moz-transform: rotate(0deg);
74 | -o-transform: rotate(0deg);
75 | -webkit-transform: rotate(0deg);
76 | transform: rotate(0deg);
77 | }
78 |
79 | 100% {
80 | -moz-transform: rotate(359deg);
81 | -o-transform: rotate(359deg);
82 | -webkit-transform: rotate(359deg);
83 | transform: rotate(359deg);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/scripts/components/codemirror-editor.js:
--------------------------------------------------------------------------------
1 | import component from './component';
2 | import React from 'react';
3 |
4 | import CodeMirror from 'codemirror';
5 | import 'codemirror/mode/javascript/javascript';
6 |
7 | import 'codemirror/addon/edit/closebrackets';
8 | import 'codemirror/addon/edit/matchbrackets';
9 |
10 | const throttledReplaceState = throttle(replaceStateValue, 2000);
11 |
12 | export default component([{
13 |
14 | componentDidMount: function () {
15 | const isLarge = this.props.statics.isLarge;
16 |
17 | const options = {
18 | autoCloseBrackets: true,
19 | matchBrackets: true,
20 | lineNumbers: isLarge,
21 | lineWrapping: false,
22 | viewportMargin: Infinity,
23 | theme: 'base16-mocha-dark',
24 | tabSize: 2,
25 | extraKeys: { Tab }
26 | };
27 |
28 | const onCodeMirrorChange = editor => {
29 | const source = editor.doc.getValue();
30 | this.props.source.update(_ => source);
31 |
32 | if (isLarge) {
33 | throttledReplaceState(source);
34 | }
35 | };
36 |
37 | this.editor = CodeMirror.fromTextArea(this.getDOMNode(), options);
38 | this.editor.on('change', onCodeMirrorChange);
39 |
40 | if (isLarge) {
41 | let initialCode = location.hash.replace(/^#/, '');
42 | try {
43 | initialCode = decodeURIComponent(initialCode);
44 | }
45 | catch (ignore) { }
46 | const source = initialCode || this.props.source.deref();
47 | this.editor.setValue(source);
48 | }
49 | },
50 |
51 | shouldComponentUpdate: function () {
52 | return false;
53 | }
54 |
55 | }], function CodeMirrorEditor ({source}) {
56 | return ;
57 | });
58 |
59 | function Tab (cm) {
60 | if (cm.somethingSelected()) {
61 | cm.indentSelection("add");
62 | } else {
63 | cm.execCommand('insertSoftTab')
64 | }
65 | }
66 |
67 | function replaceStateValue (value) {
68 | history.replaceState(null, 'playground', '#' + encodeURIComponent(value));
69 | }
70 |
71 | function throttle (fn, ms) {
72 | let timeout;
73 | return function () {
74 | const self = this, args = [].slice.call(arguments);
75 | if (timeout) {
76 | clearTimeout(timeout);
77 | timeout = undefined;
78 | }
79 | timeout = setTimeout(function () {
80 | fn.apply(self, args);
81 | }, ms);
82 | };
83 | }
84 |
85 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/lib/css/zenburn.css:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Zenburn style from voldmar.ru (c) Vladimir Epifanov
4 | based on dark.css by Ivan Sagalaev
5 |
6 | */
7 |
8 | pre code {
9 | display: block; padding: 0.5em;
10 | background: #3F3F3F;
11 | color: #DCDCDC;
12 | }
13 |
14 | pre .keyword,
15 | pre .tag,
16 | pre .django .tag,
17 | pre .django .keyword,
18 | pre .css .class,
19 | pre .css .id,
20 | pre .lisp .title {
21 | color: #E3CEAB;
22 | }
23 |
24 | pre .django .template_tag,
25 | pre .django .variable,
26 | pre .django .filter .argument {
27 | color: #DCDCDC;
28 | }
29 |
30 | pre .number,
31 | pre .date {
32 | color: #8CD0D3;
33 | }
34 |
35 | pre .dos .envvar,
36 | pre .dos .stream,
37 | pre .variable,
38 | pre .apache .sqbracket {
39 | color: #EFDCBC;
40 | }
41 |
42 | pre .dos .flow,
43 | pre .diff .change,
44 | pre .python .exception,
45 | pre .python .built_in,
46 | pre .literal,
47 | pre .tex .special {
48 | color: #EFEFAF;
49 | }
50 |
51 | pre .diff .chunk,
52 | pre .ruby .subst {
53 | color: #8F8F8F;
54 | }
55 |
56 | pre .dos .keyword,
57 | pre .python .decorator,
58 | pre .class .title,
59 | pre .haskell .label,
60 | pre .function .title,
61 | pre .ini .title,
62 | pre .diff .header,
63 | pre .ruby .class .parent,
64 | pre .apache .tag,
65 | pre .nginx .built_in,
66 | pre .tex .command,
67 | pre .input_number {
68 | color: #efef8f;
69 | }
70 |
71 | pre .dos .winutils,
72 | pre .ruby .symbol,
73 | pre .ruby .symbol .string,
74 | pre .ruby .symbol .keyword,
75 | pre .ruby .symbol .keymethods,
76 | pre .ruby .string,
77 | pre .ruby .instancevar {
78 | color: #DCA3A3;
79 | }
80 |
81 | pre .diff .deletion,
82 | pre .string,
83 | pre .tag .value,
84 | pre .preprocessor,
85 | pre .built_in,
86 | pre .sql .aggregate,
87 | pre .javadoc,
88 | pre .smalltalk .class,
89 | pre .smalltalk .localvars,
90 | pre .smalltalk .array,
91 | pre .css .rules .value,
92 | pre .attr_selector,
93 | pre .pseudo,
94 | pre .apache .cbracket,
95 | pre .tex .formula {
96 | color: #CC9393;
97 | }
98 |
99 | pre .shebang,
100 | pre .diff .addition,
101 | pre .comment,
102 | pre .java .annotation,
103 | pre .template_comment,
104 | pre .pi,
105 | pre .doctype {
106 | color: #7F9F7F;
107 | }
108 |
109 | pre .xml .css,
110 | pre .xml .javascript,
111 | pre .xml .vbscript,
112 | pre .tex .formula {
113 | opacity: 0.5;
114 | }
115 |
116 |
--------------------------------------------------------------------------------
/_workshop/03-5-arity.js:
--------------------------------------------------------------------------------
1 | ---
2 | layout: workshop
3 | collection: workshop
4 | title: Function arity
5 | section: 3
6 | prev: 03-4-fluent
7 | name: 03-5-arity
8 | next: 04-1-partial-application
9 | slides:
10 | info: |
11 | The arity of a function is the number of arguments it takes.
12 |
13 | E.g. the arity for the following function is 2:
14 |
15 | ```
16 | function plus(a, b) {
17 | return a + b;
18 | }
19 | ```
20 |
21 | ---
22 | describe('arity of parseInt', function() {
23 | // Going from string to int we can use parseInt, e.g.
24 |
25 | it('normal usage', function() {
26 | var result = parseInt('123');
27 | expect(result).to.equal(123);
28 | });
29 |
30 | // However, trying to use this function together with map,
31 | // we see a problem:
32 |
33 | it('is funky when mapping over the function', function() {
34 | var parsed = ['1','2','3'].map(parseInt)
35 |
36 | // The first is 1, as expected
37 | expect(parsed[0]).to.equal(1);
38 |
39 | // ... but the two others are not even numbers:
40 | expect(isNaN(parsed[1])).to.be.true;
41 | expect(isNaN(parsed[2])).to.be.true;
42 | });
43 |
44 | // (we can't use `to.deep.equal` since NaN !== NaN in JavaScript)
45 | });
46 |
47 | describe('fixed parseInt', function() {
48 | // The problem is that map calls each function with three parameters -- the
49 | // value, the index, and the array. Instead of the above, we could write:
50 |
51 | var parsed = ['1','2','3'].map(function(value, index, arr) {
52 | return parseInt(value);
53 | })
54 |
55 | it('should work with map', function() {
56 | var result = parsed;
57 | expect(result).to.deep.equal([1,2,3]);
58 | });
59 |
60 | // However, there are a couple of other solutions. We can for example
61 | // create a helper to do the job for us, and that lets us write:
62 | function unary(fn) {
63 | return function(arg) {
64 | return fn.call(this, arg)
65 | }
66 | }
67 |
68 | var parsed2 = ['1', '2', '3'].map(unary(parseInt))
69 |
70 | // Here we have created unary, which ensures that a function is only ever
71 | // called with one argument, no matter how many you actually send to it.
72 |
73 | it('should work with unary decorator', function() {
74 | var result = parsed2;
75 | expect(result).to.deep.equal([1,2,3]);
76 | });
77 |
78 | // However, unary might be to simple in this case, as we actually
79 | // might want to call:
80 | //
81 | // parseInt(val, 10);
82 | //
83 | // To get there, however, we should first learn some things about
84 | // partial application.
85 | });
86 |
--------------------------------------------------------------------------------
/_workshop/02-3-filter.js:
--------------------------------------------------------------------------------
1 | ---
2 | layout: workshop
3 | collection: workshop
4 | title: Make new collections with filter
5 | section: 2
6 | prev: 02-2-map
7 | name: 02-3-filter
8 | next: 02-4-reduce
9 | slides:
10 | info: |
11 | A filter function accepts a higher-order function and a collection,
12 | then applies the passed function to each element and returns a
13 | new collection which includes a subset of the original collection.
14 |
15 | An element is included in the new collection if the filter-function returns
16 | true and is excluded if the filter-function returns false.
17 | ---
18 | describe('filter', function() {
19 | // A filter-function includes the value for all function invocations that
20 | // return `true`. Here's an example, again using `for`:
21 |
22 | function removeOddIndicesFor(arr) {
23 | var newArr = [];
24 | for (var i = 0; i < arr.length; i++) {
25 | if (i % 2 == 0) {
26 | newArr.push(arr[i]);
27 | }
28 | }
29 | return newArr;
30 | }
31 |
32 | it('can be implemented as a for-loop', function() {
33 | var result = removeOddIndicesFor([1,2,3,4,5]);
34 | expect(result).to.deep.equal([1,3,5]);
35 | });
36 |
37 | // PROBLEM: Implement this using a `Array.prototype.filter`
38 | // instead:
39 |
40 | function removeOddIndices(arr) {
41 | }
42 |
43 | it('exists as a method on arrays in JavaScript', function() {
44 | var result = removeOddIndices([1,2,3,4,5]);
45 | expect(result).to.deep.equal([1,3,5]);
46 | });
47 |
48 | });
49 |
50 | // To be entirely sure that we properly understand how these
51 | // functions work, let's implement our own `map` and `filter`
52 | // functions. The implementation of these still have to concern
53 | // themselves with loops, counters and state.
54 |
55 | // (If you struggle, be sure to take a look at the examples we
56 | // saw earlier.)
57 |
58 | // PROBLEM: Implement `map`
59 |
60 | var map = function(items, fn) {
61 | }
62 |
63 | describe('implemented map', function() {
64 |
65 | it('mapfilter1', function() {
66 | var result = map([1,2,3,4], function(value, index) {
67 | return value * index;
68 | });
69 |
70 | expect(result).to.deep.equal([0, 2, 6, 12]);
71 | });
72 |
73 | });
74 |
75 | // PROBLEM: Implement `filter`
76 |
77 | var filter = function(items, fn) {
78 | }
79 |
80 | describe('implemented filter', function() {
81 |
82 | it('mapfilter2', function() {
83 | var result = ilter([1,2,3,4], function(value, index) {
84 | return value * index > 4;
85 | });
86 |
87 | expect(result).to.deep.equal([3,4]);
88 | });
89 | });
90 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/plugin/notes/notes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Handles opening of and synchronization with the reveal.js
3 | * notes window.
4 | */
5 | var RevealNotes = (function() {
6 |
7 | function openNotes() {
8 | var jsFileLocation = document.querySelector('script[src$="notes.js"]').src; // this js file path
9 | jsFileLocation = jsFileLocation.replace(/notes\.js(\?.*)?$/, ''); // the js folder path
10 | var notesPopup = window.open( jsFileLocation + 'notes.html', 'reveal.js - Notes', 'width=1120,height=850' );
11 |
12 | // Fires when slide is changed
13 | Reveal.addEventListener( 'slidechanged', post );
14 |
15 | // Fires when a fragment is shown
16 | Reveal.addEventListener( 'fragmentshown', post );
17 |
18 | // Fires when a fragment is hidden
19 | Reveal.addEventListener( 'fragmenthidden', post );
20 |
21 | /**
22 | * Posts the current slide data to the notes window
23 | */
24 | function post() {
25 | var slideElement = Reveal.getCurrentSlide(),
26 | slideIndices = Reveal.getIndices(),
27 | messageData;
28 |
29 | var notes = slideElement.querySelector( 'aside.notes' ),
30 | nextindexh,
31 | nextindexv;
32 |
33 | if( slideElement.nextElementSibling && slideElement.parentNode.nodeName == 'SECTION' ) {
34 | nextindexh = slideIndices.h;
35 | nextindexv = slideIndices.v + 1;
36 | } else {
37 | nextindexh = slideIndices.h + 1;
38 | nextindexv = 0;
39 | }
40 |
41 | messageData = {
42 | notes : notes ? notes.innerHTML : '',
43 | indexh : slideIndices.h,
44 | indexv : slideIndices.v,
45 | indexf : slideIndices.f,
46 | nextindexh : nextindexh,
47 | nextindexv : nextindexv,
48 | markdown : notes ? typeof notes.getAttribute( 'data-markdown' ) === 'string' : false
49 | };
50 |
51 | notesPopup.postMessage( JSON.stringify( messageData ), '*' );
52 | }
53 |
54 | // Navigate to the current slide when the notes are loaded
55 | notesPopup.addEventListener( 'load', function( event ) {
56 | post();
57 | }, false );
58 | }
59 |
60 | // If the there's a 'notes' query set, open directly
61 | if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) {
62 | openNotes();
63 | }
64 |
65 | // Open the notes when the 's' key is hit
66 | document.addEventListener( 'keydown', function( event ) {
67 | // Disregard the event if the target is editable or a
68 | // modifier is present
69 | if ( document.querySelector( ':focus' ) !== null || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) return;
70 |
71 | if( event.keyCode === 83 ) {
72 | event.preventDefault();
73 | openNotes();
74 | }
75 | }, false );
76 |
77 | return { open: openNotes };
78 | })();
79 |
--------------------------------------------------------------------------------
/_workshop/02-2-map.js:
--------------------------------------------------------------------------------
1 | ---
2 | layout: workshop
3 | collection: workshop
4 | title: Make new collections with map
5 | section: 2
6 | prev: 02-1-applicative
7 | name: 02-2-map
8 | next: 02-3-filter
9 | slides:
10 | info: |
11 | A map function accepts a higher-order function and a collection,
12 | then applies the passed function to each element and returns a
13 | new collection.
14 | ---
15 |
16 | describe('map', function() {
17 | // To understand what we're talking about, this is an example of
18 | // using a for loop to go through a collection, performing a
19 | // calculation on each item:
20 |
21 | function squareFor(arr) {
22 | var newArr = [];
23 | for (var i = 0; i < arr.length; i++) {
24 | newArr.push(arr[i] * arr[i]);
25 | }
26 | return newArr;
27 | }
28 |
29 | it('can be implemented as a for-loop', function() {
30 | var result = squareFor([1,2,3]);
31 | expect(result).to.deep.equal([1,4,9]);
32 | });
33 |
34 | // For-loops involve alot of manual steps, which makes it error prone.
35 | // Thankfully we now have a `map` functions on `Array.prototype`.
36 |
37 | // For each iteration of map it invokes the function with three
38 | // arguments: the current value, the current index, the entire
39 | // collection. So we could have written this instead:
40 |
41 | function square(arr) {
42 | return arr.map(function(value, index, collection) {
43 | return value * value;
44 | });
45 | }
46 |
47 | it('exists as a method on arrays in JavaScript', function() {
48 | var result = square([1,2,3]);
49 | expect(result).to.deep.equal([1,4,9]);
50 | });
51 |
52 | // An important characteristic of these kinds of higher order functions is
53 | // that they do not modify the original collection.
54 | it('does not modify the original collection', function() {
55 | var numbers = [1,2,3];
56 | var result = square(numbers);
57 |
58 | expect(numbers).to.not.equal(result);
59 | });
60 |
61 | });
62 |
63 | // PROBLEM: Implement the following function using map, i.e. a
64 | // function that adds the current index to the current value:
65 | //
66 | // for (var i = 0; i < arr.length; i++) {
67 | // arr[i] = arr[i] + i
68 | // }
69 |
70 | function addIndex(arr) {
71 | }
72 |
73 | describe('addIndex', function() {
74 | it('should add the index to the current element', function() {
75 | var result = addIndex([1,2,3]);
76 | expect(result).to.deep.equal([1,3,5]);
77 | });
78 |
79 | it('should not modify the original collection', function() {
80 | var numbers = [1,2,3];
81 | var result = addIndex(numbers);
82 |
83 | expect(result).to.deep.equal([1,3,5]);
84 | expect(numbers).to.not.equal(result);
85 | });
86 | });
87 |
--------------------------------------------------------------------------------
/_sass/_header.scss:
--------------------------------------------------------------------------------
1 | @import "./globals/colors";
2 | @import "./globals/mixins";
3 | @import "./globals/size";
4 |
5 | .mainHeader {
6 | background: linear-gradient(to bottom, $color-header-background 0%, $color-header-background--bottom 100%);
7 | }
8 |
9 | .mainHeader-illustration {
10 | @include width-constraint;
11 |
12 | display: flex;
13 | align-items: center;
14 | flex-wrap: wrap;
15 |
16 | svg {
17 | min-width: 400px;
18 | margin: auto;
19 | flex: 3 0 30%;
20 | }
21 | }
22 |
23 | .mainHeader-illustration .illustrationText {
24 | flex: 1 1 30%;
25 | color: $color-infoBoxes;
26 | text-shadow: 1px 1px 1px rgba(0,0,0,.4);
27 |
28 | .github-badges {
29 | margin-top: 15px;
30 | text-align: center;
31 | }
32 |
33 | h1 {
34 | font-size: 2.5rem;
35 | }
36 | }
37 |
38 | @media (max-width: $remove-graphics-width) {
39 | .mainHeader-illustration svg {
40 | display: none;
41 | }
42 | }
43 |
44 | .mainNavigation {
45 | z-index: 3; // .CodeMirror pre is 2
46 |
47 | height: $header-height;
48 | position: fixed;
49 | min-height: initial;
50 | top: 0;
51 | left: 0;
52 | width: 100%;
53 | background: $color-header-background--small;
54 | }
55 |
56 | .mainNavigation-inner {
57 | @include width-constraint;
58 |
59 | display: flex;
60 | align-items: center;
61 | padding: 15px 0;
62 |
63 | justify-content: space-between;
64 |
65 | ul {
66 | // display: flex;
67 | list-style-type: none;
68 | margin-top: 5px;
69 | font-size: 1.2rem;
70 |
71 | li {
72 | float: left;
73 |
74 | &:last-child a {
75 | margin-right: 0;
76 | }
77 | }
78 |
79 | li a {
80 | display: block;
81 | margin-left: 20px;
82 |
83 | color: $color-header-linkColor;
84 | transition: all 300ms;
85 |
86 | text-transform: uppercase;
87 | text-decoration: none;
88 | font-weight: 300;
89 |
90 |
91 | &:hover {
92 | text-shadow: 1px 1px 3px rgba(0,0,0, .7);
93 | }
94 | }
95 |
96 | li:first-child a {
97 | margin-left: 0;
98 | }
99 | }
100 | }
101 |
102 | @media (max-width: $minify-header-width) {
103 | .mainNavigation-inner ul {
104 | li:nth-last-child(1),
105 | li:nth-last-child(2) {
106 | display: none;
107 | }
108 | }
109 | }
110 |
111 | .mainNavigation-inner h1 a {
112 | display: block;
113 |
114 | img {
115 | height: 33px;
116 | }
117 | }
118 |
119 | .chevronDown {
120 | height: 25px;
121 | display: block;
122 | text-align: center;
123 | transition: all 400ms;
124 |
125 | i {
126 | transition: all 400ms;
127 | @include chevron($color-blue-light, 5px, 50px);
128 | top: 10px;
129 | opacity: 0.5;
130 | }
131 |
132 | &:hover i {
133 | opacity: 1;
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/_sass/_window.scss:
--------------------------------------------------------------------------------
1 | .CodeMirror {
2 | z-index: 0;
3 | padding-bottom: 0.5rem;
4 | border-top-left-radius: 3px;
5 | border-top-right-radius: 3px;
6 | }
7 | .CodeMirror,
8 | .inner--result {
9 | font-size: 1rem;
10 | }
11 | .window .CodeMirror-lines {
12 | padding: 0;
13 | padding-left: 0.4rem;
14 | }
15 |
16 | .playground {
17 |
18 | .window .CodeMirror-lines {
19 | padding: 0;
20 | }
21 |
22 | .CodeMirror {
23 | border-top-left-radius: 3px;
24 | border-top-right-radius: 0;
25 | border-bottom-left-radius: 3px;
26 | }
27 |
28 | .CodeMirror-line-numbers {
29 | font-size: 0.2rem;
30 | }
31 |
32 | .CodeMirror,
33 | .inner--result {
34 | font-size: 1.15rem;
35 | }
36 |
37 | .window {
38 | display: flex;
39 | flex-flow: row wrap;
40 | }
41 |
42 | .control {
43 | flex: 1 100%;
44 | }
45 | .inner--code {
46 | flex: 1 65%;
47 | }
48 | .inner--result {
49 | flex: 1 35%;
50 | }
51 | }
52 |
53 | $color-error: #f25156;
54 | $color-success: #4ca73c;
55 | $color-pending: #f7ac3c;
56 |
57 | .test-summary {
58 | font-size: 0.9rem;
59 | text-align: center;
60 | }
61 |
62 | .editor-pending {
63 | color: $color-pending;
64 | }
65 | .editor-success {
66 | color: $color-success;
67 | }
68 |
69 | .editor > .inner > textarea {
70 | display: none;
71 | }
72 | .editor-error {
73 | color: $color-error;
74 | pre {
75 | font-size: 12px;
76 | white-space: pre-wrap; /* CSS 3 */
77 | white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
78 | white-space: -pre-wrap; /* Opera 4-6 */
79 | white-space: -o-pre-wrap; /* Opera 7 */
80 | word-wrap: break-word; /* Internet Explorer 5.5+ */
81 | }
82 | }
83 |
84 | .window {
85 | background: #fafafa;
86 | width: 100%;
87 | border-radius: 3px;
88 | margin: 20px auto;
89 | box-shadow: 0px 1px 6px rgba(0, 0, 0, 0.2);
90 | }
91 |
92 | .window .inner {
93 | padding: 0.5rem 0.75rem 0.1rem 0.75rem;
94 | }
95 | .window .inner--result {
96 | border-bottom-left-radius: 3px;
97 | border-bottom-right-radius: 3px;
98 | }
99 | .window .inner--code--withoutResult {
100 | border-bottom-left-radius: 3px;
101 | border-bottom-right-radius: 3px;
102 | }
103 |
104 | .window.window--code {
105 | background: none;
106 | }
107 | .window .inner--code {
108 | padding: 0;
109 | }
110 |
111 | .inner--result {
112 | color: #474747;
113 | font-weight: 300;
114 | }
115 |
116 | pre code {
117 | padding: 0 10px;
118 | background: #141414;
119 | display: block;
120 | padding: 10px;
121 | border-radius: 3px;
122 | overflow: auto;
123 | }
124 |
125 | p code, ul code, li code {
126 | background: darken($color-table-zebra, 1%);
127 | border: 1px solid darken($color-table-zebra, 10%);
128 | line-height: 1.4rem;
129 | padding: 0 5px;
130 | display: inline-block;
131 | border-radius: 2px;
132 | }
133 |
--------------------------------------------------------------------------------
/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/lib/js/head.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | Head JS The only script in your
3 | Copyright Tero Piirainen (tipiirai)
4 | License MIT / http://bit.ly/mit-license
5 | Version 0.96
6 |
7 | http://headjs.com
8 | */(function(a){function z(){d||(d=!0,s(e,function(a){p(a)}))}function y(c,d){var e=a.createElement("script");e.type="text/"+(c.type||"javascript"),e.src=c.src||c,e.async=!1,e.onreadystatechange=e.onload=function(){var a=e.readyState;!d.done&&(!a||/loaded|complete/.test(a))&&(d.done=!0,d())},(a.body||b).appendChild(e)}function x(a,b){if(a.state==o)return b&&b();if(a.state==n)return k.ready(a.name,b);if(a.state==m)return a.onpreload.push(function(){x(a,b)});a.state=n,y(a.url,function(){a.state=o,b&&b(),s(g[a.name],function(a){p(a)}),u()&&d&&s(g.ALL,function(a){p(a)})})}function w(a,b){a.state===undefined&&(a.state=m,a.onpreload=[],y({src:a.url,type:"cache"},function(){v(a)}))}function v(a){a.state=l,s(a.onpreload,function(a){a.call()})}function u(a){a=a||h;var b;for(var c in a){if(a.hasOwnProperty(c)&&a[c].state!=o)return!1;b=!0}return b}function t(a){return Object.prototype.toString.call(a)=="[object Function]"}function s(a,b){if(!!a){typeof a=="object"&&(a=[].slice.call(a));for(var c=0;c
2 | {% include head.html %}
3 |
4 |
5 |
6 | Task: {{page.title}}
7 |
8 | {% if page.slides %}
9 | See related slides for this part: {{page.slides}}
10 | {% endif %}
11 |
12 |
20 |
21 | {% if page.info %}
22 | Information
23 | {{page.info | markdownify}}
24 | {% endif %}
25 |
26 |
27 |
28 | Tasks
29 |
30 | {% for item in site.workshop %}
31 | {% if item.hide != true %}
32 | {% assign pageID = page.name %}
33 | {% assign itemID = item.name %}
34 | {% assign className = pageID == itemID ? ' class="active"' : '' %}
35 | -
36 | {% if item.start == true %}
37 |
38 | {% else %}
39 |
40 | {% endif %}
41 | {% if item["section"] %}Part {{item["section"]}}: {% endif %}
42 | {{item["title"]}}
43 |
44 | {% if pageID == itemID %}[Active]{% endif %}
45 |
46 | {% endif %}
47 | {% endfor %}
48 |
49 |
50 |
58 |
59 | Help
60 |
61 | Available globals
62 |
63 | _: Lo-dash.js
64 | log: log-command that logs to view and console
65 |
66 |
67 | Testing
68 |
69 | describe: new test suite (mocha)
70 | it: new test (mocha)
71 | xit: pending test (mocha)
72 | xdescribe: pending scenario (mocha)
73 | before/after: run code before or after all tests (mocha)
74 | beforeEach/afterEach: run code before or after each tests (mocha)
75 | chai: chai.js assertion library
76 |
77 |
78 |
79 | {% include footer.html %}
80 |
81 |
82 |
--------------------------------------------------------------------------------
/assets/font/fontello.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/plugin/markdown/example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | reveal.js - Markdown Demo
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
35 |
36 |
37 |
53 |
54 |
55 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/assets/component-tree.svg:
--------------------------------------------------------------------------------
1 |
25 |
--------------------------------------------------------------------------------
/_sass/_syntax-highlighting.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Syntax highlighting styles
3 | */
4 | .highlight {
5 | background: #fff;
6 | @extend %vertical-rhythm;
7 |
8 | .c { color: #998; font-style: italic } // Comment
9 | .err { color: #a61717; background-color: #e3d2d2 } // Error
10 | .k { font-weight: bold } // Keyword
11 | .o { font-weight: bold } // Operator
12 | .cm { color: #998; font-style: italic } // Comment.Multiline
13 | .cp { color: #999; font-weight: bold } // Comment.Preproc
14 | .c1 { color: #998; font-style: italic } // Comment.Single
15 | .cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special
16 | .gd { color: #000; background-color: #fdd } // Generic.Deleted
17 | .gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific
18 | .ge { font-style: italic } // Generic.Emph
19 | .gr { color: #a00 } // Generic.Error
20 | .gh { color: #999 } // Generic.Heading
21 | .gi { color: #000; background-color: #dfd } // Generic.Inserted
22 | .gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific
23 | .go { color: #888 } // Generic.Output
24 | .gp { color: #555 } // Generic.Prompt
25 | .gs { font-weight: bold } // Generic.Strong
26 | .gu { color: #aaa } // Generic.Subheading
27 | .gt { color: #a00 } // Generic.Traceback
28 | .kc { font-weight: bold } // Keyword.Constant
29 | .kd { font-weight: bold } // Keyword.Declaration
30 | .kp { font-weight: bold } // Keyword.Pseudo
31 | .kr { font-weight: bold } // Keyword.Reserved
32 | .kt { color: #458; font-weight: bold } // Keyword.Type
33 | .m { color: #099 } // Literal.Number
34 | .s { color: #d14 } // Literal.String
35 | .na { color: #008080 } // Name.Attribute
36 | .nb { color: #0086B3 } // Name.Builtin
37 | .nc { color: #458; font-weight: bold } // Name.Class
38 | .no { color: #008080 } // Name.Constant
39 | .ni { color: #800080 } // Name.Entity
40 | .ne { color: #900; font-weight: bold } // Name.Exception
41 | .nf { color: #900; font-weight: bold } // Name.Function
42 | .nn { color: #555 } // Name.Namespace
43 | .nt { color: #000080 } // Name.Tag
44 | .nv { color: #008080 } // Name.Variable
45 | .ow { font-weight: bold } // Operator.Word
46 | .w { color: #bbb } // Text.Whitespace
47 | .mf { color: #099 } // Literal.Number.Float
48 | .mh { color: #099 } // Literal.Number.Hex
49 | .mi { color: #099 } // Literal.Number.Integer
50 | .mo { color: #099 } // Literal.Number.Oct
51 | .sb { color: #d14 } // Literal.String.Backtick
52 | .sc { color: #d14 } // Literal.String.Char
53 | .sd { color: #d14 } // Literal.String.Doc
54 | .s2 { color: #d14 } // Literal.String.Double
55 | .se { color: #d14 } // Literal.String.Escape
56 | .sh { color: #d14 } // Literal.String.Heredoc
57 | .si { color: #d14 } // Literal.String.Interpol
58 | .sx { color: #d14 } // Literal.String.Other
59 | .sr { color: #009926 } // Literal.String.Regex
60 | .s1 { color: #d14 } // Literal.String.Single
61 | .ss { color: #990073 } // Literal.String.Symbol
62 | .bp { color: #999 } // Name.Builtin.Pseudo
63 | .vc { color: #008080 } // Name.Variable.Class
64 | .vg { color: #008080 } // Name.Variable.Global
65 | .vi { color: #008080 } // Name.Variable.Instance
66 | .il { color: #099 } // Literal.Number.Integer.Long
67 | }
68 |
--------------------------------------------------------------------------------
/_workshop/03-4-fluent.js:
--------------------------------------------------------------------------------
1 | ---
2 | layout: workshop
3 | collection: workshop
4 | title: Fluent interfaces
5 | section: 3
6 | prev: 03-3-functions-with-functions
7 | name: 03-4-fluent
8 | next: 03-5-arity
9 | slides:
10 | info: |
11 | Many of us are used to jQuery and its fluent apis, e.g.
12 |
13 | ```
14 | $('#test')
15 | .css('color','#333')
16 | .height(200)
17 | .on('click', function() {
18 | console.log('clicked!')
19 | });
20 | ```
21 |
22 | Fluent apis is often referred to as method chaining. and we use it to achieve
23 | code that is as fluently readable as possible and thus quicker to understand.
24 | In the jQuery example above, all functions return `this` so we can keep
25 | calling methods that exists on `$('#test')`.
26 |
27 | Let us create a small helper that simplifies the development of
28 | such fluent apis.
29 | ---
30 | // First, to get an understanding of how we can create a simple
31 | // helper for these fluent interfaces, we start with an entirely
32 | // different example, `maybe`:
33 |
34 | function maybe(fn) {
35 | return function(arg) {
36 | if (arg != null) {
37 | return fn(arg);
38 | }
39 | }
40 | }
41 |
42 | describe('maybe', function() {
43 | var exclamate = maybe(function(val) {
44 | return val + '!';
45 | });
46 |
47 | it('should return when called with an argument', function() {
48 | var result = exclamate('test');
49 | expect(result).to.equal('test!');
50 | });
51 |
52 | it('should not return when called with null argument', function() {
53 | var result = exclamate(null);
54 | expect(result).to.equal(undefined);
55 | });
56 |
57 | it('should not return when called without argument', function() {
58 | var result = exclamate();
59 | expect(result).to.equal(undefined);
60 | });
61 |
62 | // We have now created a helper than only calls the received function is
63 | // the input is neither null nor undefined. Yet another decorator, that is.
64 |
65 | // Btw, why doesn't this work?
66 |
67 | var user = {
68 | setName: maybe(function(name) {
69 | this.name = name;
70 | })
71 | };
72 |
73 | it('to throw', function() {
74 | expect(function() {
75 | user.setName('kim');
76 | }).to.throw(TypeError);
77 | });
78 |
79 | // It throws this error at us:
80 | //
81 | // TypeError: Cannot set property 'name' of undefined
82 | });
83 |
84 | // As is often the case in JavaScript, the problem is `this`. We
85 | // forgot to handle the context when we called `fn` in our `maybe`
86 | // decorator. In decorators we must always use `call` or `apply` --
87 | // make them context agnostic!
88 |
89 | // PROBLEM: Now it's time to create a `fluent` decorator
90 |
91 | function fluent(fn) {
92 | }
93 |
94 | describe('fluent', function() {
95 | // Here we have our example `$`, containing a field `value` that we
96 | // want to read out last. (You shouldn't change anything below here.)
97 |
98 | var $ = function(el) {
99 | return {
100 | value: 'somevalue',
101 |
102 | // using our fluent helper
103 | css: fluent(function(key, val) {}),
104 | height: fluent(function(height) {}),
105 | on: fluent(function(event, cb) {})
106 | }
107 | };
108 |
109 |
110 | it('should enable use of fluent interfaces', function() {
111 | var result = $('#test')
112 | .css('color','#333')
113 | .height(200)
114 | .on('click', function() {
115 | console.log('clicked!')
116 | })
117 | .value;
118 |
119 | expect(result).to.equal('somevalue');
120 | });
121 | });
122 |
--------------------------------------------------------------------------------
/previous_presentations/dag1/slides/remark-styling.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Droid Serif';
3 | font-style: normal;
4 | font-weight: 400;
5 | src: local('Droid Serif'), local('DroidSerif'), url(font/0AKsP294HTD-nvJgucYTaIbN6UDyHWBl620a-IRfuBk.woff) format('woff');
6 | }
7 |
8 | @font-face {
9 | font-family: 'Yanone Kaffeesatz';
10 | font-style: normal;
11 | font-weight: 400;
12 | src: local('Yanone Kaffeesatz Regular'), local('YanoneKaffeesatz-Regular'), url(font/YDAoLskQQ5MOAgvHUQCcLRTHiN2BPBirwIkMLKUspj4.woff) format('woff');
13 | }
14 |
15 | body {
16 | font-family: 'Droid Serif';
17 | font-size: 20px;
18 | }
19 | h1, h2, h3 {
20 | font-family: 'Yanone Kaffeesatz';
21 | font-weight: 400;
22 | margin-bottom: 0;
23 | }
24 | h1 { font-size: 4em; }
25 | h2 { font-size: 2em; }
26 | h3 { font-size: 1.6em; }
27 | .footnote {
28 | position: absolute;
29 | bottom: 3em;
30 | }
31 | li p { line-height: 1.25em; }
32 | .red { color: #fa0000; }
33 | .gray { color: #999; }
34 | .large { font-size: 2em; }
35 | .very-large { font-size: 3em; }
36 | a, a > code {
37 | color: rgb(249, 38, 114);
38 | text-decoration: none;
39 | }
40 | code {
41 | -moz-border-radius: 5px;
42 | -web-border-radius: 5px;
43 | background: #e7e8e2;
44 | border-radius: 5px;
45 | font-size: 16px;
46 | }
47 | .pull-left {
48 | float: left;
49 | width: 47%;
50 | }
51 | .pull-right {
52 | float: right;
53 | width: 47%;
54 | }
55 | .pull-right ~ p {
56 | clear: both;
57 | }
58 | #slideshow .slide .content code {
59 | font-size: 0.8em;
60 | }
61 | #slideshow .slide .content pre code {
62 | font-size: 0.9em;
63 | padding: 15px;
64 | }
65 | .inverse {
66 | background: #272822;
67 | color: #777872;
68 |
69 | }
70 | .inverse h1, .inverse h2 {
71 | color: #f3f3f3;
72 | line-height: 0.8em;
73 | }
74 |
75 | /* Slide-specific styling */
76 | #slide-inverse .footnote {
77 | bottom: 12px;
78 | left: 20px;
79 | }
80 | #slide-how .slides {
81 | font-size: 0.9em;
82 | position: absolute;
83 | top: 151px;
84 | right: 140px;
85 | }
86 | #slide-how .slides h3 {
87 | margin-top: 0.2em;
88 | }
89 | #slide-how .slides .first, #slide-how .slides .second {
90 | padding: 1px 20px;
91 | height: 90px;
92 | width: 120px;
93 | -moz-box-shadow: 0 0 10px #777;
94 | -webkit-box-shadow: 0 0 10px #777;
95 | box-shadow: 0 0 10px #777;
96 | }
97 | #slide-how .slides .first {
98 | background: #fff;
99 | position: absolute;
100 | top: 20%;
101 | left: 20%;
102 | z-index: 1;
103 | }
104 | #slide-how .slides .second {
105 | position: relative;
106 | background: #fff;
107 | z-index: 0;
108 | }
109 |
110 | /* Two-column layout */
111 | .left-column {
112 | color: #777;
113 | width: 20%;
114 | height: 92%;
115 | float: left;
116 | }
117 | .left-column h2:last-of-type, .left-column h3:last-child {
118 | color: #000;
119 | }
120 | .right-column {
121 | width: 75%;
122 | float: right;
123 | padding-top: 2em;
124 | }
125 |
126 |
127 | /* custom stuff */
128 |
129 | .larger-img img {
130 | max-width: 100%;
131 | max-height: 100%;
132 | }
133 |
134 | img {
135 | max-width: 80%;
136 | max-height: 80%;
137 | }
138 |
139 | .leftcol-large {
140 | width: 55%;
141 | float: left;
142 | }
143 |
144 | .leftcol-medium {
145 | width: 45%;
146 | float: left;
147 | }
148 |
149 | .leftcol-small {
150 | width: 35%;
151 | float: left;
152 | }
153 |
154 | .rightcol-large {
155 | width: 55%;
156 | float: right;
157 | }
158 |
159 | .rightcol-medium {
160 | width: 45%;
161 | float: right;
162 | }
163 |
164 | .rightcol-small {
165 | width: 35%;
166 | float: right;
167 | }
168 |
169 | .no-bullets ul {
170 | padding-left: 0;
171 | list-style-type: none;
172 | }
--------------------------------------------------------------------------------
/previous_presentations/dag1/agenda.md:
--------------------------------------------------------------------------------
1 | # Utkast til agenda
2 |
3 | - Hei og velkommen
4 | - Intro: Hva er funksjonell programmering
5 | - "Funksjonelle språk" finnes ikke, men språk legger til rette for funksjonell programmering i ulik grad
6 | - Høyere ordens funksjoner
7 | - dvs, komponering av funksjonalitet vha funksjoner
8 | - Immutable state
9 | - mindre kompleksitet
10 | - eksempel med Angular sin run-loop som ikke er immutable? (sammenlign med shouldComponentUpdate i react+immutable.js)
11 | - Begreper vi kommer til å bruke, som deltagerne må kjenne (veldig kort)
12 | - Closures
13 | - Lexical scoping
14 | - Monad: "Monoid in the category of endofunctors." (for LOLs)
15 | + ref: http://james-iry.blogspot.no/2009/05/brief-incomplete-and-mostly-wrong.html
16 | - Praktisk: Hvordan komme i gang med kodingen på en praktisk måte
17 |
18 | - Hva er en funksjon (i JS)
19 | + fn som objekter -> funksjoner kan ha funksjoner som "members"
20 | + `this`
21 | + prototyper
22 | + konstruktør-funksjoner
23 | + `call`, `apply`, `arguments`
24 |
25 | - Høyere ordens funksjoner
26 | - Kort: Hva er en HOF / førsteklasses funksjon
27 | - bruke lodash
28 | - the use of generic functions built on a collection-centric philosophy
29 | - Funksjon som returnerer funksjon: `makeAdder`
30 | - Funksjon som tar funksjon som arg: ??
31 | - Dekoratorer: `debounce`, `throttle`, `memoize`
32 | - State vha closures: `counter`, `timer`, `uniqeid`
33 | - Presentere `filter`, `map`, `reduce` (fra `_`)
34 | - Oppgaver
35 | + bruke `filter` til ting
36 | + bruke `map` til ting
37 | + bruke `reduce` til ting
38 | + implementere de over selv (optional)
39 |
40 | *(pause)*
41 |
42 | - Partial applicaton
43 | - Teori: Hva er dette / vise megabasic eksempel med _
44 | - Nyttig bruk: `.on('change', _.partial(fn, 'foo')`
45 | - Tips: flip
46 | - Oppgaver:
47 | - Implementere `partial` selv
48 |
49 | - Rekursjon (trenger vi denne?)
50 | + TCO kommer i ES6
51 | + Eksempel: Traversering av trær
52 | + Kode:
53 |
54 | def reverse(liste):
55 | baklengs = []
56 | for x in liste:
57 | baklengs.append(x)
58 | return baklengs
59 |
60 | def reverse(liste):
61 | if liste == []: return []
62 | else: return reverse(liste[1:]) + [liste[0]]
63 |
64 | + Oppgaver:
65 | * ???
66 |
67 | *(lunchpause)*
68 |
69 | - Tilstand
70 | - Hvorfor immutable state? Enklere å debugge og teste
71 | - Pragmatisk: alt må ikke være immutable, state har en plass
72 | - State kan komme og bite deg i ræva
73 | - Pass by reference vs pass by value
74 | - Farligheten med at andre kan modifisere shit etter at vi er ferdig med det
75 | - KJ finner eksempel, cache
76 | - Muligjør memoisering
77 | - Clone vs deepClone
78 | - object.freeze
79 | - Tips: implementere `deepFreeze`
80 | - Teknikker for å abstrahere bort state
81 | + `timer`
82 | + ???
83 | - Oppgaver:
84 | + ???
85 |
86 | - Diverse nyttige funksjoner
87 | + `pluck`
88 | + `find`
89 | + `any`, `all`
90 | + `compose`
91 | + Oppgaver:
92 | * Diverse bruk av funksjonene over
93 |
94 | *(pause)*
95 |
96 | - Idé til større del
97 | + Implementere så mye som mulig av `_` fra bunnen av
98 | + Bruk immutable.js sammen med React.js (til state, props er immutable)
99 | + Litt større ting vha Node
100 | * Presentere data fra et kult API på en ny måte? (som krever en del transformering der funksjonelle konsepter kan passe godt inn)
101 | * Se etter API som er relevant!
102 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/plugin/notes-server/notes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | reveal.js - Slide Notes
9 |
10 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | UPCOMING:
101 |
102 |
103 |
104 |
105 |
106 |
107 |
140 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/small-case/app.js:
--------------------------------------------------------------------------------
1 | var Bacon = require('baconjs');
2 | var $ = require('jquery');
3 | var _ = require('lodash');
4 |
5 | var api = require('./api.js');
6 |
7 | /*
8 | HELPER FUNCTIONS
9 |
10 | See their respective comments for clarifications
11 | */
12 |
13 | //Takes a record and produces a html string
14 | var renderRecord = function (record) {
15 | return '' +
16 | '' + record.album + '
' +
17 | ' Artist: ' + record.artist + '
' +
18 | 'Year: ' + record.year + '
' +
19 | 'Genre: ' + record.genre + '
' +
20 | '';
21 | };
22 |
23 | //Takes a recor collection and produces a html string
24 | var renderRecords = function(records) {
25 | return _.reduce(records, function(acc, record) {
26 | return acc + renderRecord(record);
27 | }, '');
28 | };
29 |
30 | //Takes a regex pattern as a string and returns a function that tests a value
31 | var testRegex = function(pattern) {
32 | return function(value) {
33 | if(!value) return false;
34 | return new RegExp(pattern, 'i').test(value);
35 | };
36 | };
37 |
38 | //Takes a record collection and a filter
39 | //Returns a filtered collection with regex matching on all fields of all records
40 | var filterRecords = function(records, recordFilter) {
41 | return _.filter(records, function(record) {
42 | return _(record).values().any(testRegex(recordFilter));
43 | });
44 | };
45 |
46 | //Takes an input-value and a valid-predicate and produces the approperiate icon
47 | var mapToInputIcon = function(input, valid) {
48 | if(!input) return '*';
49 | if(!valid) return '!';
50 | return '✔';
51 | };
52 |
53 | //Resets the form by setting all values to '' and triggering keyup
54 | var resetForm = function() {
55 | $('#add-record input').val('').trigger('keyup');
56 | };
57 |
58 | /*
59 | THIS IS WHERE YOU IMPLEMENT STUFF
60 | */
61 |
62 | //Make a convenience function to get properties from input fields
63 | var propertyFromInput = function(field) {
64 | };
65 |
66 | //Define your initial sources
67 | var recordFilter; //The current value of the filter input
68 |
69 | var album = propertyFromInput($('#album'));
70 | var artist = propertyFromInput($('#artist'));
71 | var year = propertyFromInput($('#year'));
72 | var genre = propertyFromInput($('#genre'));
73 |
74 | var add; //A stream of clicks on the add button
75 |
76 | var records; //The result of a call to the API for record collection
77 |
78 | //Make a representation of a record model
79 | var record;
80 |
81 | //Get a stream of added records
82 | //Remember to use the API!
83 | var addedRecord;
84 |
85 | //Collect all added records in a list
86 | var addedRecords;
87 |
88 | //Make a representation of all added records and all exisiting records
89 | var allRecords;
90 |
91 | //Show a spinner when loading the record collection
92 | var showLoadingRecordsSpinner;
93 |
94 | //Show an error message when fetching records fails
95 | var showLoadingRecordsError;
96 |
97 | //Define the validity of the form inputs
98 | var validAlbum; //Valid if it has a value and album does not exist already
99 | var validArtist;//Always valid if it has a value
100 | var validYear; //Valid only if it has a value and is 4 digits
101 | var validGenre; //Always valid if it has a value
102 |
103 | //Assign the correct indicator to the form input for all inputs
104 | var albumIcon;
105 |
106 | var artistIcon;
107 |
108 | var yearIcon;
109 |
110 | var genreIcon;
111 |
112 | //Assign some indicator for the validity of the whole form
113 | var validRecord;//Only valid if all fields are valid
114 |
115 | //Show a spinner while waiting for a reply from the server when adding records
116 | //Remember the observable you defined a while back for addedRecord
117 | var showAddingRecordSpinner;
118 |
119 | //Show an error if the API replies with an error
120 | var showAddingRecordError;
121 |
122 | //Finally assign all the records to the DOM
123 | //Remember to use the recordfilter!
124 | var filteredAllRecords;
--------------------------------------------------------------------------------
/_workshop/02-4-reduce.js:
--------------------------------------------------------------------------------
1 | ---
2 | layout: workshop
3 | collection: workshop
4 | title: Make new collections with reduce
5 | section: 2
6 | prev: 02-3-filter
7 | name: 02-4-reduce
8 | next: 02-5-lodash
9 | slides:
10 | info: |
11 | The last applicative functions we will look at for now is reduce.
12 | Reduce applies a function against an accumulator and each value
13 | of the array to reduce it to a single value.
14 |
15 | Reduce is different from map and filter in that it returns a value rather than a
16 | collection. However, the value could also be a collection.
17 | ---
18 |
19 | describe('reduce', function() {
20 | // As always, let's start with an example of calculating the sum of
21 | // all items in an array using a `for` loop:
22 |
23 | function sumFor(arr) {
24 | var sum = 0;
25 | for (var i = 0; i < arr.length; i++) {
26 | sum += arr[i];
27 | }
28 | return sum;
29 | }
30 |
31 | it('can be implemented with a for-loop', function() {
32 | var result = sumFor([1,2,3]);
33 | expect(result).to.equal(6);
34 | });
35 |
36 | // Using reduce it can look like this:
37 |
38 | function sum(arr) {
39 | return arr.reduce(function(acc, value){
40 |
41 | // What is returned in this function is used as `acc` for
42 | // the next iteration
43 | return acc + value;
44 |
45 | }, 0);
46 | // 0 is the starting value for `acc`
47 |
48 | // What we return on the last iteration is the result of
49 | // the reduce.
50 | }
51 |
52 | // This illustrates how reduce works:
53 |
54 | // Operation Accumulator List
55 | // + 0 1, 2, 3, 4
56 | // 1 2, 3, 4
57 | // 3 3, 4
58 | // 6 4
59 | // 10
60 |
61 | it('exists as a method on arrays in JavaScript', function() {
62 | var result = sum([1,2,3,4]);
63 | expect(result).to.equal(10);
64 | });
65 |
66 | it('hands the values in the collection to the reducing-function', function() {
67 | var result = sum([0,0,-1]);
68 | expect(result).to.equal(-1);
69 | });
70 |
71 | });
72 |
73 | // PROBLEM: Implement multiplication using reduce
74 |
75 | function multiply(arr) {
76 | }
77 |
78 | describe('multiply', function() {
79 |
80 | it('does multiply all the numbers in the collection', function() {
81 | var result = multiply([1,2,3,4]);
82 | expect(result).to.equal(24);
83 | });
84 |
85 | it('does work as expected when 0 appears in the collection', function() {
86 | var result = multiply([0,1,2,3]);
87 | expect(result).to.equal(0);
88 | });
89 | });
90 |
91 | // We don't always need to specify the initial value, i.e. `0` in `sum`
92 | // above. If we don't specify an initial value, the first item is used as
93 | // the initial value, and the first round with `reduce` is therefore with
94 | // the first and second item.
95 |
96 | // PROBLEM: Implement join using reduce without specifying an initial value
97 |
98 | function join(arr, chr) {
99 | }
100 |
101 | describe('join', function() {
102 |
103 | it('works correctly with only one element', function() {
104 | var result = join(["a"], ":");
105 | expect(result).to.equal("a");
106 | });
107 |
108 | it('works correctly with multiple elements', function() {
109 | var result = join(["a","b","c"], ":");
110 | expect(result).to.equal("a:b:c");
111 | });
112 |
113 | });
114 |
115 | // PROBLEM: Implement find using reduce
116 | // (think about what we want to get back from such a function)
117 |
118 | function find(arr, el) {
119 | }
120 |
121 | describe('find', function() {
122 |
123 | it('should return true if element exists in the array', function() {
124 | var result = find([1,2,3], 1);
125 | expect(result).to.be.ok;
126 | });
127 |
128 | it('should return false if element does not exist in the array', function() {
129 | var result = find([1,2,3], 4);
130 | expect(result).to.not.be.ok;
131 | });
132 |
133 | it('should return false if given an empty collection', function() {
134 | var result = find([], 1);
135 | expect(result).to.not.be.ok;
136 | });
137 | });
138 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/css/theme/night.css:
--------------------------------------------------------------------------------
1 | @import url(https://fonts.googleapis.com/css?family=Montserrat:700);
2 | @import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic,700italic);
3 | /**
4 | * Black theme for reveal.js.
5 | *
6 | * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
7 | */
8 | /*********************************************
9 | * GLOBAL STYLES
10 | *********************************************/
11 | body {
12 | background: #111111;
13 | background-color: #111111; }
14 |
15 | .reveal {
16 | font-family: "Open Sans", sans-serif;
17 | font-size: 30px;
18 | font-weight: 200;
19 | letter-spacing: -0.02em;
20 | color: #eeeeee; }
21 |
22 | ::selection {
23 | color: white;
24 | background: #e7ad52;
25 | text-shadow: none; }
26 |
27 | /*********************************************
28 | * HEADERS
29 | *********************************************/
30 | .reveal h1,
31 | .reveal h2,
32 | .reveal h3,
33 | .reveal h4,
34 | .reveal h5,
35 | .reveal h6 {
36 | margin: 0 0 20px 0;
37 | color: #eeeeee;
38 | font-family: "Montserrat", Impact, sans-serif;
39 | line-height: 0.9em;
40 | letter-spacing: -0.03em;
41 | text-transform: none;
42 | text-shadow: none; }
43 |
44 | .reveal h1 {
45 | text-shadow: 0px 0px 6px rgba(0, 0, 0, 0.2); }
46 |
47 | /*********************************************
48 | * LINKS
49 | *********************************************/
50 | .reveal a:not(.image) {
51 | color: #e7ad52;
52 | text-decoration: none;
53 | -webkit-transition: color .15s ease;
54 | -moz-transition: color .15s ease;
55 | -ms-transition: color .15s ease;
56 | -o-transition: color .15s ease;
57 | transition: color .15s ease; }
58 |
59 | .reveal a:not(.image):hover {
60 | color: #f3d7ac;
61 | text-shadow: none;
62 | border: none; }
63 |
64 | .reveal .roll span:after {
65 | color: #fff;
66 | background: #d08a1d; }
67 |
68 | /*********************************************
69 | * IMAGES
70 | *********************************************/
71 | .reveal section img {
72 | margin: 15px 0px;
73 | background: rgba(255, 255, 255, 0.12);
74 | border: 4px solid #eeeeee;
75 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
76 | -webkit-transition: all .2s linear;
77 | -moz-transition: all .2s linear;
78 | -ms-transition: all .2s linear;
79 | -o-transition: all .2s linear;
80 | transition: all .2s linear; }
81 |
82 | .reveal a:hover img {
83 | background: rgba(255, 255, 255, 0.2);
84 | border-color: #e7ad52;
85 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); }
86 |
87 | /*********************************************
88 | * NAVIGATION CONTROLS
89 | *********************************************/
90 | .reveal .controls div.navigate-left,
91 | .reveal .controls div.navigate-left.enabled {
92 | border-right-color: #e7ad52; }
93 |
94 | .reveal .controls div.navigate-right,
95 | .reveal .controls div.navigate-right.enabled {
96 | border-left-color: #e7ad52; }
97 |
98 | .reveal .controls div.navigate-up,
99 | .reveal .controls div.navigate-up.enabled {
100 | border-bottom-color: #e7ad52; }
101 |
102 | .reveal .controls div.navigate-down,
103 | .reveal .controls div.navigate-down.enabled {
104 | border-top-color: #e7ad52; }
105 |
106 | .reveal .controls div.navigate-left.enabled:hover {
107 | border-right-color: #f3d7ac; }
108 |
109 | .reveal .controls div.navigate-right.enabled:hover {
110 | border-left-color: #f3d7ac; }
111 |
112 | .reveal .controls div.navigate-up.enabled:hover {
113 | border-bottom-color: #f3d7ac; }
114 |
115 | .reveal .controls div.navigate-down.enabled:hover {
116 | border-top-color: #f3d7ac; }
117 |
118 | /*********************************************
119 | * PROGRESS BAR
120 | *********************************************/
121 | .reveal .progress {
122 | background: rgba(0, 0, 0, 0.2); }
123 |
124 | .reveal .progress span {
125 | background: #e7ad52;
126 | -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
127 | -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
128 | -ms-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
129 | -o-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
130 | transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
131 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/css/theme/serif.css:
--------------------------------------------------------------------------------
1 | /**
2 | * A simple theme for reveal.js presentations, similar
3 | * to the default theme. The accent color is brown.
4 | *
5 | * This theme is Copyright (C) 2012-2013 Owen Versteeg, http://owenversteeg.com - it is MIT licensed.
6 | */
7 | .reveal a:not(.image) {
8 | line-height: 1.3em; }
9 |
10 | /*********************************************
11 | * GLOBAL STYLES
12 | *********************************************/
13 | body {
14 | background: #f0f1eb;
15 | background-color: #f0f1eb; }
16 |
17 | .reveal {
18 | font-family: "Palatino Linotype", "Book Antiqua", Palatino, FreeSerif, serif;
19 | font-size: 36px;
20 | font-weight: 200;
21 | letter-spacing: -0.02em;
22 | color: black; }
23 |
24 | ::selection {
25 | color: white;
26 | background: #26351c;
27 | text-shadow: none; }
28 |
29 | /*********************************************
30 | * HEADERS
31 | *********************************************/
32 | .reveal h1,
33 | .reveal h2,
34 | .reveal h3,
35 | .reveal h4,
36 | .reveal h5,
37 | .reveal h6 {
38 | margin: 0 0 20px 0;
39 | color: #383d3d;
40 | font-family: "Palatino Linotype", "Book Antiqua", Palatino, FreeSerif, serif;
41 | line-height: 0.9em;
42 | letter-spacing: 0.02em;
43 | text-transform: none;
44 | text-shadow: none; }
45 |
46 | .reveal h1 {
47 | text-shadow: 0px 0px 6px rgba(0, 0, 0, 0.2); }
48 |
49 | /*********************************************
50 | * LINKS
51 | *********************************************/
52 | .reveal a:not(.image) {
53 | color: #51483d;
54 | text-decoration: none;
55 | -webkit-transition: color .15s ease;
56 | -moz-transition: color .15s ease;
57 | -ms-transition: color .15s ease;
58 | -o-transition: color .15s ease;
59 | transition: color .15s ease; }
60 |
61 | .reveal a:not(.image):hover {
62 | color: #8b7c69;
63 | text-shadow: none;
64 | border: none; }
65 |
66 | .reveal .roll span:after {
67 | color: #fff;
68 | background: #25211c; }
69 |
70 | /*********************************************
71 | * IMAGES
72 | *********************************************/
73 | .reveal section img {
74 | margin: 15px 0px;
75 | background: rgba(255, 255, 255, 0.12);
76 | border: 4px solid black;
77 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
78 | -webkit-transition: all .2s linear;
79 | -moz-transition: all .2s linear;
80 | -ms-transition: all .2s linear;
81 | -o-transition: all .2s linear;
82 | transition: all .2s linear; }
83 |
84 | .reveal a:hover img {
85 | background: rgba(255, 255, 255, 0.2);
86 | border-color: #51483d;
87 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); }
88 |
89 | /*********************************************
90 | * NAVIGATION CONTROLS
91 | *********************************************/
92 | .reveal .controls div.navigate-left,
93 | .reveal .controls div.navigate-left.enabled {
94 | border-right-color: #51483d; }
95 |
96 | .reveal .controls div.navigate-right,
97 | .reveal .controls div.navigate-right.enabled {
98 | border-left-color: #51483d; }
99 |
100 | .reveal .controls div.navigate-up,
101 | .reveal .controls div.navigate-up.enabled {
102 | border-bottom-color: #51483d; }
103 |
104 | .reveal .controls div.navigate-down,
105 | .reveal .controls div.navigate-down.enabled {
106 | border-top-color: #51483d; }
107 |
108 | .reveal .controls div.navigate-left.enabled:hover {
109 | border-right-color: #8b7c69; }
110 |
111 | .reveal .controls div.navigate-right.enabled:hover {
112 | border-left-color: #8b7c69; }
113 |
114 | .reveal .controls div.navigate-up.enabled:hover {
115 | border-bottom-color: #8b7c69; }
116 |
117 | .reveal .controls div.navigate-down.enabled:hover {
118 | border-top-color: #8b7c69; }
119 |
120 | /*********************************************
121 | * PROGRESS BAR
122 | *********************************************/
123 | .reveal .progress {
124 | background: rgba(0, 0, 0, 0.2); }
125 |
126 | .reveal .progress span {
127 | background: #51483d;
128 | -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
129 | -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
130 | -ms-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
131 | -o-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
132 | transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
133 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/css/theme/template/theme.scss:
--------------------------------------------------------------------------------
1 | // Base theme template for reveal.js
2 |
3 | /*********************************************
4 | * GLOBAL STYLES
5 | *********************************************/
6 |
7 | body {
8 | @include bodyBackground();
9 | background-color: $backgroundColor;
10 | }
11 |
12 | .reveal {
13 | font-family: $mainFont;
14 | font-size: $mainFontSize;
15 | font-weight: 200;
16 | letter-spacing: -0.02em;
17 | color: $mainColor;
18 | }
19 |
20 | ::selection {
21 | color: $selectionColor;
22 | background: $selectionBackgroundColor;
23 | text-shadow: none;
24 | }
25 |
26 | /*********************************************
27 | * HEADERS
28 | *********************************************/
29 |
30 | .reveal h1,
31 | .reveal h2,
32 | .reveal h3,
33 | .reveal h4,
34 | .reveal h5,
35 | .reveal h6 {
36 | margin: $headingMargin;
37 | color: $headingColor;
38 |
39 | font-family: $headingFont;
40 | line-height: $headingLineHeight;
41 | letter-spacing: $headingLetterSpacing;
42 |
43 | text-transform: $headingTextTransform;
44 | text-shadow: $headingTextShadow;
45 | }
46 |
47 | .reveal h1 {
48 | text-shadow: $heading1TextShadow;
49 | }
50 |
51 |
52 | /*********************************************
53 | * LINKS
54 | *********************************************/
55 |
56 | .reveal a:not(.image) {
57 | color: $linkColor;
58 | text-decoration: none;
59 |
60 | -webkit-transition: color .15s ease;
61 | -moz-transition: color .15s ease;
62 | -ms-transition: color .15s ease;
63 | -o-transition: color .15s ease;
64 | transition: color .15s ease;
65 | }
66 | .reveal a:not(.image):hover {
67 | color: $linkColorHover;
68 |
69 | text-shadow: none;
70 | border: none;
71 | }
72 |
73 | .reveal .roll span:after {
74 | color: #fff;
75 | background: darken( $linkColor, 15% );
76 | }
77 |
78 |
79 | /*********************************************
80 | * IMAGES
81 | *********************************************/
82 |
83 | .reveal section img {
84 | margin: 15px 0px;
85 | background: rgba(255,255,255,0.12);
86 | border: 4px solid $mainColor;
87 |
88 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
89 |
90 | -webkit-transition: all .2s linear;
91 | -moz-transition: all .2s linear;
92 | -ms-transition: all .2s linear;
93 | -o-transition: all .2s linear;
94 | transition: all .2s linear;
95 | }
96 |
97 | .reveal a:hover img {
98 | background: rgba(255,255,255,0.2);
99 | border-color: $linkColor;
100 |
101 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55);
102 | }
103 |
104 |
105 | /*********************************************
106 | * NAVIGATION CONTROLS
107 | *********************************************/
108 |
109 | .reveal .controls div.navigate-left,
110 | .reveal .controls div.navigate-left.enabled {
111 | border-right-color: $linkColor;
112 | }
113 |
114 | .reveal .controls div.navigate-right,
115 | .reveal .controls div.navigate-right.enabled {
116 | border-left-color: $linkColor;
117 | }
118 |
119 | .reveal .controls div.navigate-up,
120 | .reveal .controls div.navigate-up.enabled {
121 | border-bottom-color: $linkColor;
122 | }
123 |
124 | .reveal .controls div.navigate-down,
125 | .reveal .controls div.navigate-down.enabled {
126 | border-top-color: $linkColor;
127 | }
128 |
129 | .reveal .controls div.navigate-left.enabled:hover {
130 | border-right-color: $linkColorHover;
131 | }
132 |
133 | .reveal .controls div.navigate-right.enabled:hover {
134 | border-left-color: $linkColorHover;
135 | }
136 |
137 | .reveal .controls div.navigate-up.enabled:hover {
138 | border-bottom-color: $linkColorHover;
139 | }
140 |
141 | .reveal .controls div.navigate-down.enabled:hover {
142 | border-top-color: $linkColorHover;
143 | }
144 |
145 |
146 | /*********************************************
147 | * PROGRESS BAR
148 | *********************************************/
149 |
150 | .reveal .progress {
151 | background: rgba(0,0,0,0.2);
152 | }
153 | .reveal .progress span {
154 | background: $linkColor;
155 |
156 | -webkit-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
157 | -moz-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
158 | -ms-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
159 | -o-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
160 | transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
161 | }
162 |
163 |
164 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/css/theme/simple.css:
--------------------------------------------------------------------------------
1 | @import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700);
2 | @import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
3 | /**
4 | * A simple theme for reveal.js presentations, similar
5 | * to the default theme. The accent color is darkblue.
6 | *
7 | * This theme is Copyright (C) 2012 Owen Versteeg, https://github.com/StereotypicalApps. It is MIT licensed.
8 | * reveal.js is Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
9 | */
10 | /*********************************************
11 | * GLOBAL STYLES
12 | *********************************************/
13 | body {
14 | background: white;
15 | background-color: white; }
16 |
17 | .reveal {
18 | font-family: "Lato", sans-serif;
19 | font-size: 36px;
20 | font-weight: 200;
21 | letter-spacing: -0.02em;
22 | color: black; }
23 |
24 | ::selection {
25 | color: white;
26 | background: rgba(0, 0, 0, 0.99);
27 | text-shadow: none; }
28 |
29 | /*********************************************
30 | * HEADERS
31 | *********************************************/
32 | .reveal h1,
33 | .reveal h2,
34 | .reveal h3,
35 | .reveal h4,
36 | .reveal h5,
37 | .reveal h6 {
38 | margin: 0 0 20px 0;
39 | color: black;
40 | font-family: "News Cycle", Impact, sans-serif;
41 | line-height: 0.9em;
42 | letter-spacing: 0.02em;
43 | text-transform: none;
44 | text-shadow: none; }
45 |
46 | .reveal h1 {
47 | text-shadow: 0px 0px 6px rgba(0, 0, 0, 0.2); }
48 |
49 | /*********************************************
50 | * LINKS
51 | *********************************************/
52 | .reveal a:not(.image) {
53 | color: darkblue;
54 | text-decoration: none;
55 | -webkit-transition: color .15s ease;
56 | -moz-transition: color .15s ease;
57 | -ms-transition: color .15s ease;
58 | -o-transition: color .15s ease;
59 | transition: color .15s ease; }
60 |
61 | .reveal a:not(.image):hover {
62 | color: #0000f1;
63 | text-shadow: none;
64 | border: none; }
65 |
66 | .reveal .roll span:after {
67 | color: #fff;
68 | background: #00003f; }
69 |
70 | /*********************************************
71 | * IMAGES
72 | *********************************************/
73 | .reveal section img {
74 | margin: 15px 0px;
75 | background: rgba(255, 255, 255, 0.12);
76 | border: 4px solid black;
77 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
78 | -webkit-transition: all .2s linear;
79 | -moz-transition: all .2s linear;
80 | -ms-transition: all .2s linear;
81 | -o-transition: all .2s linear;
82 | transition: all .2s linear; }
83 |
84 | .reveal a:hover img {
85 | background: rgba(255, 255, 255, 0.2);
86 | border-color: darkblue;
87 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); }
88 |
89 | /*********************************************
90 | * NAVIGATION CONTROLS
91 | *********************************************/
92 | .reveal .controls div.navigate-left,
93 | .reveal .controls div.navigate-left.enabled {
94 | border-right-color: darkblue; }
95 |
96 | .reveal .controls div.navigate-right,
97 | .reveal .controls div.navigate-right.enabled {
98 | border-left-color: darkblue; }
99 |
100 | .reveal .controls div.navigate-up,
101 | .reveal .controls div.navigate-up.enabled {
102 | border-bottom-color: darkblue; }
103 |
104 | .reveal .controls div.navigate-down,
105 | .reveal .controls div.navigate-down.enabled {
106 | border-top-color: darkblue; }
107 |
108 | .reveal .controls div.navigate-left.enabled:hover {
109 | border-right-color: #0000f1; }
110 |
111 | .reveal .controls div.navigate-right.enabled:hover {
112 | border-left-color: #0000f1; }
113 |
114 | .reveal .controls div.navigate-up.enabled:hover {
115 | border-bottom-color: #0000f1; }
116 |
117 | .reveal .controls div.navigate-down.enabled:hover {
118 | border-top-color: #0000f1; }
119 |
120 | /*********************************************
121 | * PROGRESS BAR
122 | *********************************************/
123 | .reveal .progress {
124 | background: rgba(0, 0, 0, 0.2); }
125 |
126 | .reveal .progress span {
127 | background: darkblue;
128 | -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
129 | -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
130 | -ms-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
131 | -o-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
132 | transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
133 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/big-case/style/reset.less:
--------------------------------------------------------------------------------
1 | /* Reset.less
2 | * Props to Eric Meyer (meyerweb.com) for his CSS reset file. We're using an adapted version here that cuts out some of the reset HTML elements we will never need here (i.e., dfn, samp, etc).
3 | * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
4 |
5 |
6 | // ERIC MEYER RESET
7 | // --------------------------------------------------
8 |
9 | html, body { margin: 0; padding: 0; }
10 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, cite, code, del, dfn, em, img, q, s, samp, small, strike, strong, sub, sup, tt, var, dd, dl, dt, li, ol, ul, fieldset, form, label, legend, button, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; font-weight: normal; font-style: normal; font-size: 100%; line-height: 1; font-family: inherit; }
11 | table { border-collapse: collapse; border-spacing: 0; }
12 | ol, ul { list-style: none; }
13 | q:before, q:after, blockquote:before, blockquote:after { content: ""; }
14 |
15 |
16 | // Normalize.css
17 | // Pulling in select resets form the normalize.css project
18 | // --------------------------------------------------
19 |
20 | // Display in IE6-9 and FF3
21 | // -------------------------
22 | // Source: http://github.com/necolas/normalize.css
23 | html {
24 | overflow-y: scroll;
25 | font-size: 100%;
26 | -webkit-text-size-adjust: 100%;
27 | -ms-text-size-adjust: 100%;
28 | }
29 | // Focus states
30 | a:focus {
31 | outline: thin dotted;
32 | }
33 | // Hover & Active
34 | a:hover,
35 | a:active {
36 | outline: 0;
37 | }
38 |
39 | // Display in IE6-9 and FF3
40 | // -------------------------
41 | // Source: http://github.com/necolas/normalize.css
42 | article,
43 | aside,
44 | details,
45 | figcaption,
46 | figure,
47 | footer,
48 | header,
49 | hgroup,
50 | nav,
51 | section {
52 | display: block;
53 | }
54 |
55 | // Display block in IE6-9 and FF3
56 | // -------------------------
57 | // Source: http://github.com/necolas/normalize.css
58 | audio,
59 | canvas,
60 | video {
61 | display: inline-block;
62 | *display: inline;
63 | *zoom: 1;
64 | }
65 |
66 | // Prevents modern browsers from displaying 'audio' without controls
67 | // -------------------------
68 | // Source: http://github.com/necolas/normalize.css
69 | audio:not([controls]) {
70 | display: none;
71 | }
72 |
73 | // Prevents sub and sup affecting line-height in all browsers
74 | // -------------------------
75 | // Source: http://github.com/necolas/normalize.css
76 | sub,
77 | sup {
78 | font-size: 75%;
79 | line-height: 0;
80 | position: relative;
81 | vertical-align: baseline;
82 | }
83 | sup {
84 | top: -0.5em;
85 | }
86 | sub {
87 | bottom: -0.25em;
88 | }
89 |
90 | // Img border in a's and image quality
91 | // -------------------------
92 | // Source: http://github.com/necolas/normalize.css
93 | img {
94 | border: 0;
95 | -ms-interpolation-mode: bicubic;
96 | }
97 |
98 | // Forms
99 | // -------------------------
100 | // Source: http://github.com/necolas/normalize.css
101 |
102 | // Font size in all browsers, margin changes, misc consistency
103 | button,
104 | input,
105 | select,
106 | textarea {
107 | font-size: 100%;
108 | margin: 0;
109 | vertical-align: baseline;
110 | *vertical-align: middle;
111 | }
112 | button,
113 | input {
114 | line-height: normal; // FF3/4 have !important on line-height in UA stylesheet
115 | *overflow: visible; // Inner spacing ie IE6/7
116 | }
117 | button::-moz-focus-inner,
118 | input::-moz-focus-inner { // Inner padding and border oddities in FF3/4
119 | border: 0;
120 | padding: 0;
121 | }
122 | button,
123 | input[type="button"],
124 | input[type="reset"],
125 | input[type="submit"] {
126 | cursor: pointer; // Cursors on all buttons applied consistently
127 | -webkit-appearance: button; // Style clicable inputs in iOS
128 | }
129 | input[type="search"] { // Appearance in Safari/Chrome
130 | -webkit-appearance: textfield;
131 | -webkit-box-sizing: content-box;
132 | -moz-box-sizing: content-box;
133 | box-sizing: content-box;
134 | }
135 | input[type="search"]::-webkit-search-decoration {
136 | -webkit-appearance: none; // Inner-padding issues in Chrome OSX, Safari 5
137 | }
138 | textarea {
139 | overflow: auto; // Remove vertical scrollbar in IE6-9
140 | vertical-align: top; // Readability and alignment cross-browser
141 | }
--------------------------------------------------------------------------------
/_workshop/04-2-functions-from-functions.js:
--------------------------------------------------------------------------------
1 | ---
2 | layout: workshop
3 | collection: workshop
4 | title: Create functions from functions
5 | section: 4
6 | prev: 04-1-partial-application
7 | name: 04-2-functions-from-functions
8 | next: 05-1-currying
9 | slides:
10 | info:
11 | ---
12 | // Okey, let's keep playing with partial application. The thing about map,
13 | // filter and reduce is that we often have a "static" function as the last
14 | // parameter, and a "dynamic" input that is applied to the function. Take
15 | // for example this function:
16 |
17 | function square(arr) {
18 | return _.map(arr, function(val) {
19 | return val * val;
20 | });
21 | }
22 |
23 | describe('square', function() {
24 | it('should square numbers', function() {
25 | var result = square([1,2,3]);
26 | expect(result).to.deep.equal([1,4,9]);
27 | });
28 | });
29 |
30 | // With partial application this can also be written like this:
31 | var partialSquare = _.partialRight(_.map, function(val) {
32 | return val * val;
33 | });
34 |
35 | describe('partialSquare', function() {
36 | it('should square numbers like square', function() {
37 | var result = partialSquare([1,2,3]);
38 | expect(result).to.deep.equal([1,4,9]);
39 | });
40 | });
41 |
42 | // Note that we never specify the array argument in `square2`, but we need to
43 | // specify it in `square` (where it's named `arr`). Again, point-free style.
44 |
45 | // PROBLEM: Use _.partialRight to create a function that filters
46 | // all odd values from an array
47 |
48 | var onlyEven = null;
49 |
50 | describe('onlyEven', function() {
51 | it('should only return even numbers', function() {
52 | var result = onlyEven([1,2,3,4,5]);
53 | expect(result).to.deep.equal([2,4]);
54 | });
55 | });
56 |
57 | // Above we needed to use _.partialRight to create our function based on
58 | // `map` and `filter`. As we touched upon you often want to work in the
59 | // opposite direction of the direction specified by Lo-Dash and
60 | // Underscore.js -- that is, we want to partially apply the last parameter,
61 | // the function, first. So, let's create a function that works the other way
62 | // around:
63 |
64 | function mapWith(fn, arr) {
65 | return _.map(arr, fn);
66 | };
67 |
68 | var mapWithSquare = _.partial(mapWith, function(val) {
69 | return val * val;
70 | });
71 |
72 | describe('mapWithSquare', function() {
73 | it('should square numbers', function() {
74 | var result = mapWithSquare([1,2,3]);
75 | expect(result).to.deep.equal([1,4,9]);
76 | });
77 | });
78 |
79 | // PROBLEM: Use `mapWith` and `_.partial` to create a function that adds
80 | // the current index to the current value:
81 |
82 | var plusIndex = null;
83 | describe('plusIndex', function() {
84 | it('should add index to number', function() {
85 | var result = plusIndex([1,2,3]);
86 | expect(result).to.deep.equal([1,3,5]);
87 | });
88 | });
89 |
90 | // But damn, it would be nice to get away from these call to _.partial! In
91 | // order to get there, let's first do a small generalization then we'll take a
92 | // look at a another powerful technique.
93 |
94 | // So, first the generalization: Instead of flipping the arguments ourselves as
95 | // we did in `mapWith` above we can create a flip method which flips the two
96 | // arguments on the passed function:
97 |
98 | function flip(fn) {
99 | return function(first, second) {
100 | return fn.call(this, second, first);
101 | };
102 | };
103 | // We can use this function to create a new `mapWith`:
104 |
105 | var flippedMapWith = flip(_.map);
106 |
107 | // And then, as above:
108 |
109 | var flippedMapWithSquare = _.partial(flippedMapWith, function(val) {
110 | return val * val;
111 | });
112 |
113 |
114 | describe('flippedMapWithSquare', function() {
115 | it('should square numbers', function() {
116 | var result = flippedMapWithSquare([1,2,3]);
117 | expect(result).to.deep.equal([1,4,9]);
118 | });
119 | });
120 |
121 | // PROBLEM: Use flip to create a parseInt that applies in the other
122 | // direction, i.e. the base first. Then partially apply it to create
123 | // parseDigit. (Because flip only works on two arguments, we don't need to
124 | // think about the unary stuff we did earlier.)
125 |
126 | var parseDigit = null;
127 |
128 | var parseDigits = _.partial(mapWith, parseDigit);
129 |
130 | describe('parseDigits', function() {
131 | it('should properly parse digits', function() {
132 | var result = parseDigits(['123', '08', '001']);
133 | expect(result).to.deep.equal([123, 8, 1]);
134 | });
135 | });
136 |
--------------------------------------------------------------------------------
/previous_presentations/dag2/slides/css/theme/moon.css:
--------------------------------------------------------------------------------
1 | @import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
2 | /**
3 | * Solarized Dark theme for reveal.js.
4 | * Author: Achim Staebler
5 | */
6 | @font-face {
7 | font-family: 'League Gothic';
8 | src: url("../../lib/font/league_gothic-webfont.eot");
9 | src: url("../../lib/font/league_gothic-webfont.eot?#iefix") format("embedded-opentype"), url("../../lib/font/league_gothic-webfont.woff") format("woff"), url("../../lib/font/league_gothic-webfont.ttf") format("truetype"), url("../../lib/font/league_gothic-webfont.svg#LeagueGothicRegular") format("svg");
10 | font-weight: normal;
11 | font-style: normal; }
12 |
13 | /**
14 | * Solarized colors by Ethan Schoonover
15 | */
16 | html * {
17 | color-profile: sRGB;
18 | rendering-intent: auto; }
19 |
20 | /*********************************************
21 | * GLOBAL STYLES
22 | *********************************************/
23 | body {
24 | background: #002b36;
25 | background-color: #002b36; }
26 |
27 | .reveal {
28 | font-family: "Lato", sans-serif;
29 | font-size: 36px;
30 | font-weight: 200;
31 | letter-spacing: -0.02em;
32 | color: #93a1a1; }
33 |
34 | ::selection {
35 | color: white;
36 | background: #d33682;
37 | text-shadow: none; }
38 |
39 | /*********************************************
40 | * HEADERS
41 | *********************************************/
42 | .reveal h1,
43 | .reveal h2,
44 | .reveal h3,
45 | .reveal h4,
46 | .reveal h5,
47 | .reveal h6 {
48 | margin: 0 0 20px 0;
49 | color: #eee8d5;
50 | font-family: "League Gothic", Impact, sans-serif;
51 | line-height: 0.9em;
52 | letter-spacing: 0.02em;
53 | text-transform: uppercase;
54 | text-shadow: none; }
55 |
56 | .reveal h1 {
57 | text-shadow: 0px 0px 6px rgba(0, 0, 0, 0.2); }
58 |
59 | /*********************************************
60 | * LINKS
61 | *********************************************/
62 | .reveal a:not(.image) {
63 | color: #268bd2;
64 | text-decoration: none;
65 | -webkit-transition: color .15s ease;
66 | -moz-transition: color .15s ease;
67 | -ms-transition: color .15s ease;
68 | -o-transition: color .15s ease;
69 | transition: color .15s ease; }
70 |
71 | .reveal a:not(.image):hover {
72 | color: #78b9e6;
73 | text-shadow: none;
74 | border: none; }
75 |
76 | .reveal .roll span:after {
77 | color: #fff;
78 | background: #1a6091; }
79 |
80 | /*********************************************
81 | * IMAGES
82 | *********************************************/
83 | .reveal section img {
84 | margin: 15px 0px;
85 | background: rgba(255, 255, 255, 0.12);
86 | border: 4px solid #93a1a1;
87 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
88 | -webkit-transition: all .2s linear;
89 | -moz-transition: all .2s linear;
90 | -ms-transition: all .2s linear;
91 | -o-transition: all .2s linear;
92 | transition: all .2s linear; }
93 |
94 | .reveal a:hover img {
95 | background: rgba(255, 255, 255, 0.2);
96 | border-color: #268bd2;
97 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); }
98 |
99 | /*********************************************
100 | * NAVIGATION CONTROLS
101 | *********************************************/
102 | .reveal .controls div.navigate-left,
103 | .reveal .controls div.navigate-left.enabled {
104 | border-right-color: #268bd2; }
105 |
106 | .reveal .controls div.navigate-right,
107 | .reveal .controls div.navigate-right.enabled {
108 | border-left-color: #268bd2; }
109 |
110 | .reveal .controls div.navigate-up,
111 | .reveal .controls div.navigate-up.enabled {
112 | border-bottom-color: #268bd2; }
113 |
114 | .reveal .controls div.navigate-down,
115 | .reveal .controls div.navigate-down.enabled {
116 | border-top-color: #268bd2; }
117 |
118 | .reveal .controls div.navigate-left.enabled:hover {
119 | border-right-color: #78b9e6; }
120 |
121 | .reveal .controls div.navigate-right.enabled:hover {
122 | border-left-color: #78b9e6; }
123 |
124 | .reveal .controls div.navigate-up.enabled:hover {
125 | border-bottom-color: #78b9e6; }
126 |
127 | .reveal .controls div.navigate-down.enabled:hover {
128 | border-top-color: #78b9e6; }
129 |
130 | /*********************************************
131 | * PROGRESS BAR
132 | *********************************************/
133 | .reveal .progress {
134 | background: rgba(0, 0, 0, 0.2); }
135 |
136 | .reveal .progress span {
137 | background: #268bd2;
138 | -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
139 | -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
140 | -ms-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
141 | -o-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
142 | transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
143 |
--------------------------------------------------------------------------------