Added Android Lightning Talk for DevICT

This commit is contained in:
Brian Buller 2016-02-24 13:43:02 -06:00
parent eb66761baf
commit 61e0307a88
21 changed files with 2447 additions and 0 deletions

153
2016/02/android.slide Normal file
View File

@ -0,0 +1,153 @@
Android
February 25, 2016
Brian Buller
Buller Codeworks, LLC
* Generally
Native Android is Java...
* Generally
Native Android is Java...
but I'm not talking about that
* Android Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.application"
android:versionCode="3"
android:versionName="1.2" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
android:theme="@android:style/Theme.Holo.Light" >
<activity android:name=".FeedListActivity"
android:label="@string/app_name"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
...
</application>
</manifest>
* Permissions
- Sandboxed Applications
- Normal Permissions
The permission must be declared, but the system automatically grants access
- Dangerous Permissions
The user must grant permission
- Changes in Android 6
- List of permissions and severity at [[http://developer.android.com/guide/topics/security/permissions.html]]
* Permissions Example
- Declared in manifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- Request at run time
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
* Intents
- Declare in manifest
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
- Call in code
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_TEXT, alert_message);
shareIntent.setType("text/plain");
startActivity(shareIntent);
* Activities
Main Activity (icon in launcher)
<activity android:name=".FeedListActivity"
android:label="@string/app_name"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Other Activities
<activity android:name=".FeedDetailActivity"
android:label="@string/app_name"
android:launchMode="singleInstance">
</activity>
* Application Lifecycle
General Lifecycle
- Resumed
The activity has the user focus (aka - Running)
- Paused
Another activity is in the foreground, but this one is still visisble.
A Paused activity is fully alive but can be killed by the system in extremely
low-memory situations.
- Stopped
The activity is completely obscured by another activity. The activity is still alive,
but no longer visible and can be killed if memory is needed elsewhere.
* Application Lifecycle
Functions
- onCreate - The activity is being created
- onStart - The activity is about to become visible
- onResume - The activity has become visible
- onPause - Another activity is taking focus
- onStop - The activity is no longer visible
- onDestroy - The activity is about to be destroyed
Those are all overrides and you *must* hit the overridden function before doing any work in them.
* Layout Files
<LinearLayout
android:id="@+id/layout_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView android:id="@+id/layout_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Text"
android:textSize="25dip" />
<Button android:id="@+id/layout_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button Text" />
<LinearLayout android:id="@+id/list_wrapper"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView android:id="@+id/list_view"
android:listSelector="#00000000"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
* Notes
The slides are available on [[http://gogs.bullercodeworks.com/brian/talks/2016/02/android.slide]]

15
app.yaml Normal file
View File

@ -0,0 +1,15 @@
application: Android Lightning Talk
version: 1
runtime: go
api_version: go1
handlers:
- url: /favicon.ico
static_files: present/static/favicon.ico
upload: present/static/favicon.ico
- url: /static
static_dir: present/static
application_readable: true
- url: /.*
script: _go_app

22
appengine.go Normal file
View File

@ -0,0 +1,22 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build appengine
package main
import (
"mime"
"golang.org/x/tools/present"
)
func init() {
initTemplates("./present/")
present.PlayEnabled = true
initPlayground("./present/", nil)
// App Engine has no /etc/mime.types
mime.AddExtensionType(".svg", "image/svg+xml")
}

213
dir.go Normal file
View File

@ -0,0 +1,213 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"html/template"
"io"
"log"
"net/http"
"os"
"path/filepath"
"sort"
"golang.org/x/tools/present"
)
func init() {
http.HandleFunc("/", dirHandler)
}
// dirHandler serves a directory listing for the requested path, rooted at basePath.
func dirHandler(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/favicon.ico" {
http.Error(w, "not found", 404)
return
}
const base = "."
name := filepath.Join(base, r.URL.Path)
if isDoc(name) {
err := renderDoc(w, name)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), 500)
}
return
}
if isDir, err := dirList(w, name); err != nil {
log.Println(err)
http.Error(w, err.Error(), 500)
return
} else if isDir {
return
}
http.FileServer(http.Dir(base)).ServeHTTP(w, r)
}
func isDoc(path string) bool {
_, ok := contentTemplate[filepath.Ext(path)]
return ok
}
var (
// dirListTemplate holds the front page template.
dirListTemplate *template.Template
// contentTemplate maps the presentable file extensions to the
// template to be executed.
contentTemplate map[string]*template.Template
)
func initTemplates(base string) error {
// Locate the template file.
actionTmpl := filepath.Join(base, "templates/action.tmpl")
contentTemplate = make(map[string]*template.Template)
for ext, contentTmpl := range map[string]string{
".slide": "slides.tmpl",
".article": "article.tmpl",
} {
contentTmpl = filepath.Join(base, "templates", contentTmpl)
// Read and parse the input.
tmpl := present.Template()
tmpl = tmpl.Funcs(template.FuncMap{"playable": playable})
if _, err := tmpl.ParseFiles(actionTmpl, contentTmpl); err != nil {
return err
}
contentTemplate[ext] = tmpl
}
var err error
dirListTemplate, err = template.ParseFiles(filepath.Join(base, "templates/dir.tmpl"))
if err != nil {
return err
}
return nil
}
// renderDoc reads the present file, gets its template representation,
// and executes the template, sending output to w.
func renderDoc(w io.Writer, docFile string) error {
// Read the input and build the doc structure.
doc, err := parse(docFile, 0)
if err != nil {
return err
}
// Find which template should be executed.
tmpl := contentTemplate[filepath.Ext(docFile)]
// Execute the template.
return doc.Render(w, tmpl)
}
func parse(name string, mode present.ParseMode) (*present.Doc, error) {
f, err := os.Open(name)
if err != nil {
return nil, err
}
defer f.Close()
return present.Parse(f, name, 0)
}
// dirList scans the given path and writes a directory listing to w.
// It parses the first part of each .slide file it encounters to display the
// presentation title in the listing.
// If the given path is not a directory, it returns (isDir == false, err == nil)
// and writes nothing to w.
func dirList(w io.Writer, name string) (isDir bool, err error) {
f, err := os.Open(name)
if err != nil {
return false, err
}
defer f.Close()
fi, err := f.Stat()
if err != nil {
return false, err
}
if isDir = fi.IsDir(); !isDir {
return false, nil
}
fis, err := f.Readdir(0)
if err != nil {
return false, err
}
d := &dirListData{Path: name}
for _, fi := range fis {
// skip the golang.org directory
if name == "." && fi.Name() == "golang.org" {
continue
}
e := dirEntry{
Name: fi.Name(),
Path: filepath.ToSlash(filepath.Join(name, fi.Name())),
}
if fi.IsDir() && showDir(e.Name) {
d.Dirs = append(d.Dirs, e)
continue
}
if isDoc(e.Name) {
if p, err := parse(e.Path, present.TitlesOnly); err != nil {
log.Println(err)
} else {
e.Title = p.Title
}
switch filepath.Ext(e.Path) {
case ".article":
d.Articles = append(d.Articles, e)
case ".slide":
d.Slides = append(d.Slides, e)
}
} else if showFile(e.Name) {
d.Other = append(d.Other, e)
}
}
if d.Path == "." {
d.Path = ""
}
sort.Sort(d.Dirs)
sort.Sort(d.Slides)
sort.Sort(d.Articles)
sort.Sort(d.Other)
return true, dirListTemplate.Execute(w, d)
}
// showFile reports whether the given file should be displayed in the list.
func showFile(n string) bool {
switch filepath.Ext(n) {
case ".pdf":
case ".html":
case ".go":
default:
return isDoc(n)
}
return true
}
// showDir reports whether the given directory should be displayed in the list.
func showDir(n string) bool {
if len(n) > 0 && (n[0] == '.' || n[0] == '_') || n == "present" {
return false
}
return true
}
type dirListData struct {
Path string
Dirs, Slides, Articles, Other dirEntrySlice
}
type dirEntry struct {
Name, Path, Title string
}
type dirEntrySlice []dirEntry
func (s dirEntrySlice) Len() int { return len(s) }
func (s dirEntrySlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s dirEntrySlice) Less(i, j int) bool { return s[i].Name < s[j].Name }

