Skip to content

Commit d53e1cc

Browse files
committed
Finish index terms in Chapter 21
1 parent 4cde39a commit d53e1cc

File tree

2 files changed

+120
-107
lines changed

2 files changed

+120
-107
lines changed

05_higher_order.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -937,9 +937,10 @@ endif::html_target[]
937937

938938
(((ancestry example)))(((age difference (exercise))))(((average
939939
function)))Using the example data set from this chapter, compute the
940-
average age difference between mothers and children. You can use the
941-
`average` function defined
942-
link:05_higher_order.html#average_function[earlier] in this chapter.
940+
average age difference between mothers and children (the age of the
941+
mother when the child is born). You can use the `average` function
942+
defined link:05_higher_order.html#average_function[earlier] in this
943+
chapter.
943944

944945
(((byName object)))Note that not all the mothers mentioned in the data
945946
are themselves present in the array. The `byName` object, which makes

21_skillsharing.txt

Lines changed: 116 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33

44
= Project: Skill-Sharing Website =
55

6-
(((meetup)))(((project chapter)))A _((skill-sharing))_ meeting is an
7-
event where people with a shared interest come together and give
8-
small, informal presentations about things they know. At a
9-
((gardening)) skill-sharing meeting, someone might explain how to
10-
cultivate ((celery)). Or in a programming-oriented skill-sharing
11-
group, you could drop by and tell everybody about Node.js.
6+
(((skill-sharing project)))(((meetup)))(((project chapter)))A
7+
_((skill-sharing))_ meeting is an event where people with a shared
8+
interest come together and give small, informal presentations about
9+
things they know. At a ((gardening)) skill-sharing meeting, someone
10+
might explain how to cultivate ((celery)). Or in a
11+
programming-oriented skill-sharing group, you could drop by and tell
12+
everybody about Node.js.
1213

