Skip to content

Commit fda91bf

Browse files
committed
Add solutions for Chapter 21
1 parent e0c0f7f commit fda91bf

File tree

4 files changed

+145
-1
lines changed

4 files changed

+145
-1
lines changed

bin/chapter_info.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ var fs = require("fs");
66

77
var output = [], failed = false;
88

9-
var allSolutions = fs.readdirSync("code/solutions/").filter(function(file) { return !/^20/.test(file); });
9+
var allSolutions = fs.readdirSync("code/solutions/").filter(function(file) { return !/^2[01]/.test(file); });
1010

1111
var dir = fs.readdirSync(".");
1212
dir.sort();
@@ -92,6 +92,29 @@ dir.forEach(function(file) {
9292
solution: "// This solutions consists of multiple files. Download it\n// though the link below.\n"
9393
}
9494
];
95+
if (chapter.number == 21) chapter.exercises = [
96+
{name: "Disk persistence",
97+
file: "code/solutions/21_1_disk_persistence.js",
98+
number: 1,
99+
type: "js",
100+
code: nodeInfo,
101+
solution: fs.readFileSync("code/solutions/21_1_disk_persistence.js", "utf8")
102+
},
103+
{name: "Comment field resets",
104+
file: "code/solutions/21_2_comment_field_resets.js",
105+
number: 2,
106+
type: "js",
107+
code: nodeInfo,
108+
solution: fs.readFileSync("code/solutions/21_2_comment_field_resets.js", "utf8")
109+
},
110+
{name: "Better templates",
111+
file: "code/solutions/21_3_better_templates.js",
112+
number: 3,
113+
type: "js",
114+
code: nodeInfo,
115+
solution: fs.readFileSync("code/solutions/21_3_better_templates.js", "utf8")
116+
}
117+
];
95118

96119
output.push(chapter);
97120
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// This isn't a stand-alone file, only a redefinition of a few
2+
// fragments from skillsharing/skillsharing_server.js
3+
4+
var fs = require("fs");
5+
6+
var talks = loadTalks();
7+
8+
function loadTalks() {
9+
var result = Object.create(null), json;
10+
try {
11+
json = JSON.parse(fs.readFileSync("./talks.json", "utf8"));
12+
} catch (e) {
13+
json = {};
14+
}
15+
for (var title in json)
16+
result[title] = json[title];
17+
return result;
18+
}
19+
20+
function registerChange(title) {
21+
changes.push({title: title, time: Date.now()});
22+
waiting.forEach(function(waiter) {
23+
sendTalks(getChangedTalks(waiter.since), waiter.response);
24+
});
25+
waiting = [];
26+
27+
fs.writeFile("./talks.json", JSON.stringify(talks));
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// This isn't a stand-alone file, only a redefinition of displayTalks
2+
// from skillsharing/public/skillsharing_client.js
3+
4+
function displayTalks(talks) {
5+
talks.forEach(function(talk) {
6+
var shown = shownTalks[talk.title];
7+
if (talk.deleted) {
8+
if (shown) {
9+
talkDiv.removeChild(shown);
10+
delete shownTalks[talk.title];
11+
}
12+
} else {
13+
var node = drawTalk(talk);
14+
if (shown) {
15+
var textField = shown.querySelector("input");
16+
var hasFocus = document.activeElement == textField;
17+
var value = textField.value;
18+
talkDiv.replaceChild(node, shown);
19+
var newTextField = node.querySelector("input");
20+
newTextField.value = value;
21+
if (hasFocus) newTextField.focus();
22+
} else {
23+
talkDiv.appendChild(node);
24+
}
25+
shownTalks[talk.title] = node;
26+
}
27+
});
28+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Note that the first argument to instantiateTemplate was changed to
2+
// be the template itself, not its name, to make testing easier.
3+
4+
function instantiateTemplate(template, values) {
5+
function instantiateText(text, values) {
6+
return text.replace(/\{\{(\w+)\}\}/g, function(_, name) {
7+
return values[name];
8+
});
9+
}
10+
function attr(node, attrName) {
11+
return node.nodeType == document.ELEMENT_NODE &&
12+
node.getAttribute(attrName);
13+
}
14+
function instantiate(node, values) {
15+
if (node.nodeType == document.ELEMENT_NODE) {
16+
var copy = node.cloneNode();
17+
for (var i = 0; i < node.childNodes.length; i++) {
18+
var child = node.childNodes[i];
19+
20+
var when = attr(child, "template-when"), unless = attr(child, "template-unless");
21+
if (when && !values[when] || unless && values[unless])
22+
continue;
23+
24+
var repeat = attr(child, "template-repeat");
25+
if (repeat)
26+
(values[repeat] || []).forEach(function(element) {
27+
copy.appendChild(instantiate(child, element));
28+
});
29+
else
30+
copy.appendChild(instantiate(child, values));
31+
}
32+
return copy;
33+
} else if (node.nodeType == document.TEXT_NODE) {
34+
return document.createTextNode(instantiateText(node.nodeValue, values));
35+
}
36+
}
37+
38+
return instantiate(template, values);
39+
}
40+
41+
// A simple test function to verify that the above actually works
42+
43+
function test(template, values, expected) {
44+
var testTemplate = document.createElement("div");
45+
testTemplate.innerHTML = template;
46+
var result = instantiateTemplate(testTemplate, values).innerHTML;
47+
if (result != expected)
48+
console.log("Unexpected instantiation. Expected\n " + expected + "\ngot\n " + result);
49+
}
50+
51+
test('<h1 template-when="header">{{header}}</h1>',
52+
{header: "One"},
53+
'<h1 template-when="header">One</h1>');
54+
55+
test('<h1 template-when="header">{{header}}</h1>',
56+
{header: false},
57+
'');
58+
59+
test('<p><img src="icon.png" template-unless="noicon">Hello</p>',
60+
{noicon: true},
61+
'<p>Hello</p>');
62+
63+
test('<ol><li template-repeat="items">{{name}}: {{score}}</li></ol>',
64+
{items: [{name: "Alice", score: "10"}, {name: "Bob", score: "7"}]},
65+
'<ol><li template-repeat="items">Alice: 10</li><li template-repeat="items">Bob: 7</li></ol>');

0 commit comments

Comments
 (0)