56
doc.go Normal file
View File

@ -0,0 +1,56 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Present displays slide presentations and articles. It runs a web server that
presents slide and article files from the current directory.
It may be run as a stand-alone command or an App Engine app.
Usage of present:
-base="": base path for slide template and static resources
-http="127.0.0.1:3999": HTTP service address (e.g., '127.0.0.1:3999')
-nacl=false: use Native Client environment playground (prevents non-Go code execution)
-orighost="": host component of web origin URL (e.g., 'localhost')
-play=true: enable playground (permit execution of arbitrary user code)
The setup of the Go version of NaCl is documented at:
https://golang.org/wiki/NativeClient
To use with App Engine, copy the tools/cmd/present directory to the root of
your application and create an app.yaml file similar to this:
application: [application]
version: [version]
runtime: go
api_version: go1
handlers:
- url: /favicon.ico
static_files: present/static/favicon.ico
upload: present/static/favicon.ico
- url: /static
static_dir: present/static
application_readable: true
- url: /.*
script: _go_app
# nobuild_files is a regexp that identifies which files to not build. It
# is useful for embedding static assets like code snippets and preventing
# them from producing build errors for your project.
nobuild_files: [path regexp for talk materials]
Present then can be tested in a local App Engine environment with
goapp serve
Input files are named foo.extension, where "extension" defines the format of
the generated output. The supported formats are:
.slide // HTML5 slide presentation
.article // article format, such as a blog post
The present file format is documented by the present package:
http://godoc.org/golang.org/x/tools/present
*/
package main // import "golang.org/x/tools/cmd/present"

129
local.go Normal file
View File

@ -0,0 +1,129 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !appengine
package main
import (
"flag"
"fmt"
"go/build"
"log"
"net"
"net/http"
"net/url"
"os"
"strings"
"golang.org/x/tools/present"
)
const basePkg = "golang.org/x/tools/cmd/present"
var (
httpAddr = flag.String("http", "127.0.0.1:3999", "HTTP service address (e.g., '127.0.0.1:3999')")
originHost = flag.String("orighost", "", "host component of web origin URL (e.g., 'localhost')")
basePath = flag.String("base", "", "base path for slide template and static resources")
nativeClient = flag.Bool("nacl", false, "use Native Client environment playground (prevents non-Go code execution)")
)
func main() {
flag.BoolVar(&present.PlayEnabled, "play", true, "enable playground (permit execution of arbitrary user code)")
flag.Parse()
if *basePath == "" {
p, err := build.Default.Import(basePkg, "", build.FindOnly)
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't find gopresent files: %v\n", err)
fmt.Fprintf(os.Stderr, basePathMessage, basePkg)
os.Exit(1)
}
*basePath = p.Dir
}
err := initTemplates(*basePath)
if err != nil {
log.Fatalf("Failed to parse templates: %v", err)
}
ln, err := net.Listen("tcp", *httpAddr)
if err != nil {
log.Fatal(err)
}
defer ln.Close()
_, port, err := net.SplitHostPort(ln.Addr().String())
if err != nil {
log.Fatal(err)
}
origin := &url.URL{Scheme: "http"}
if *originHost != "" {
origin.Host = net.JoinHostPort(*originHost, port)
} else if ln.Addr().(*net.TCPAddr).IP.IsUnspecified() {
name, _ := os.Hostname()
origin.Host = net.JoinHostPort(name, port)
} else {
reqHost, reqPort, err := net.SplitHostPort(*httpAddr)
if err != nil {
log.Fatal(err)
}
if reqPort == "0" {
origin.Host = net.JoinHostPort(reqHost, port)
} else {
origin.Host = *httpAddr
}
}
initPlayground(*basePath, origin)
http.Handle("/static/", http.FileServer(http.Dir(*basePath)))
if !ln.Addr().(*net.TCPAddr).IP.IsLoopback() &&
present.PlayEnabled && !*nativeClient {
log.Print(localhostWarning)
}
log.Printf("Open your web browser and visit %s", origin.String())
log.Fatal(http.Serve(ln, nil))
}
func environ(vars ...string) []string {
env := os.Environ()
for _, r := range vars {
k := strings.SplitAfter(r, "=")[0]
var found bool
for i, v := range env {
if strings.HasPrefix(v, k) {
env[i] = r
found = true
}
}
if !found {
env = append(env, r)
}
}
return env
}
const basePathMessage = `
By default, gopresent locates the slide template files and associated
static content by looking for a %q package
in your Go workspaces (GOPATH).
You may use the -base flag to specify an alternate location.
`
const localhostWarning = `
WARNING! WARNING! WARNING!
The present server appears to be listening on an address that is not localhost.
Anyone with access to this address and port will have access to this machine as
the user running present.
To avoid this message, listen on localhost or run with -play=false.
If you don't understand this message, hit Control-C to terminate this process.
WARNING! WARNING! WARNING!
`

43
play.go Normal file
View File