1314
(((learning)))(((users' group)))Such meetups, also often called
1415
_users’ groups_ when they are about computers, are a great way to
@@ -36,11 +37,11 @@ http://eloquentjavascript.net/code/skillsharing.zip[_eloquentjavascript.net/code
3637

3738
== Design ==
3839

39-
(((persistence)))There is a _((server))_ part to this project, written
40-
for ((Node.js)), and a _((client))_ part, written for the ((browser)).
41-
The server stores the system's data and provides it to the client. It
42-
also serves the HTML and JavaScript files that implement the
43-
client-side system.
40+
(((skill-sharing project)))(((persistence)))There is a _((server))_
41+
part to this project, written for ((Node.js)), and a _((client))_
42+
part, written for the ((browser)). The server stores the system's data
43+
and provides it to the client. It also serves the HTML and JavaScript
44+
files that implement the client-side system.
4445

4546
The server keeps a list of ((talk))s proposed for the next meeting,
4647
and the client shows this list. Each talk has a presenter name, a
@@ -117,9 +118,9 @@ system.
117118

118119
== HTTP interface ==
119120

120-
Before we start fleshing out either the server or the client, let's
121-
think about the point where they touch: the ((HTTP)) ((interface))
122-
over which they communicate.
121+
(((skill-sharing project)))Before we start fleshing out either the
122+
server or the client, let's think about the point where they touch:
123+
the ((HTTP)) ((interface)) over which they communicate.
123124

124125
We will base our interface on ((JSON)), and, like in the file server
125126
from link:20_node.html#file_server[Chapter 20], try to make good use
@@ -200,8 +201,6 @@ delayed until something happens, or a given time period (we will use
200201
90 seconds) has elapsed.
201202

202203
[[poll_time]]
203-
204-
205204
(((Unix time)))(((Date.now function)))(((synchronization)))The time
206205
must be indicated as the number of milliseconds elapsed since the
207206
start of 1970, the same type of number that is returned by
@@ -263,8 +262,8 @@ always risky). But all that is outside of the scope of this chapter.
263262

264263
== The server ==
265264

266-
Let's start by writing the ((server))-side part of the program. The
267-
following code runs on ((Node.js)).
265+
(((skill-sharing project)))Let's start by writing the ((server))-side
266+
part of the program. The following code runs on ((Node.js)).
268267

269268
=== Routing ===
270269

@@ -692,8 +691,9 @@ the `/talks` URL.
692691

693692
== The client ==
694693

695-
The ((client))-side part of the talk-managing website consists of
696-
three files: an HTML page, a style sheet, and a JavaScript file.
694+
(((skill-sharing project)))The ((client))-side part of the
695+
talk-managing website consists of three files: an HTML page, a style
696+
sheet, and a JavaScript file.
697697

698698
=== HTML ===
699699

@@ -927,10 +927,10 @@ function displayTalks(talks) {
927927
}
928928
----
929929

930-
(((instantiation)))Building up the DOM structure for talks is done
931-
using the ((template))s that were included in the HTML document. First
932-
we must define `instantiateTemplate`, which looks up and fills in a
933-
template.
930+
(((drawTalk function)))(((instantiation)))Building up the DOM
931+
structure for talks is done using the ((template))s that were included
932+
in the HTML document. First we must define `instantiateTemplate`,
933+
which looks up and fills in a template.
934934

935935
(((class (CSS))))(((querySelector method)))The `name` parameter is the
936936
template's name. To look up the template element, we search for an
@@ -977,8 +977,8 @@ whose properties hold the strings that are to be filled into the
977977
template. A ((placeholder)) like `{{title}}` will be replaced with the
978978
value of `values`’ `title` property.
979979

980-
This is a crude approach to templating, but it is enough to implement
981-
`drawTalk`.
980+
(((drawTalk function)))This is a crude approach to templating, but it
981+
is enough to implement `drawTalk`.
982982

983983
// include_code >code/skillsharing/public/skillsharing_client.js
984984

@@ -1175,63 +1175,68 @@ about efficiency—do the simplest thing that works.
11751175

11761176
!!solution!!
11771177

1178-
The simplest solution I can come up with is to simply encode the whole
1179-
`talks` object as JSON and dump it to a file with `fs.writeFile`.
1180-
There is already a function (`registerChange`) which is called every
1181-
time the server's data changes. It can be extended to write the new
1182-
data to disk.
1183-
1184-
Pick a file name, for example `./talks.json`. When the server starts
1185-
up, it can try to read that file with `fs.readFile`, and if that
1186-
succeeds, use its contents as our starting data.
1187-
1188-
Beware though, the `talks` object started out as a prototype-less
1189-
object, so that the `in` operator could be sanely used. `JSON.parse`
1190-
will return regular objects with `Object.prototype` as their
1191-
prototype. If you use JSON as your file format, you'll have to copy
1192-
the properties of the object returned by `JSON.parse` into a new,
1193-
prototype-less object.
1178+
(((file system)))(((writeFile function)))(((registerChange
1179+
function)))(((persistence)))The simplest solution I can come up with
1180+
is to simply encode the whole `talks` object as ((JSON)) and dump it
1181+
to a file with `fs.writeFile`. There is already a function
1182+
(`registerChange`) which is called every time the server's data
1183+
changes. It can be extended to write the new data to disk.
1184+
1185+
(((readFile function)))Pick a ((file)) name, for example
1186+
`./talks.json`. When the server starts up, it can try to read that
1187+
file with `fs.readFile`, and if that succeeds, use its contents as our
1188+
starting data.
1189+
1190+
(((prototype)))(((JSON.parse function)))Beware though, the `talks`
1191+
object started out as a prototype-less object, so that the `in`
1192+
operator could be sanely used. `JSON.parse` will return regular
1193+
objects with `Object.prototype` as their prototype. If you use JSON as
1194+
your file format, you'll have to copy the properties of the object
1195+
returned by `JSON.parse` into a new, prototype-less object.
11941196

11951197
!!solution!!
11961198

11971199
=== Comment field resets ===
11981200

1199-
The wholesale redrawing of talks works pretty well because you usually
1201+
(((comment field reset (exercise))))(((template)))(((state)))The
1202+
wholesale redrawing of talks works pretty well because you usually
12001203
can't tell the difference between a DOM node and its identical
12011204
replacement. But there are exceptions. If you start typing something
1202-
in the comment field for a talk in one browser window, and then, in
1203-
another, add a comment to that talk, the field in the first window
1204-
will be redrawn, removing both its content and its focus.
1205+
in the comment ((field)) for a talk in one browser window, and then,
1206+
in another, add a comment to that talk, the field in the first window
1207+
will be redrawn, removing both its content and its ((focus)).
12051208

12061209
In a heated discussion, where multiple people are adding comments to a
12071210
single talk, this would be very annoying. Can you come up with a way
12081211
to avoid it?
12091212

12101213
!!solution!!
12111214

1212-
The ad-hoc approach is to simply store the state a talk's comment
1213-
field (its content and whether it is focused) before redrawing the
1214-
talk, and then reset the field to its old state afterwards.
1215+
(((comment field reset (exercise))))(((template)))The ad-hoc approach
1216+
is to simply store the state a talk's comment field (its content and
1217+
whether it is ((focus))ed) before redrawing the talk, and then
1218+
((reset)) the ((field)) to its old state afterwards.
12151219

1216-
Another solution would be to not simply replace the old DOM structure
1217-
with the new one, but recursively compare them, node by node, and only
1218-
update the parts that actually changed. This is more general (it
1219-
continues working even if we add another text field), but also a lot
1220-
harder to implement.
1220+
(((recursion)))(((comparison,of DOM nodes)))Another solution would be
1221+
to not simply replace the old DOM structure with the new one, but
1222+
recursively compare them, node by node, and only update the parts that
1223+
actually changed. This is more general (it continues working even if
1224+
we add another text field), but also a lot harder to implement.
12211225

12221226
!!solution!!
12231227

12241228
=== Better templates ===
12251229

1226-
Most templating systems do more than just fill in a bunch of fields.
1227-
At the very least, they also allow conditional inclusion of parts of
1228-
the template, analogous to `if` statements, and repetition of parts of
1229-
a template, similar to a loop.
1230+
(((conditional execution)))(((repetition)))(((template)))Most
1231+
templating systems do more than just fill in some strings. At the very
1232+
least, they also allow conditional inclusion of parts of the template,
1233+
analogous to `if` statements, and repetition of parts of a template,
1234+
similar to a loop.
12301235

12311236
If we were able to repeat a piece of template for each element in an
12321237
array, we would not need the second template (`"comment"`), but rather
1233-
could specify the `"talk"` template to loop over the array held in a
1234-
talk's `comments` property, and render the nodes that make up a
1238+
could specify the `"talk"` template to ((loop)) over the array held in
1239+
a talk's `comments` property, and render the nodes that make up a
12351240
comment for every element in the array.
12361241

12371242
It could look like this:
@@ -1245,32 +1250,36 @@ It could look like this:
12451250
</div>
12461251
----
12471252

1248-
The idea being that whenever a node with a `template-repeat` attribute
1249-
is found during template instantiation, the instantiating code loops
1250-
over the array held in the property indicated by the attribute. For
1251-
each element in the array, it adds an instance of the node. The
1252-
template's context (the `values` variable in `instantiateTemplate`)
1253-
would, during this loop, point at the current element of the array, so
1254-
that `{{author}}`, rather than being looked up in the original context
1255-
(the talk), would be looked up in the comment object.
1253+
(((template-repeat attribute)))The idea being that whenever a node
1254+
with a `template-repeat` attribute is found during template
1255+
instantiation, the instantiating code loops over the array held in the
1256+
property named by that attribute. For each element in the array, it
1257+
adds an instance of the node. The template's context (the `values`
1258+
variable in `instantiateTemplate`) would, during this loop, point at
1259+
the current element of the array, so that `{{author}}`, rather than
1260+
being looked up in the original context (the talk), would be looked up
1261+
in the comment object.
12561262

