Skip to content

Commit 4045780

Browse files
author
James Halliday
committed
widget with assets level
1 parent 1c41cf1 commit 4045780

File tree

12 files changed

+8186
-6
lines changed

12 files changed

+8186
-6
lines changed

menu.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
"BUILD A WIDGET",
88
"USING TRANSFORMS",
99
"WRITING TRANSFORMS",
10+
"WIDGET WITH ASSETS",
1011

11-
"!WIDGET WITH BRFS",
12+
"SHIMMING NON-COMMONJS MODULES",
1213

1314
"!DEBUGGING",
1415
"!WATCH",
@@ -18,7 +19,5 @@
1819
"!BUILD YOUR OWN BROWSERIFY",
1920
"!COMPILER PIPELINE",
2021
"!BROWSER UNPACK",
21-
"!FACTOR BUNDLE",
22-
23-
"SHIMMING NON-COMMONJS MODULES"
22+
"!FACTOR BUNDLE"
2423
]

package.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
"falafel": "~0.3.1",
1616
"shoe": "~0.0.15",
1717
"split": "~0.3.0",
18-
"through2": "~0.5.1"
18+
"through2": "~0.5.1",
19+
"ever": "~0.0.3",
20+
"colornames": "~0.0.2"
1921
},
2022
"devDependencies": {
2123
"brfs": "^1.1.2",
@@ -26,7 +28,9 @@
2628
"sprintf": "~0.1.3",
2729
"stream-combiner2": "^1.0.0",
2830
"tape": "^2.13.3",
29-
"uniq": "^1.0.1"
31+
"uniq": "^1.0.1",
32+
"through2": "~0.5.1",
33+
"insert-css": "~0.2.0"
3034
},
3135
"scripts": {
3236
"test": "tape test/*.js"
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
var shoe = require('shoe');
2+
var sock = shoe('/sock');
3+
var ever = require('ever');
4+
5+
var Widget = require('widget');
6+
var w = Widget();
7+
var elem = document.createElement('div');
8+
document.body.appendChild(elem);
9+
w.appendTo(elem);
10+
var form = elem.querySelector('form');
11+
12+
w.on('message', function (msg) {
13+
sock.write(JSON.stringify(['msg',msg]) + '\n');
14+
});
15+
var txt = form.querySelector('textarea[name="msg"]')
16+
txt.value = 'howdee pardner';
17+
ever(form).emit('submit');
18+
19+
var style = window.getComputedStyle(txt);
20+
sock.write(JSON.stringify(['bg',style.backgroundColor]) + '\n');
21+
sock.write(JSON.stringify(['fg',style.color]) + '\n');
22+
23+
sock.write(JSON.stringify(['style',true]) + '\n');
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
var fs = require('fs');
2+
var path = require('path');
3+
var verify = require('adventure-verify');
4+
var concat = require('concat-stream');
5+
var http = require('http');
6+
var shoe = require('shoe');
7+
var ecstatic = require('ecstatic')(path.join(__dirname, 'static'));
8+
var split = require('split');
9+
var through = require('through2');
10+
var colorname = require('colornames');
11+
12+
exports.problem = fs.createReadStream(__dirname + '/problem.txt');
13+
exports.solution = fs.createReadStream(__dirname + '/solution.txt');
14+
15+
exports.verify = verify({ modeReset: true }, function (args, t) {
16+
var expected = [
17+
[ [ 'msg', 'howdee pardner' ], 'emits the message event' ],
18+
[ [ 'bg', 'purple' ], 'textarea background set to purple' ],
19+
[ [ 'fg', 'yellow' ], 'textarea foreground set to yellow' ],
20+
[ [ 'style', true ], 'using a style tag' ]
21+
];
22+
t.plan(expected.length);
23+
process.stdin.pipe(concat(function (body) {
24+
createServer(body, t).pipe(through.obj(function (row, enc, next) {
25+
var xex = expected.shift();
26+
var ex = xex[0], desc = xex[1];
27+
28+
if (row[0] === 'fg' || row[0] === 'bg') {
29+
if (ex[1] !== row[1] && /^#/.test(row[1])) {
30+
ex[1] = colorname(ex[1]);
31+
}
32+
else if (ex[1] !== row[1] && /^rgb/.test(row[1])) {
33+
var rgb = colorname(ex[1]).match(/\w{2}/g);
34+
ex[1] = 'rgb(' + rgb.map(function (s) {
35+
return parseInt(s, 16);
36+
}).join(',') + ')';
37+
row[1] = row[1].replace(/\s+/g, '');
38+
}
39+
}
40+
t.deepEqual(row, ex, desc);
41+
next();
42+
}));
43+
}));
44+
});
45+
46+
function createServer (body, t) {
47+
var output = through.obj();
48+
var server = http.createServer(function (req, res) {
49+
if (req.url === '/code.js') {
50+
res.end(body);
51+
}
52+
else ecstatic(req, res)
53+
});
54+
server.listen(55500, function () {
55+
console.log('Web server running. Visit this URL:'
56+
+ ' http://localhost:' + server.address().port
57+
);
58+
});
59+
var sock = shoe(function (stream) {
60+
stream.pipe(split()).pipe(through.obj(function (buf, enc, next) {
61+
var line = buf.toString('utf8');
62+
try { var row = JSON.parse(line) }
63+
catch (err) {
64+
if (t) return t.fail(err)
65+
else console.error(err);
66+
}
67+
68+
this.push(row);
69+
next();
70+
})).pipe(output);
71+
72+
if (t) t.once('end', function () { stream.end() });
73+
});
74+
75+
if (t) t.once('end', function () {
76+
server.close();
77+
setTimeout(function () {
78+
process.exit();
79+
}, 100);
80+
});
81+
sock.install(server, '/sock');
82+
return output;
83+
}
84+
85+
exports.run = function (args) {
86+
process.stdin.pipe(concat(function (body) {
87+
createServer(body).pipe(through.obj(function (row, enc, next) {
88+
console.log(row);
89+
next();
90+
}));
91+
}));
92+
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"scripts": {
3+
"build": "browserify -d -x widget browser.js -o static/bundle.js"
4+
}
5+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
This time the verifier will call your code. It will do something like this:
2+
3+
var Widget = require('widget');
4+
var w = Widget();
5+
w.setName('beep boop');
6+
w.appendTo(document.body);
7+
8+
You should implement the widget module that will be loaded with
9+
`require('widget')`. Your widget module should create an html element from
10+
the html string:
11+
12+
<div>Hello <span class="name"></span>!</div>
13+
14+
To turn this html string into a dom element, you can use the domify package
15+
from npm:
16+
17+
npm install domify
18+
19+
and then do `require('domify')` to get a `domify(html)` function that
20+
returns html elements. Otherwise you can create a dom element with
21+
`document.createElement('div')` and then set its innerHTML directly.
22+
23+
Your widget module will need to implement `w.setName(str)` and
24+
`w.appendTo(target)`. `w.setName(str)` will need to update the "name"
25+
span's inner context with `str`. You can set the span element's
26+
`.textContent` once you have a handle on the span which you can obtain with
27+
`elem.querySelector('css selector goes here')`.
28+
29+
You will also need to implement `w.appendTo(target)`, which appends the
30+
widget's internal html element to `target`. You can use
31+
`target.appendChild(elem)` to append the widget's element to the target.
32+
33+
Compile your program with `browserify -r ./widget.js:widget` to create a
34+
bundle that will expose `require('widget')` to the environment and pipe the
35+
bundle output into `$ADVENTURE_COMMAND verify` like this:
36+
37+
browserify -d -r ./widget.js:widget | $ADVENTURE_COMMAND verify
38+
39+
The `-d` turns on debug mode so you will get a stack trace with the proper
40+
line offsets if there is an error.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Here's the reference solution:
2+
3+
var domify = require('domify');
4+
var html = '<div>Hello <span class="name"></span>!</div>';
5+
6+
module.exports = Widget;
7+
8+
function Widget () {
9+
if (!(this instanceof Widget)) return new Widget;
10+
this.element = domify(html);
11+
}
12+
13+
Widget.prototype.setName = function (name) {
14+
this.element.querySelector('.name').textContent = name;
15+
};
16+
17+
Widget.prototype.appendTo = function (target) {
18+
target.appendChild(this.element);
19+
};
20+
21+
There are lots of ways to complete this level, so your solution might look
22+
quite different!
23+
24+
In this solution, we create an element with a string of html every time the
25+
widget gets instantiated. When `setName()` is called, we find the `name`
26+
span and update its text content. When `appendTo(target)` is called, we
27+
append the widget's html element to the target element.

0 commit comments

Comments
 (0)