@ -0,0 +1,43 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"path/filepath"
"time"
"golang.org/x/tools/godoc/static"
)
var scripts = []string{"jquery.js", "jquery-ui.js", "playground.js", "play.js"}
// playScript registers an HTTP handler at /play.js that serves all the
// scripts specified by the variable above, and appends a line that
// initializes the playground with the specified transport.
func playScript(root, transport string) {
modTime := time.Now()
var buf bytes.Buffer
for _, p := range scripts {
if s, ok := static.Files[p]; ok {
buf.WriteString(s)
continue
}
b, err := ioutil.ReadFile(filepath.Join(root, "static", p))
if err != nil {
panic(err)
}
buf.Write(b)
}
fmt.Fprintf(&buf, "\ninitPlayground(new %v());\n", transport)
b := buf.Bytes()
http.HandleFunc("/play.js", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-type", "application/javascript")
http.ServeContent(w, r, "", modTime, bytes.NewReader(b))
})
}

23
play_http.go Normal file
View File

@ -0,0 +1,23 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build appengine appenginevm
package main
import (
"net/url"
"golang.org/x/tools/present"
_ "golang.org/x/tools/playground"
)
func initPlayground(basepath string, origin *url.URL) {
playScript(basepath, "HTTPTransport")
}
func playable(c present.Code) bool {
return present.PlayEnabled && c.Play && c.Ext == ".go"
}

36
play_socket.go Normal file
View File

@ -0,0 +1,36 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !appengine,!appenginevm
package main
import (
"net/http"
"net/url"
"runtime"
"golang.org/x/tools/playground/socket"
"golang.org/x/tools/present"
)
func initPlayground(basepath string, origin *url.URL) {
if present.PlayEnabled {
if *nativeClient {
socket.RunScripts = false
socket.Environ = func() []string {
if runtime.GOARCH == "amd64" {
return environ("GOOS=nacl", "GOARCH=amd64p32")
}
return environ("GOOS=nacl")
}
}
playScript(basepath, "SocketTransport")
http.Handle("/socket", socket.NewHandler(origin))
}
}
func playable(c present.Code) bool {
return present.PlayEnabled && c.Play
}

136
static/article.css Normal file
View File

@ -0,0 +1,136 @@
body {
margin: 0;
font-family: Helvetica, Arial, sans-serif;
font-size: 16px;
}
pre,
code {
font-family: Menlo, monospace;
font-size: 14px;
}
pre {
line-height: 18px;
margin: 0;
padding: 0;
}
a {
color: #375EAB;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
p, ul, ol {
margin: 20px;
}
h1, h2, h3, h4 {
margin: 20px 0;
padding: 0;
color: #375EAB;
font-weight: bold;
}
h1 {
font-size: 24px;
}
h2 {
font-size: 20px;
background: #E0EBF5;
padding: 2px 5px;
}
h3 {
font-size: 20px;
}
h3, h4 {
margin: 20px 5px;
}
h4 {
font-size: 16px;
}
div#heading {
float: left;
margin: 0 0 10px 0;
padding: 21px 0;
font-size: 20px;
font-weight: normal;
}
div#topbar {
background: #E0EBF5;
height: 64px;
overflow: hidden;
}
body {
text-align: center;
}
div#page {
width: 100%;
}
div#page > .container,
div#topbar > .container {
text-align: left;
margin-left: auto;
margin-right: auto;
padding: 0 20px;
width: 900px;
}
div#page.wide > .container,
div#topbar.wide > .container {
width: auto;
}
div#footer {
text-align: center;
color: #666;
font-size: 14px;
margin: 40px 0;
}
.author p {
margin: 20, 0, 0, 0px;
}
div.code,
div.output {
margin: 20px;
padding: 10px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
div.code { background: #e9e9e9; }
div.output { background: black; }
div.output .stdout { color: #e6e6e6; }
div.output .stderr { color: rgb(244, 74, 63); }
div.output .system { color: rgb(255, 209, 77) }
.buttons {
margin-left: 20px;
}
div.output .buttons {
margin-left: 0;
margin-bottom: 10px;
}
#toc {
float: right;
margin: 0px 10px;
padding: 10px;
border: 1px solid #e5ecf9;
background-color: white;
max-width: 33%;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
#toc ul, #toc a {
list-style-type: none;
padding-left: 10px;
color: black;
margin: 0px;
}

186
static/dir.css Normal file
View File

@ -0,0 +1,186 @@
/* copied from $GOROOT/doc/style.css */
body {
margin: 0;
font-family: Helvetica, Arial, sans-serif;
font-size: 16px;
}
pre,
code {
font-family: Menlo, monospace;
font-size: 14px;
}
pre {
line-height: 18px;
}
pre .comment {
color: #375EAB;
}
pre .highlight,
pre .highlight-comment,
pre .selection-highlight,
pre .selection-highlight-comment {
background: #FFFF00;
}
pre .selection,
pre .selection-comment {
background: #FF9632;
}
pre .ln {
color: #999;
}
body {
color: #222;
}
a,
.exampleHeading .text {
color: #375EAB;
text-decoration: none;
}
a:hover,
.exampleHeading .text:hover {
text-decoration: underline;
}
p,
pre,
ul,
ol {
margin: 20px;
}
pre {
background: #e9e9e9;
padding: 10px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
h1,
h2,
h3,
h4,
.rootHeading {
margin: 20px 0;
padding: 0;
color: #375EAB;
font-weight: bold;
}
h1 {
font-size: 24px;
}
h2 {
font-size: 20px;
background: #E0EBF5;
padding: 2px 5px;
}
h3 {
font-size: 20px;
}
h3,
h4 {
margin: 20px 5px;
}
h4 {
font-size: 16px;
}
dl {
margin: 20px;
}
dd {
margin: 2px 20px;
}
dl,
dd {
font-size: 14px;
}
div#nav table td {
vertical-align: top;
}
div#heading {
float: left;
margin: 0 0 10px 0;
padding: 21px 0;
font-size: 20px;
font-weight: normal;
}
div#heading a {
color: #222;
text-decoration: none;
}
div#topbar {
background: #E0EBF5;
height: 64px;
}
body {
text-align: center;
}
div#page,
div#topbar > .container {
clear: both;
text-align: left;
margin-left: auto;
margin-right: auto;
padding: 0 20px;
width: 900px;
}
div#page.wide,
div#topbar > .wide {
width: auto;
}
div#plusone {
float: right;
}
div#footer {
color: #666;
font-size: 14px;
margin: 40px 0;
}
div#menu > a,
div#menu > input {
padding: 10px;
text-decoration: none;
font-size: 16px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
div#menu > a,
div#menu > input {
border: 1px solid #375EAB;
}
div#menu > a {
color: white;
background: #375EAB;
}
div#menu {
float: right;
min-width: 590px;
padding: 10px 0;
text-align: right;
}
div#menu > a {
margin-right: 5px;
margin-bottom: 10px;
padding: 10px;
}
div#menu > input {
position: relative;
top: 1px;
width: 60px;
background: white;
color: #222;
}
div#menu > input.inactive {
color: #999;
}