1257-
Rewrite `instantiateTemplate` to implement this, and then change the
1258-
templates to use this feature and remove the explicit rendering of
1259-
comments from the `drawTalk` function.
1263+
(((drawTalk function)))(((instantiateTemplate function)))Rewrite
1264+
`instantiateTemplate` to implement this, and then change the templates
1265+
to use this feature and remove the explicit rendering of comments from
1266+
the `drawTalk` function.
12601267

1261-
How would you add conditional instantiation of nodes, where it is
1268+
How would you add conditional instantiation of nodes, making it
12621269
possible to omit parts of the template when a given value is true or
12631270
false?
12641271

12651272
!!solution!!
12661273

1267-
One way to do this is to change `instantiateTemplate` so that its
1268-
inner function takes not just a node, but also a current context as
1269-
argument. You can then, when looping over a node's child nodes, check
1270-
whether the child has a `template-repeat` attribute. If it does, don't
1271-
instantiate it once, but instead loop over the array indicated by the
1272-
attribute's value, and instantiate it once for every element in the
1273-
array, passing the current array element as context.
1274+
(((template)))(((repetition)))(((instantiateTemplate
1275+
function)))(((recursion)))(((template-repeat attribute)))One way to do
1276+
this is to change `instantiateTemplate` so that its inner function
1277+
takes not just a node, but also a current context as argument. You can
1278+
then, when looping over a node's child nodes, check whether the child
1279+
has a `template-repeat` attribute. If it does, don't instantiate it
1280+
once, but instead loop over the array indicated by the attribute's
1281+
value, and instantiate it once for every element in the array, passing
1282+
the current array element as context.
12741283

