user interfaces 2
lesson 12
January 15th, 2020
talking
thinking
doing
programming
workflow
software design
system architecture
performance
user interfaces
agenda
advanced system design :: lesson 12 :: user interfaces 2
3
/ 93
web development
visualizations
frontend development
the world wide web
web technologies
web development
roadmap
advanced system design :: lesson 12 :: user interfaces 2
6
/ 93
the world wide web
advanced system design :: lesson 12 :: user interfaces 2
7
/ 93
static websites
advanced system design :: lesson 12 :: user interfaces 2
8
/ 93
dynamic websites
advanced system design :: lesson 12 :: user interfaces 2
9
/ 93
web apis
advanced system design :: lesson 12 :: user interfaces 2
10
/ 93
web applications
advanced system design :: lesson 12 :: user interfaces 2
11
/ 93
summary
advanced system design :: lesson 12 :: user interfaces 2
12
/ 93
frontend development
the world wide web
web technologies
web development
roadmap
advanced system design :: lesson 12 :: user interfaces 2
14
/ 93
html
advanced system design :: lesson 12 :: user interfaces 2
15
/ 93
layout and content
advanced system design :: lesson 12 :: user interfaces 2
16
/ 93
html in action
<html>
<head>
<meta charset="utf8" />
<title>Advanced System Design</title>
</head>
<body>
<h1>Advanced System Design</h1>
<p>A course about the unbearable lightness of coding.</p>
<ul>
<li><a href="/lessons">Lessons</a></li>
<li><a href="/exercises">Exercises</a></li>
<li><a href="/login">Login</a></li>
</ul>
</body>
</html>
<!doctype html>
advanced system design :: lesson 12 :: user interfaces 2
20
/ 93
css
advanced system design :: lesson 12 :: user interfaces 2
21
/ 93
design
advanced system design :: lesson 12 :: user interfaces 2
22
/ 93
who runs css
advanced system design :: lesson 12 :: user interfaces 2
23
/ 93
css in action
body {
background-color: #f0e2c8;
}
* {
font-family: 'Josefin Sans';
}
a {
color: #629ebb;
}
li {
margin-bottom: 10px;
}
advanced system design :: lesson 12 :: user interfaces 2
25
/ 93
semantics
advanced system design :: lesson 12 :: user interfaces 2
26
/ 93
not easy
advanced system design :: lesson 12 :: user interfaces 2
27
/ 93
more platforms
advanced system design :: lesson 12 :: user interfaces 2
28
/ 93
bootstrap in action
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" />
</head>
<body>
<div class="container mt-3">
<h1>Advanced System Design</h1>
<p>A course about the unbearable lightness of coding.</p>
</div>
<nav class="navbar navbar-expand-sm navbar-light bg-light">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/lessons">Lessons</a>
</li>
…
</ul>
</nav>
</body>
advanced system design :: lesson 12 :: user interfaces 2
29
/ 93
js
advanced system design :: lesson 12 :: user interfaces 2
30
/ 93
who runs js
advanced system design :: lesson 12 :: user interfaces 2
31
/ 93
js in action
> var x = 1;
> x;
1
> var s = 0;
> for (var i = 0; i < 5; i++) {
s += Math.pow(i, 2);
}
> s;
30
> function inc(x) {
return x + 1;
}
> inc(1);
2
> var o = {foo: 1, bar: 2};
> o.foo;
1
> o['bar'];
2
> function runTwice(f) {
f();
f();
}
> function hello() {
console.log('Hello, world!');
}
> runTwice(hello)
Hello, world!
Hello, world!
> runTwice(function() {
console.log('I have no name.');
});
I have no name.
I have no name.
advanced system design :: lesson 12 :: user interfaces 2
32
/ 93
introduction to prototypes
> function Person(name) {� this.name = name;
}
> var alice = new Person('Alice');
> alice;
Person {name: 'Alice'}
> alice.hello = function() { console.log("Hello! I'm ' + this.name); };
> alice.hello();
Hello! I'm Alice
> var bob = new Person('Bob');
> bob.hello()
TypeError: bob.hello is not a function
> Person.hello = function() { … };
> bob.hello();
TypeError: bob.hello is not a function
> Person.prototype.hello = function() { … };
> bob.hello()
Hello! I'm Bob
> var charlie = Person('Charlie');
> charlie
undefined
> window.name
'Charlie'
alice.__proto__.hello = function() { … };
{}
constructor: Person(name)
{}
name: 'Alice'
__proto__
hello: [Function]
hello: [Function]
prototype
hello: …
name: 'Bob'
{}
__proto__
advanced system design :: lesson 12 :: user interfaces 2
33
/ 93
implementing prototypes
>>> def Person(this, name):
... this.name = name
>>> alice = new(Person)('Alice')
>>> def new(f):
... if not hasattr(f, 'prototype'):
... f.prototype = Object()
... f.prototype.constructor = f
... this = Object()
... this.__proto__ = f.prototype
... def construct(*args, **kwargs):
... this.__proto__.constructor(this, *args, **kwargs)
... return this
... return construct
>>> alice.__proto__.hello = lambda this: print(f"Hello! I'm {this.name}!")
>>> alice.hello()
Hello! I'm Alice
>>> bob = new(Person)('Bob')
>>> bob.hello()
Hello! I'm Bob
>>> class Object:
... __proto__ = None
... def __getattr__(self, name):
... value = getattr(self.__proto__, name)
... if inspect.isfunction(value):
... return value.__get__(self, self.__class__)
... return value
{}
{}
__proto__
f
constructor
prototype
{}
__proto__
advanced system design :: lesson 12 :: user interfaces 2
34
/ 93
the dom
advanced system design :: lesson 12 :: user interfaces 2
35
/ 93
the dom in action
> var p = document.getElementById('greeting');
> p.textContent = 'Hello, world!';
> p.remove();
> var ul = document.createElement('ul');
> var li = document.createElement('li');
> var t = document.createTextNode('one');
> li.appendChild(t);
> ul.append(li);
> li2 = document.createElement('li');
> t2 = document.createTextNode('two');
> li2.appendChild(t2);
> ul.append(li2);
> document.body.append(ul);
> function hello() {
alert('Hello, world!')
}
<p id="greeting"></p>
<button onClick="hello()">Click me!</button>
advanced system design :: lesson 12 :: user interfaces 2
36
/ 93
a more complicated example
function onHover(image, activate) {
var src = image.getAttribute('src');
if (activate) {
var parts = src.split('.');
src = parts[0] + '-active' + parts[1];
} else {
var parts = src.split('.');
src = parts[0].substring(0, parts[0].indexOf('-'))� + parts[1];
image.setAttribute('src', src);
}
var imgs = document.getElementsByClassName('social-media-button');
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i];
img.setAttribute('src', img.getAttribute('data-inactive'));
img.onmouseover = function() { this.setAttribute('src', this.getAttribute('data-active')); };
img.onmouseout = function() { this.setAttribute('src', this.getAttribute('data-inactive')); };
}
<img src="fb.png"
onMouseOver="onHover(this, true)"
onMouseOut="onHover(this, false)" />
<img class="social-media-button"
data-inactive="fb.png"
data-active="fb-active.png" />
}
advanced system design :: lesson 12 :: user interfaces 2
37
/ 93
a lesson in decoupling
advanced system design :: lesson 12 :: user interfaces 2
38
/ 93
still, a mess
advanced system design :: lesson 12 :: user interfaces 2
39
/ 93
jsfuck
> []
[]
> +[]
0
> ![]
false
> [] + []
''
> ![] + []
'false'
> (![] + [])[+[]]
'f'
> function f() {}
> f.constructor
Function() { [native code] }
> f['constructor']
Function() { [native code] }
> f = Function('return 42')
> f()
42
> [].filter
filter() { [native code] }
> []['filter']['constructor']('return 42')()
42
advanced system design :: lesson 12 :: user interfaces 2
40
/ 93
jquery to the rescue
advanced system design :: lesson 12 :: user interfaces 2
41
/ 93
jquery in action
> var p = $('p');
> p.text('Hello, world!');
> p.remove();
> $('body').append(
$('<ul></ul>').append($('<li></li>', {text: 'one'}))
.append($('<li></li>', {text: 'two'}))
);
> $('img').hover(function() {
$(this).attr('src', $(this).data('active'));
}, function() {
$(this).attr('src', $(this).data('inactive'));
});
> $('img').each(function() {
$(this).attr('src', $(this).data('inactive'));
});
advanced system design :: lesson 12 :: user interfaces 2
42
/ 93
dynamic websites
advanced system design :: lesson 12 :: user interfaces 2
43
/ 93
flask in action
app = flask.Flask(__name__)
@app.route('/login')
def login():
return flask.render_template('login.html')
@app.route('/login', methods=['GET', 'POST'])
def login():
if flask.request.method == 'GET':
return flask.render_template('login.html')
username = flask.request.form['username']
password = flask.request.form['password']
token = authenticate(username, password):
if token:
redirect = flask.redirect('/account')
response = flask.make_response(redirect)
response.set_cookie('token', token)
return response
<form method="POST">
<input type="text" name="username" />
<input type="password" name="password" />
</form>
@app.route('/account')
def account():
token = flask.request.cookies.get('token')
user = get_user(token)
if not user:
return flask.redirect('/login')
return flask.render_template('account.html',� user=user)
{% if user %}
<p>Hello, {{ user.name }}!</p>
{% else %}
<a href="/login">Log in</a>
{% endif %}
return flask.redirect('/login')
advanced system design :: lesson 12 :: user interfaces 2
44
/ 93
a side-note on code generation
advanced system design :: lesson 12 :: user interfaces 2
45
/ 93
summary
advanced system design :: lesson 12 :: user interfaces 2
46
/ 93
frontend development
the world wide web
web technologies
web development
roadmap
advanced system design :: lesson 12 :: user interfaces 2
48
/ 93
the two ends
advanced system design :: lesson 12 :: user interfaces 2
49
/ 93
ajax
advanced system design :: lesson 12 :: user interfaces 2
50
/ 93
ajax in action
function getPosts() {
$.get('/posts', function(data) {
var posts = JSON.parse(data); // or use $.getJSON
for (var i = 0; i < posts.length; i++) {
var post = posts[i];
var author = $('<td></td>', {'text': post.author});
var content = $('<td></td>', {'text': post.content});
var row = $('<tr></tr>');
row.append(author);
row.append(content);
$('#posts').append(row);
}
});
}
<table id="posts"></table>
advanced system design :: lesson 12 :: user interfaces 2
51
/ 93
the good, the bad, and the ugly
advanced system design :: lesson 12 :: user interfaces 2
52
/ 93
defining the problem
advanced system design :: lesson 12 :: user interfaces 2
53
/ 93
jsx
advanced system design :: lesson 12 :: user interfaces 2
54
/ 93
jsx in action
var as = [];
for (var i = 0; i < links.length; i++) {
var a = <a href={links[i].url}>{links[i].text}</a>;
as.push(a);
}
var result = <div>{as}</div>
var result = user ? (
<p>Hello, {user.name}!</p>
) : (
<a href="/login">Log in</a>
);
advanced system design :: lesson 12 :: user interfaces 2
55
/ 93
react
advanced system design :: lesson 12 :: user interfaces 2
56
/ 93
react in action
function Menu() {
var links = [
{url: '/lessons', text: 'Lessons'},
{url: '/exercises', text: 'Exercises'},
{url: '/login', text: 'Login'},
];
var lis = [];
for (var i = 0; i < links.length; i++) {
var li = <li><a href={links[i].url}>{links[i].text}</a></li>;
lis.push(li);
}
return <ul>{lis}</ul>;
}
<div id="app"></div>
<script>
ReactDOM.render(<App />, document.getElementById('app'));
</script>
function App() {
return (<div>
<Menu />
<h1>Advanced System Design</h1>
<p>A course about the unbearable lightness of coding.</p>
</div>);
}
advanced system design :: lesson 12 :: user interfaces 2
57
/ 93
arguments
advanced system design :: lesson 12 :: user interfaces 2
58
/ 93
props in action
function Menu(props) {
var lis = [];
for (var i = 0; i < props.links.length; i++) {
var li = <li><a href={props.links[i].url}>{props.links[i].text}</a></li>;
lis.push(a);
}
return <ul>{lis}</ul>;
}
<Menu links={…} />
advanced system design :: lesson 12 :: user interfaces 2
59
/ 93
state
advanced system design :: lesson 12 :: user interfaces 2
60
/ 93
state in action
class Button extends React.Component {
state = {index: 0};
render() {
var color = this.props.colors[this.state.index];
return <button style={{backgroundColor: color}} onClick={this.toggle.bind(this)}>Click me!</button>;
}
toggle() {
var index = (this.state.index + 1) % this.props.colors.length;
this.setState({index: index}); // not this.state.index = index
}
}
click me!
click me!
click me!
click me!
advanced system design :: lesson 12 :: user interfaces 2
61
/ 93
flow
advanced system design :: lesson 12 :: user interfaces 2
62
/ 93
flow in action
class Posts extends React.Component {
state = {posts: null}
render() {
if (!this.state.posts) {
return <div>Loading…</div>
}
return <div>{this.state.posts.map(function(post) { return <div>{post.content}</div>; })}</div>;
}
componentDidMount() {
fetch(API_ROOT + '/posts').then(function(data) {
var posts = JSON.parse(data);
this.setState({posts: posts});
}
}
}
advanced system design :: lesson 12 :: user interfaces 2
63
/ 93
deployment
advanced system design :: lesson 12 :: user interfaces 2
64
/ 93
web development
visualizations
visualizations
advanced system design :: lesson 12 :: user interfaces 2
66
/ 93
4 dimensional plots
f(z) = z
f(z) = z3 - 1
f(z) = sin(z)
advanced system design :: lesson 12 :: user interfaces 2
67
/ 93
charts
interactivity
visualizations
roadmap
advanced system design :: lesson 12 :: user interfaces 2
69
/ 93
visualization
advanced system design :: lesson 12 :: user interfaces 2
70
/ 93
bad visualization
advanced system design :: lesson 12 :: user interfaces 2
71
/ 93
chart types
advanced system design :: lesson 12 :: user interfaces 2
72
/ 93
matplotlib
advanced system design :: lesson 12 :: user interfaces 2
73
/ 93
matplotlib in action
>>> import matplotlib.pyplot as plt
>>> x = list(range(100))
>>> plt.plot(x, x, color='black')
>>> plt.show()
>>> plt.clf()
>>> import numpy as np
>>> x = np.linspace(0, 2, 100)
>>> plt.plot(x, x, label='linear', color='#fd4f2a')
>>> plt.plot(x, x**2, label='quadratic', color='#629ebb')
>>> plt.plot(x, x**3, label='cubic', color='#fea027')
>>> plt.xlabel('X axis')
>>> plt.ylabel('Y axis')
>>> plt.title('Lines')
>>> plt.legend()
>>> plt.show()
advanced system design :: lesson 12 :: user interfaces 2
74
/ 93
object-oriented matplotlib
advanced system design :: lesson 12 :: user interfaces 2
75
/ 93
object-oriented matplotlib in action
>>> fig = plt.figure(figsize=(8, 2.5))
>>> fig.suptitle('Lines')
>>> ax = fig.add_subplot(1, 3, 1)
>>> ax.set_title('Linear')
>>> ax.plot(x, x, color='#fd4f2a')
>>> ax = fig.add_subplot(1, 3, 2)
>>> ax.set_title('Quadratic')
>>> ax.plot(x, x**2, color='#629ebb')
>>> ax = fig.add_subplot(1, 3, 3)
>>> ax.set_title('Cubic')
>>> ax.plot(x, x**3, color='#fea027')
>>> fig.show()
advanced system design :: lesson 12 :: user interfaces 2
76
/ 93
when it's actually helpful
>>> import sklearn.datasets
>>> iris = sklearn.datasets.load_iris()
>>> sepal_length, sepal_width, petal_length, petal_width = iris.data.T
>>> type = iris.target
>>> fig = plt.figure()
>>> ax = fig.add_subplot(1, 2, 1)
>>> ax.scatter(sepal_length[type == 0], sepal_width[type == 0], color='#fd4f2a')
>>> ax.scatter(sepal_length[type == 1], sepal_width[type == 1], color='#629ebb')
>>> ax.scatter(sepal_length[type == 2], sepal_width[type == 2], color='#fea027')
>>> fig.show()
>>> ax = fig.add_subplot(1, 2, 2)
>>> ax.scatter(petal_length[type == 0], petal_width[type == 0], color='#fd4f2a')
>>> ax.scatter(petal_length[type == 1], petal_width[type == 1], color='#629ebb')
>>> ax.scatter(petal_length[type == 2], petal_width[type == 2], color='#fea027')
>>> fig.show()
advanced system design :: lesson 12 :: user interfaces 2
77
/ 93
going 3d
>>> from mpl_toolkits.mplot3d import Axes3D
>>> fig = plot.figure()
>>> ax = Axes3D(fig, elev=-150, azim=120)
>>> ax.scatter(petal_length[type == 0], petal_width[type == 0], sepal_width=[type == 0], color='#fd4f2a')
>>> ax.scatter(petal_length[type == 1], petal_width[type == 1], sepal_width=[type == 1], color='#629ebb')
>>> ax.scatter(petal_length[type == 2], petal_width[type == 2], sepal_width=[type == 2], color='#fea027')
>>> fig.show()
advanced system design :: lesson 12 :: user interfaces 2
78
/ 93
plotly
advanced system design :: lesson 12 :: user interfaces 2
79
/ 93
bar charts
>>> # magically acquire data
>>> import plotly.express as px
>>> fig = px.bar(data, x='year', y='population')
>>> fig.update_layout(title=…, yaxis_title=…, xaxis_title=…, width=…, height=…)
>>> fig.update_xaxes(tickangle=…)
>>> fig.show()
advanced system design :: lesson 12 :: user interfaces 2
80
/ 93
area charts
>>> fig = px.area(data, x='year', y='population', line_group='country', color='country')
>>> …
>>> fig.show()
advanced system design :: lesson 12 :: user interfaces 2
81
/ 93
pie charts
>>> fig = px.area(data, values='population', names='country')
>>> fig.update_traces(textposition='inside', textinfo='percent+label')
>>> fig.show()
advanced system design :: lesson 12 :: user interfaces 2
82
/ 93
bubble charts
>>> fig = px.area(data, x='gdp_per_capita', y='life_expectancy', size='population', color='country')
>>> …
>>> fig.show()
US
Japan
France
China
India
Nigeria
Israel
advanced system design :: lesson 12 :: user interfaces 2
83
/ 93
summary
advanced system design :: lesson 12 :: user interfaces 2
84
/ 93
plotting
interactivity
visualizations
roadmap
advanced system design :: lesson 12 :: user interfaces 2
86
/ 93
interactivity
advanced system design :: lesson 12 :: user interfaces 2
87
/ 93
games: the ultimate art
advanced system design :: lesson 12 :: user interfaces 2
88
/ 93
interactive plots
advanced system design :: lesson 12 :: user interfaces 2
89
/ 93
interactive python
advanced system design :: lesson 12 :: user interfaces 2
90
/ 93
jupyter notebook
advanced system design :: lesson 12 :: user interfaces 2
91
/ 93
jupyter notebook use-cases
advanced system design :: lesson 12 :: user interfaces 2
92
/ 93
summary
advanced system design :: lesson 12 :: user interfaces 2
93
/ 93