41
static/dir.js Normal file
View File

@ -0,0 +1,41 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// copied from $GOROOT/doc/godocs.js
function bindEvent(el, e, fn) {
if (el.addEventListener){
el.addEventListener(e, fn, false);
} else if (el.attachEvent){
el.attachEvent('on'+e, fn);
}
}
function godocs_bindSearchEvents() {
var search = document.getElementById('search');
if (!search) {
// no search box (index disabled)
return;
}
function clearInactive() {
if (search.className == "inactive") {
search.value = "";
search.className = "";
}
}
function restoreInactive() {
if (search.value !== "") {
return;
}
if (search.type != "search") {
search.value = search.getAttribute("placeholder");
}
search.className = "inactive";
}
restoreInactive();
bindEvent(search, 'focus', clearInactive);
bindEvent(search, 'blur', restoreInactive);
}
bindEvent(window, 'load', godocs_bindSearchEvents);

BIN
static/favicon.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

BIN
static/go-favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 785 B

6
static/jquery-ui.js vendored Normal file

File diff suppressed because one or more lines are too long

526
static/slides.js Normal file
View File

@ -0,0 +1,526 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
var PERMANENT_URL_PREFIX = '/static/';
var SLIDE_CLASSES = ['far-past', 'past', 'current', 'next', 'far-next'];
var PM_TOUCH_SENSITIVITY = 15;
var curSlide;
/* ---------------------------------------------------------------------- */
/* classList polyfill by Eli Grey
* (http://purl.eligrey.com/github/classList.js/blob/master/classList.js) */
if (typeof document !== "undefined" && !("classList" in document.createElement("a"))) {
(function (view) {
var
classListProp = "classList"
, protoProp = "prototype"
, elemCtrProto = (view.HTMLElement || view.Element)[protoProp]
, objCtr = Object
strTrim = String[protoProp].trim || function () {
return this.replace(/^\s+|\s+$/g, "");
}
, arrIndexOf = Array[protoProp].indexOf || function (item) {
for (var i = 0, len = this.length; i < len; i++) {
if (i in this && this[i] === item) {
return i;
}
}
return -1;
}
// Vendors: please allow content code to instantiate DOMExceptions
, DOMEx = function (type, message) {
this.name = type;
this.code = DOMException[type];
this.message = message;
}
, checkTokenAndGetIndex = function (classList, token) {
if (token === "") {
throw new DOMEx(
"SYNTAX_ERR"
, "An invalid or illegal string was specified"
);
}
if (/\s/.test(token)) {
throw new DOMEx(
"INVALID_CHARACTER_ERR"
, "String contains an invalid character"
);
}
return arrIndexOf.call(classList, token);
}
, ClassList = function (elem) {
var
trimmedClasses = strTrim.call(elem.className)
, classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []
;
for (var i = 0, len = classes.length; i < len; i++) {
this.push(classes[i]);
}
this._updateClassName = function () {
elem.className = this.toString();
};
}
, classListProto = ClassList[protoProp] = []
, classListGetter = function () {
return new ClassList(this);
}
;
// Most DOMException implementations don't allow calling DOMException's toString()
// on non-DOMExceptions. Error's toString() is sufficient here.
DOMEx[protoProp] = Error[protoProp];
classListProto.item = function (i) {
return this[i] || null;
};
classListProto.contains = function (token) {
token += "";
return checkTokenAndGetIndex(this, token) !== -1;
};
classListProto.add = function (token) {
token += "";
if (checkTokenAndGetIndex(this, token) === -1) {
this.push(token);
this._updateClassName();
}
};
classListProto.remove = function (token) {
token += "";
var index = checkTokenAndGetIndex(this, token);
if (index !== -1) {
this.splice(index, 1);
this._updateClassName();
}
};
classListProto.toggle = function (token) {
token += "";
if (checkTokenAndGetIndex(this, token) === -1) {
this.add(token);
} else {
this.remove(token);
}
};
classListProto.toString = function () {
return this.join(" ");
};
if (objCtr.defineProperty) {
var classListPropDesc = {
get: classListGetter
, enumerable: true
, configurable: true
};
try {
objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
} catch (ex) { // IE 8 doesn't support enumerable:true
if (ex.number === -0x7FF5EC54) {
classListPropDesc.enumerable = false;
objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
}
}
} else if (objCtr[protoProp].__defineGetter__) {
elemCtrProto.__defineGetter__(classListProp, classListGetter);
}
}(self));
}
/* ---------------------------------------------------------------------- */
/* Slide movement */
function hideHelpText() {
$('#help').hide();
};
function getSlideEl(no) {
if ((no < 0) || (no >= slideEls.length)) {
return null;
} else {
return slideEls[no];
}
};
function updateSlideClass(slideNo, className) {
var el = getSlideEl(slideNo);
if (!el) {
return;
}
if (className) {
el.classList.add(className);
}
for (var i in SLIDE_CLASSES) {
if (className != SLIDE_CLASSES[i]) {
el.classList.remove(SLIDE_CLASSES[i]);
}
}
};
function updateSlides() {
if (window.trackPageview) window.trackPageview();
for (var i = 0; i < slideEls.length; i++) {
switch (i) {
case curSlide - 2:
updateSlideClass(i, 'far-past');
break;
case curSlide - 1:
updateSlideClass(i, 'past');
break;
case curSlide:
updateSlideClass(i, 'current');
break;
case curSlide + 1:
updateSlideClass(i, 'next');
break;
case curSlide + 2:
updateSlideClass(i, 'far-next');
break;
default:
updateSlideClass(i);
break;
}
}
triggerLeaveEvent(curSlide - 1);
triggerEnterEvent(curSlide);
window.setTimeout(function() {
// Hide after the slide
disableSlideFrames(curSlide - 2);
}, 301);
enableSlideFrames(curSlide - 1);
enableSlideFrames(curSlide + 2);
updateHash();
};
function prevSlide() {
hideHelpText();
if (curSlide > 0) {
curSlide--;
updateSlides();
}
};
function nextSlide() {
hideHelpText();
if (curSlide < slideEls.length - 1) {
curSlide++;
updateSlides();
}
};
/* Slide events */
function triggerEnterEvent(no) {
var el = getSlideEl(no);
if (!el) {
return;
}
var onEnter = el.getAttribute('onslideenter');
if (onEnter) {
new Function(onEnter).call(el);
}
var evt = document.createEvent('Event');
evt.initEvent('slideenter', true, true);
evt.slideNumber = no + 1; // Make it readable
el.dispatchEvent(evt);
};
function triggerLeaveEvent(no) {
var el = getSlideEl(no);
if (!el) {
return;
}
var onLeave = el.getAttribute('onslideleave');
if (onLeave) {
new Function(onLeave).call(el);
}
var evt = document.createEvent('Event');
evt.initEvent('slideleave', true, true);
evt.slideNumber = no + 1; // Make it readable
el.dispatchEvent(evt);
};
/* Touch events */
function handleTouchStart(event) {
if (event.touches.length == 1) {
touchDX = 0;
touchDY = 0;
touchStartX = event.touches[0].pageX;
touchStartY = event.touches[0].pageY;
document.body.addEventListener('touchmove', handleTouchMove, true);
document.body.addEventListener('touchend', handleTouchEnd, true);
}
};
function handleTouchMove(event) {
if (event.touches.length > 1) {
cancelTouch();
} else {
touchDX = event.touches[0].pageX - touchStartX;
touchDY = event.touches[0].pageY - touchStartY;
event.preventDefault();
}
};
function handleTouchEnd(event) {
var dx = Math.abs(touchDX);
var dy = Math.abs(touchDY);
if ((dx > PM_TOUCH_SENSITIVITY) && (dy < (dx * 2 / 3))) {
if (touchDX > 0) {
prevSlide();
} else {
nextSlide();
}
}
cancelTouch();
};
function cancelTouch() {
document.body.removeEventListener('touchmove', handleTouchMove, true);
document.body.removeEventListener('touchend', handleTouchEnd, true);
};
/* Preloading frames */
function disableSlideFrames(no) {
var el = getSlideEl(no);
if (!el) {
return;
}
var frames = el.getElementsByTagName('iframe');
for (var i = 0, frame; frame = frames[i]; i++) {
disableFrame(frame);
}
};
function enableSlideFrames(no) {
var el = getSlideEl(no);
if (!el) {
return;
}
var frames = el.getElementsByTagName('iframe');
for (var i = 0, frame; frame = frames[i]; i++) {
enableFrame(frame);
}
};
function disableFrame(frame) {
frame.src = 'about:blank';
};
function enableFrame(frame) {
var src = frame._src;
if (frame.src != src && src != 'about:blank') {
frame.src = src;
}
};
function setupFrames() {
var frames = document.querySelectorAll('iframe');
for (var i = 0, frame; frame = frames[i]; i++) {
frame._src = frame.src;
disableFrame(frame);
}
enableSlideFrames(curSlide);
enableSlideFrames(curSlide + 1);
enableSlideFrames(curSlide + 2);
};
function setupInteraction() {
/* Clicking and tapping */
var el = document.createElement('div');
el.className = 'slide-area';
el.id = 'prev-slide-area';
el.addEventListener('click', prevSlide, false);
document.querySelector('section.slides').appendChild(el);
var el = document.createElement('div');
el.className = 'slide-area';
el.id = 'next-slide-area';
el.addEventListener('click', nextSlide, false);
document.querySelector('section.slides').appendChild(el);
/* Swiping */
document.body.addEventListener('touchstart', handleTouchStart, false);
}
/* Hash functions */
function getCurSlideFromHash() {
var slideNo = parseInt(location.hash.substr(1));
if (slideNo) {
curSlide = slideNo - 1;
} else {
curSlide = 0;
}
};
function updateHash() {
location.replace('#' + (curSlide + 1));
};
/* Event listeners */
function handleBodyKeyDown(event) {
// If we're in a code element, only handle pgup/down.
var inCode = event.target.classList.contains("code");
switch (event.keyCode) {
case 72: // 'H' hides the help text
case 27: // escape key
if (!inCode) hideHelpText();
break;
case 39: // right arrow
case 13: // Enter
case 32: // space
if (inCode) break;
case 34: // PgDn
nextSlide();
event.preventDefault();
break;
case 37: // left arrow
case 8: // Backspace
if (inCode) break;
case 33: // PgUp
prevSlide();
event.preventDefault();
break;
case 40: // down arrow
if (inCode) break;
nextSlide();
event.preventDefault();
break;
case 38: // up arrow
if (inCode) break;
prevSlide();
event.preventDefault();
break;
}
};
function addEventListeners() {
document.addEventListener('keydown', handleBodyKeyDown, false);
};
/* Initialization */
function addFontStyle() {
var el = document.createElement('link');
el.rel = 'stylesheet';
el.type = 'text/css';
el.href = '//fonts.googleapis.com/css?family=' +
'Open+Sans:regular,semibold,italic,italicsemibold|Droid+Sans+Mono';
document.body.appendChild(el);
};
function addGeneralStyle() {
var el = document.createElement('link');
el.rel = 'stylesheet';
el.type = 'text/css';
el.href = PERMANENT_URL_PREFIX + 'styles.css';
document.body.appendChild(el);
var el = document.createElement('meta');
el.name = 'viewport';
el.content = 'width=1100,height=750';
document.querySelector('head').appendChild(el);
var el = document.createElement('meta');
el.name = 'apple-mobile-web-app-capable';
el.content = 'yes';
document.querySelector('head').appendChild(el);
};
function showHelpText() {
};
function handleDomLoaded() {
slideEls = document.querySelectorAll('section.slides > article');
setupFrames();
addFontStyle();
addGeneralStyle();
addEventListeners();
updateSlides();
setupInteraction();
if (window.location.hostname == "localhost" || window.location.hostname == "127.0.0.1" || window.location.hostname == "::1") {
hideHelpText();
}
document.body.classList.add('loaded');
};
function initialize() {
getCurSlideFromHash();
if (window['_DEBUG']) {
PERMANENT_URL_PREFIX = '../';
}
if (window['_DCL']) {
handleDomLoaded();
} else {
document.addEventListener('DOMContentLoaded', handleDomLoaded, false);
}
}
// If ?debug exists then load the script relative instead of absolute
if (!window['_DEBUG'] && document.location.href.indexOf('?debug') !== -1) {
document.addEventListener('DOMContentLoaded', function() {
// Avoid missing the DomContentLoaded event
window['_DCL'] = true
}, false);
window['_DEBUG'] = true;
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = '../slides.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(script, s);
// Remove this script
s.parentNode.removeChild(s);
} else {
initialize();
}