12751284
Conditionals can be implemented in a similar way, with attributes
12761285
called, for example, `template-when` and `template-unless`, which
@@ -1281,45 +1290,48 @@ false).
12811290

12821291
=== The unscriptables ===
12831292

1284-
When someone visits our website with a browser that has JavaScript
1285-
disabled, or is simply not capable of displaying JavaScript, they will
1286-
get a completely broken, inoperable page. This is not nice.
1293+
(((skill-sharing project)))(((JavaScript,absence of)))When someone
1294+
visits our website with a ((browser)) that has JavaScript disabled, or
1295+
is simply not capable of displaying JavaScript, they will get a
1296+
completely broken, inoperable page. This is not nice.
12871297

1288-
Some types of web applications really can't be done without
1289-
JavaScript. For others, you just don't have the budget or patience to
1290-
bother about clients that can't run scripts. But for pages with a wide
1291-
audience, it is polite to support script-less users.
1298+
Some types of ((web application))s really can't be done without
1299+
JavaScript. For others, you just don't have the ((budget)) or patience
1300+
to bother about clients that can't run scripts. But for pages with a
1301+
wide audience, it is polite to support script-less users.
12921302

1293-
Try to think of a way the skill sharing website could be set up to
1294-
preserve basic functionality when ran without JavaScript. The
1295-
automatic updates will have to go, and people will have to refresh
1296-
their page the old-fashioned way. But being able to see existing
1297-
talks, create new ones, and submit comments would be nice.
1303+
(((graceful degradation)))Try to think of a way the skill sharing
1304+
website could be set up to preserve basic functionality when ran
1305+
without JavaScript. The automatic updates will have to go, and people
1306+
will have to refresh their page the old-fashioned way. But being able
1307+
to see existing talks, create new ones, and submit comments would be
1308+
nice.
12981309

12991310
Don't feel obliged to actually implement this. Outlining a solution is
13001311
enough. Does the revised approach strike you as more, or less elegant
13011312
than what we did initially?
13021313

13031314
!!solution!!
13041315

1305-
Two central aspects of the approach taken in this chapter—a clean HTTP
1306-
interface, and client-side template rendering—don't work without
1307-
JavaScript. Normal HTML forms can send `GET` and `POST` requests, but
1308-
no `PUT` or `DELETE` requests, and can only send their data to a fixed
1309-
URL.
1316+
(((form (HTML tag))))(((page reload)))Two central aspects of the
1317+
approach taken in this chapter—a clean HTTP interface, and client-side
1318+
template rendering—don't work without JavaScript. Normal HTML forms
1319+
can send `GET` and `POST` requests, but no `PUT` or `DELETE` requests,
1320+
and can only send their data to a fixed URL.
13101321

1311-
Thus, the server would have to be revised to accept comments, new
1312-
talks, and deleted talks through `POST` requests, whose bodies aren't
1313-
JSON, but rather use the URL-encoded format that HTML forms use (see
1322+
(((query string)))(((POST method)))(((URL encoding)))Thus, the server
1323+
would have to be revised to accept comments, new talks, and deleted
1324+
talks through `POST` requests, whose bodies aren't JSON, but rather
1325+
use the URL-encoded format that HTML forms use (see
13141326
link:18_forms.html#forms[Chapter 17]). These requests would have to
13151327
return the full new page, so that users see the new state of the site
13161328
after they make a change. This would not be too hard to engineer, and
13171329
could be implemented alongside the “clean” HTTP interface.
13181330

1319-
The code for rendering talks would have to be duplicated on the
1320-
server. The `index.html` file, rather than being a static file, would
1321-
have to be generated dynamically (by adding a handler for it to the
1322-
router), so that it already includes the current talks when it gets
1323-
served.
1331+
(((template)))The code for rendering talks would have to be duplicated
1332+
on the server. The `index.html` file, rather than being a static file,
1333+
would have to be generated dynamically (by adding a handler for it to
1334+
the router), so that it already includes the current talks and
1335+
comments when it gets served.
13241336

13251337
!!solution!!

0 commit comments

Comments
 (0)