523
static/styles.css Normal file
View File

@ -0,0 +1,523 @@
@media screen {
/* Framework */
html {
height: 100%;
}
body {
margin: 0;
padding: 0;
display: block !important;
height: 100%;
min-height: 740px;
overflow-x: hidden;
overflow-y: auto;
background: rgb(215, 215, 215);
background: -o-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
background: -moz-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
background: -webkit-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 500, from(rgb(240, 240, 240)), to(rgb(190, 190, 190)));
-webkit-font-smoothing: antialiased;
}
.slides {
width: 100%;
height: 100%;
left: 0;
top: 0;
position: absolute;
-webkit-transform: translate3d(0, 0, 0);
}
.slides > article {
display: block;
position: absolute;
overflow: hidden;
width: 900px;
height: 700px;
left: 50%;
top: 50%;
margin-left: -450px;
margin-top: -350px;
padding: 40px 60px;
box-sizing: border-box;
-o-box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
border-radius: 10px;
-o-border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
background-color: white;
border: 1px solid rgba(0, 0, 0, .3);
transition: transform .3s ease-out;
-o-transition: -o-transform .3s ease-out;
-moz-transition: -moz-transform .3s ease-out;
-webkit-transition: -webkit-transform .3s ease-out;
}
.slides.layout-widescreen > article {
margin-left: -550px;
width: 1100px;
}
.slides.layout-faux-widescreen > article {
margin-left: -550px;
width: 1100px;
padding: 40px 160px;
}
.slides.layout-widescreen > article:not(.nobackground):not(.biglogo),
.slides.layout-faux-widescreen > article:not(.nobackground):not(.biglogo) {
background-position-x: 0, 840px;
}
/* Clickable/tappable areas */
.slide-area {
z-index: 1000;
position: absolute;
left: 0;
top: 0;
width: 150px;
height: 700px;
left: 50%;
top: 50%;
cursor: pointer;
margin-top: -350px;
tap-highlight-color: transparent;
-o-tap-highlight-color: transparent;
-moz-tap-highlight-color: transparent;
-webkit-tap-highlight-color: transparent;
}
#prev-slide-area {
margin-left: -550px;
}
#next-slide-area {
margin-left: 400px;
}
.slides.layout-widescreen #prev-slide-area,
.slides.layout-faux-widescreen #prev-slide-area {
margin-left: -650px;
}
.slides.layout-widescreen #next-slide-area,
.slides.layout-faux-widescreen #next-slide-area {
margin-left: 500px;
}
/* Slides */
.slides > article {
display: none;
}
.slides > article.far-past {
display: block;
transform: translate(-2040px);
-o-transform: translate(-2040px);
-moz-transform: translate(-2040px);
-webkit-transform: translate3d(-2040px, 0, 0);
}
.slides > article.past {
display: block;
transform: translate(-1020px);
-o-transform: translate(-1020px);
-moz-transform: translate(-1020px);
-webkit-transform: translate3d(-1020px, 0, 0);
}
.slides > article.current {
display: block;
transform: translate(0);
-o-transform: translate(0);
-moz-transform: translate(0);
-webkit-transform: translate3d(0, 0, 0);
}
.slides > article.next {
display: block;
transform: translate(1020px);
-o-transform: translate(1020px);
-moz-transform: translate(1020px);
-webkit-transform: translate3d(1020px, 0, 0);
}
.slides > article.far-next {
display: block;
transform: translate(2040px);
-o-transform: translate(2040px);
-moz-transform: translate(2040px);
-webkit-transform: translate3d(2040px, 0, 0);
}
.slides.layout-widescreen > article.far-past,
.slides.layout-faux-widescreen > article.far-past {
display: block;
transform: translate(-2260px);
-o-transform: translate(-2260px);
-moz-transform: translate(-2260px);
-webkit-transform: translate3d(-2260px, 0, 0);
}
.slides.layout-widescreen > article.past,
.slides.layout-faux-widescreen > article.past {
display: block;
transform: translate(-1130px);
-o-transform: translate(-1130px);
-moz-transform: translate(-1130px);
-webkit-transform: translate3d(-1130px, 0, 0);
}
.slides.layout-widescreen > article.current,
.slides.layout-faux-widescreen > article.current {
display: block;
transform: translate(0);
-o-transform: translate(0);
-moz-transform: translate(0);
-webkit-transform: translate3d(0, 0, 0);
}
.slides.layout-widescreen > article.next,
.slides.layout-faux-widescreen > article.next {
display: block;
transform: translate(1130px);
-o-transform: translate(1130px);
-moz-transform: translate(1130px);
-webkit-transform: translate3d(1130px, 0, 0);
}
.slides.layout-widescreen > article.far-next,
.slides.layout-faux-widescreen > article.far-next {
display: block;
transform: translate(2260px);
-o-transform: translate(2260px);
-moz-transform: translate(2260px);
-webkit-transform: translate3d(2260px, 0, 0);
}
}
@media print {
/* Set page layout */
@page {
size: A4 landscape;
}
body {
display: block !important;
}
.slides > article {
display: block;
position: relative;
page-break-inside: never;
page-break-after: always;
overflow: hidden;
}
h2 {
position: static !important;
margin-top: 400px !important;
margin-bottom: 100px !important;
}
div.code {
background: rgb(240, 240, 240);
}
/* Add explicit links */
a:link:after, a:visited:after {
content: " (" attr(href) ") ";
font-size: 50%;
}
#help {
display: none;
visibility: hidden;
}
}
/* Styles for slides */
.slides > article {
font-family: 'Open Sans', Arial, sans-serif;
color: black;
text-shadow: 0 1px 1px rgba(0, 0, 0, .1);
font-size: 26px;
line-height: 36px;
letter-spacing: -1px;
}
b {
font-weight: 600;
}
a {
color: rgb(0, 102, 204);
text-decoration: none;
}
a:visited {
color: rgba(0, 102, 204, .75);
}
a:hover {
color: black;
}
p {
margin: 0;
padding: 0;
margin-top: 20px;
}
p:first-child {
margin-top: 0;
}
h1 {
font-size: 60px;
line-height: 60px;
padding: 0;
margin: 0;
margin-top: 200px;
margin-bottom: 5px;
padding-right: 40px;
font-weight: 600;
letter-spacing: -3px;
color: rgb(51, 51, 51);
}
h2 {
font-size: 45px;
line-height: 45px;
position: absolute;
bottom: 150px;
padding: 0;
margin: 0;
padding-right: 40px;
font-weight: 600;
letter-spacing: -2px;
color: rgb(51, 51, 51);
}
h3 {
font-size: 30px;
line-height: 36px;
padding: 0;
margin: 0;
padding-right: 40px;
font-weight: 600;
letter-spacing: -1px;
color: rgb(51, 51, 51);
}
ul {
margin: 0;
padding: 0;
margin-top: 20px;
margin-left: 1.5em;
}
li {
padding: 0;
margin: 0 0 .5em 0;
}
div.code {
padding: 5px 10px;
margin-top: 20px;
margin-bottom: 20px;
overflow: hidden;
background: rgb(240, 240, 240);
border: 1px solid rgb(224, 224, 224);
}
pre {
margin: 0;
padding: 0;
font-family: 'Droid Sans Mono', 'Courier New', monospace;
font-size: 18px;
line-height: 24px;
letter-spacing: -1px;
color: black;
}
code {
font-size: 95%;
font-family: 'Droid Sans Mono', 'Courier New', monospace;
color: black;
}
article > .image {
text-align: center;
margin-top: 40px;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 40px;
}
th {
font-weight: 600;
text-align: left;
}
td,
th {
border: 1px solid rgb(224, 224, 224);
padding: 5px 10px;
vertical-align: top;
}
p.link {
margin-left: 20px;
}
/* Code */
div.code {
outline: 0px solid transparent;
}
div.playground {
position: relative;
}
div.output {
position: absolute;
left: 50%;
top: 50%;
right: 40px;
bottom: 40px;
background: #202020;
padding: 5px 10px;
z-index: 2;
border-radius: 10px;
-o-border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
}
div.output pre {
margin: 0;
padding: 0;
background: none;
border: none;
width: 100%;
height: 100%;
overflow: auto;
}
div.output .stdout, div.output pre {
color: #e6e6e6;
}
div.output .stderr, div.output .error {
color: rgb(255, 200, 200);
}
div.output .system, div.output .exit {
color: rgb(255, 230, 120)
}
.buttons {
position: relative;
float: right;
top: -60px;
right: 10px;
}
div.output .buttons {
position: absolute;
float: none;
top: auto;
right: 5px;
bottom: 5px;
}
/* Presenter details */
.presenter {
margin-top: 20px;
}
.presenter p,
.presenter .link {
margin: 0;
font-size: 28px;
line-height: 1.2em;
}
/* Output resize details */
.ui-resizable-handle {
position: absolute;
}
.ui-resizable-n {
cursor: n-resize;
height: 7px;
width: 100%;
top: -5px;
left: 0;
}
.ui-resizable-w {
cursor: w-resize;
width: 7px;
left: -5px;
top: 0;
height: 100%;
}
.ui-resizable-nw {
cursor: nw-resize;
width: 9px;
height: 9px;
left: -5px;
top: -5px;
}
iframe {
border: none;
}
figcaption {
color: #666;
text-align: center;
font-size: 0.75em;
}
#help {
font-family: 'Open Sans', Arial, sans-serif;
text-align: center;
color: white;
background: #000;
opacity: 0.5;
position: fixed;
bottom: 25px;
left: 50px;
right: 50px;
padding: 20px;
border-radius: 10px;
-o-border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
}

48
templates/action.tmpl Normal file
View File

@ -0,0 +1,48 @@
{/*
This is the action template.
It determines how the formatting actions are rendered.
*/}
{{define "section"}}
<h{{len .Number}} id="TOC_{{.FormattedNumber}}">{{.FormattedNumber}} {{.Title}}</h{{len .Number}}>
{{range .Elem}}{{elem $.Template .}}{{end}}
{{end}}
{{define "list"}}
<ul>
{{range .Bullet}}
<li>{{style .}}</li>
{{end}}
</ul>
{{end}}
{{define "text"}}
{{if .Pre}}
<div class="code"><pre>{{range .Lines}}{{.}}{{end}}</pre></div>
{{else}}
<p>
{{range $i, $l := .Lines}}{{if $i}}{{template "newline"}}
{{end}}{{style $l}}{{end}}
</p>
{{end}}
{{end}}
{{define "code"}}
<div class="code{{if playable .}} playground{{end}}" contenteditable="true" spellcheck="false">{{.Text}}</div>
{{end}}
{{define "image"}}
<div class="image">
<img src="{{.URL}}"{{with .Height}} height="{{.}}"{{end}}{{with .Width}} width="{{.}}"{{end}}>
</div>
{{end}}
{{define "iframe"}}
<iframe src="{{.URL}}"{{with .Height}} height="{{.}}"{{end}}{{with .Width}} width="{{.}}"{{end}}></iframe>
{{end}}
{{define "link"}}<p class="link"><a href="{{.URL}}" target="_blank">{{style .Label}}</a></p>{{end}}
{{define "html"}}{{.HTML}}{{end}}
{{define "caption"}}<figcaption>{{style .Text}}</figcaption>{{end}}

89
templates/article.tmpl Normal file
View File

@ -0,0 +1,89 @@
{/* This is the article template. It defines how articles are formatted. */}
{{define "root"}}
<!DOCTYPE html>
<html>
<head>
<title>{{.Title}}</title>
<link type="text/css" rel="stylesheet" href="/static/article.css">
<meta charset='utf-8'>
<script>
// Initialize Google Analytics tracking code on production site only.
if (window["location"] && window["location"]["hostname"] == "talks.golang.org") {
var _gaq = _gaq || [];
_gaq.push(["_setAccount", "UA-11222381-6"]);
_gaq.push(["b._setAccount", "UA-49880327-6"]);
window.trackPageview = function() {
_gaq.push(["_trackPageview", location.pathname+location.hash]);
_gaq.push(["b._trackPageview", location.pathname+location.hash]);
};
window.trackPageview();
window.trackEvent = function(category, action, opt_label, opt_value, opt_noninteraction) {
_gaq.push(["_trackEvent", category, action, opt_label, opt_value, opt_noninteraction]);
_gaq.push(["b._trackEvent", category, action, opt_label, opt_value, opt_noninteraction]);
};
}
</script>
</head>
<body>
<div id="topbar" class="wide">
<div class="container">
<div id="heading">{{.Title}}
{{with .Subtitle}}{{.}}{{end}}
</div>
</div>
</div>
<div id="page" class="wide">
<div class="container">
{{with .Sections}}
<div id="toc">
{{template "TOC" .}}
</div>
{{end}}
{{range .Sections}}
{{elem $.Template .}}
{{end}}{{/* of Section block */}}
{{if .Authors}}
<h2>Authors</h2>
{{range .Authors}}
<div class="author">
{{range .Elem}}{{elem $.Template .}}{{end}}
</div>
{{end}}
{{end}}
</div>
</div>
{{if .PlayEnabled}}
<script src='/play.js'></script>
{{end}}
<script>
(function() {
// Load Google Analytics tracking code on production site only.
if (window["location"] && window["location"]["hostname"] == "talks.golang.org") {
var ga = document.createElement("script"); ga.type = "text/javascript"; ga.async = true;
ga.src = ("https:" == document.location.protocol ? "https://ssl" : "http://www") + ".google-analytics.com/ga.js";
var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ga, s);
}
})();
</script>
</body>
</html>
{{end}}
{{define "TOC"}}
<ul>
{{range .}}
<li><a href="#TOC_{{.FormattedNumber}}">{{.Title}}</a></li>
{{with .Sections}}{{template "TOC" .}}{{end}}
{{end}}
</ul>
{{end}}
{{define "newline"}}
{{/* No automatic line break. Paragraphs are free-form. */}}
{{end}}

108
templates/dir.tmpl Normal file
View File

@ -0,0 +1,108 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Talks - The Go Programming Language</title>
<link type="text/css" rel="stylesheet" href="/static/dir.css">
<script src="/static/dir.js"></script>
<script>
// Initialize Google Analytics tracking code on production site only.
if (window["location"] && window["location"]["hostname"] == "talks.golang.org") {
var _gaq = _gaq || [];
_gaq.push(["_setAccount", "UA-11222381-6"]);
_gaq.push(["b._setAccount", "UA-49880327-6"]);
window.trackPageview = function() {
_gaq.push(["_trackPageview", location.pathname+location.hash]);
_gaq.push(["b._trackPageview", location.pathname+location.hash]);
};
window.trackPageview();
window.trackEvent = function(category, action, opt_label, opt_value, opt_noninteraction) {
_gaq.push(["_trackEvent", category, action, opt_label, opt_value, opt_noninteraction]);
_gaq.push(["b._trackEvent", category, action, opt_label, opt_value, opt_noninteraction]);
};
}
</script>
</head>
<body>
<div id="topbar"><div class="container">
<form method="GET" action="//golang.org/search">
<div id="menu">
<a href="http://golang.org/doc/">Documents</a>
<a href="http://golang.org/ref">References</a>
<a href="http://golang.org/pkg/">Packages</a>
<a href="http://golang.org/project/">The Project</a>
<a href="http://golang.org/help/">Help</a>
<input type="text" id="search" name="q" class="inactive" value="Search">
</div>
<div id="heading"><a href="/">The Go Programming Language</a></div>
</form>
</div></div>
<div id="page">
<h1>Go talks</h1>
{{with .Path}}<h2>{{.}}</h2>{{end}}
{{with .Articles}}
<h4>Articles:</h4>
<dl>
{{range .}}
<dd><a href="/{{.Path}}">{{.Name}}</a>: {{.Title}}</dd>
{{end}}
</dl>
{{end}}
{{with .Slides}}
<h4>Slide decks:</h4>
<dl>
{{range .}}
<dd><a href="/{{.Path}}">{{.Name}}</a>: {{.Title}}</dd>
{{end}}
</dl>
{{end}}
{{with .Other}}
<h4>Files:</h4>
<dl>
{{range .}}
<dd><a href="/{{.Path}}">{{.Name}}</a></dd>
{{end}}
</dl>
{{end}}
{{with .Dirs}}
<h4>Sub-directories:</h4>
<dl>
{{range .}}
<dd><a href="/{{.Path}}">{{.Name}}</a></dd>
{{end}}
</dl>
{{end}}
</div>
<div id="footer">
Except as <a href="https://developers.google.com/site-policies#restrictions">noted</a>,
the content of this page is licensed under the
Creative Commons Attribution 3.0 License,
and code is licensed under a <a href="http://golang.org/LICENSE">BSD license</a>.<br>
<a href="http://golang.org/doc/tos.html">Terms of Service</a> |
<a href="http://www.google.com/intl/en/policies/privacy/">Privacy Policy</a>
</div>
<script>
(function() {
// Load Google Analytics tracking code on production site only.
if (window["location"] && window["location"]["hostname"] == "talks.golang.org") {
var ga = document.createElement("script"); ga.type = "text/javascript"; ga.async = true;
ga.src = ("https:" == document.location.protocol ? "https://ssl" : "http://www") + ".google-analytics.com/ga.js";
var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ga, s);
}
})();
</script>
</body>
</html>

94
templates/slides.tmpl Normal file
View File

@ -0,0 +1,94 @@
{/* This is the slide template. It defines how presentations are formatted. */}
{{define "root"}}
<!DOCTYPE html>
<html>
<head>
<title>{{.Title}}</title>
<meta charset='utf-8'>
<script src='/static/slides.js'></script>
<script>
// Initialize Google Analytics tracking code on production site only.
if (window["location"] && window["location"]["hostname"] == "talks.golang.org") {
var _gaq = _gaq || [];
_gaq.push(["_setAccount", "UA-11222381-6"]);
_gaq.push(["b._setAccount", "UA-49880327-6"]);
window.trackPageview = function() {
_gaq.push(["_trackPageview", location.pathname+location.hash]);
_gaq.push(["b._trackPageview", location.pathname+location.hash]);
};
window.trackPageview();
window.trackEvent = function(category, action, opt_label, opt_value, opt_noninteraction) {
_gaq.push(["_trackEvent", category, action, opt_label, opt_value, opt_noninteraction]);
_gaq.push(["b._trackEvent", category, action, opt_label, opt_value, opt_noninteraction]);
};
}
</script>
</head>
<body style='display: none'>
<section class='slides layout-widescreen'>
<article>
<h1>{{.Title}}</h1>
{{with .Subtitle}}<h3>{{.}}</h3>{{end}}
{{if not .Time.IsZero}}<h3>{{.Time.Format "2 January 2006"}}</h3>{{end}}
{{range .Authors}}
<div class="presenter">
{{range .TextElem}}{{elem $.Template .}}{{end}}
</div>
{{end}}
</article>
{{range $i, $s := .Sections}}
<!-- start of slide {{$s.Number}} -->
<article>
{{if $s.Elem}}
<h3>{{$s.Title}}</h3>
{{range $s.Elem}}{{elem $.Template .}}{{end}}
{{else}}
<h2>{{$s.Title}}</h2>
{{end}}
</article>
<!-- end of slide {{$i}} -->
{{end}}{{/* of Slide block */}}
<article>
<h3>Thank you</h3>
{{range .Authors}}
<div class="presenter">
{{range .Elem}}{{elem $.Template .}}{{end}}
</div>
{{end}}
</article>
</section>
<div id="help">
Use the left and right arrow keys or click the left and right
edges of the page to navigate between slides.<br>
(Press 'H' or navigate to hide this message.)
</div>
{{if .PlayEnabled}}
<script src='/play.js'></script>
{{end}}
<script>
(function() {
// Load Google Analytics tracking code on production site only.
if (window["location"] && window["location"]["hostname"] == "talks.golang.org") {
var ga = document.createElement("script"); ga.type = "text/javascript"; ga.async = true;
ga.src = ("https:" == document.location.protocol ? "https://ssl" : "http://www") + ".google-analytics.com/ga.js";
var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ga, s);
}
})();
</script>
</body>
</html>
{{end}}
{{define "newline"}}
<br>
{{end}}