purpose & fundamentals
Federico Pereiro
Start with why
Two heroes under stress
Two heroes under stress
1) Starts with energy
2) Faces challenges
as chosen
Two heroes under stress
1) Starts with dread
2) Faces challenges
as imposed
Moving onto how
Web page
Web application
- Sending or receiving info requires a page refresh.
- The page is rendered once.
- Background communication with server.
- The page must be updated.
- Relies on connectivity.
- Fetches the whole thing.
- Offline ability.
- Fetches just the data.
// server code
http.get ('/update', function (req, res) {
response.end ('<li>New item</li>');
})
// client code
ajax ('get', '/update', function (error, data) {
$ ('ul.list').append (data);
});
// server code
http.get ('/update', function (req, res) {
response.end (['New item']);
})
// client code
ajax ('get', '/update', function (error, data) {
JSON.parse (data).map (function (item) {
$ ('.table').append ('<li>' + item + '</li>');
});
});
// client code
function makeTag (tag, className, value, content) {
var o = '<' + tag;
o += ' class="' + className + '"';
o += ' value="' + value + '">';
o += content;
o += '</' + tag + '>';
return o;
}
<p>Hello!</p>
[‘p’, ‘Hello!’]
<p class=”nice”></p>
[‘p’, {class: ‘nice’}]
<div>
<p class=”nice”>Hello</p>
</div>
['div', [
[‘p’, {class: ‘nice’}, 'Hello']
]]
Conditional #1: cond ? [‘p’, ‘Hello!’] : []
Conditional #2: [‘p’, {class: cond ? ‘h2’ : ‘’}, ‘Hello!’]
Iteration:
[‘table’, ITEMS.map (function (item) {
return [‘tr’, [‘td’, item]];
})]
// client code
ajax ('get', '/update', function (error, data) {
var items = JSON.parse (data).map (function (item) {
return ['li', item];
});
$ ('ul.list').append (makeHTML (items));
});
(Re)load:
- Affects everything.
- Must preserve user-provided amounts.
- Must preserve cart.
Filter:
- Affects counter of matching elements.
- Affects display of matching elements.
- Must preserve hidden elements.
Add to cart:
- Relies on whether product is in cart already.
- Relies on amount entered in box.
- Affects cart item count, total & actual items.
Remove from cart:
- Affects cart item count, total & actual items.
Submit cart:
- Get all cart data.
- Submit it.
- Clean up cart.
reload (data) {
updateItems ();
updateCart ();
}
changeFilter () {
var filter = $ ('#filter').value;
updateItems ();
}
addToCart (index) {
var q = $ ('#amount-' + index);
var p = ... // get matching product
updateCart ();
}
removeFromCart (index) {
var p = ... // get matching cart entry
updateCart ();
}
updateItems () {
// Update counters
// Go through each of the DOM elements
// Hide/unhide it if required
// Update it if it has changed
// Remove it if it was deleted
// Add it if it is new
}
updateCart () {
// Update counter & total
// Go through each of the DOM elements
// Hide/unhide it if required
// Update it if it has changed
// Remove it if it was deleted
// Add it if it is new
}
2
var Store = { items: [], cart: [], filter: '' }; ['input', {oninput: 'Store.filter = this.value; redraw ()'}];
function redraw () {
// redraws entire view
}
view ('items', function (items) {
return view ('filter', function (filter) {
return items.map (function (item) {
if (item.match (filter)) return ['td', item];
});
});
});
do ('set', 'filter', 'kitties');
do ('set', 'items', [
{title: 'kitties', price: 20},
{title: 'sunshine', price: 30}
]);
do ('add', 'items', {title: 'New!', price: 1000});
do ('rem', 'items', 0);
verb
path
arguments
do ('set', ['items', 0, title], 'kitties & sunshine');
view ('items', function (items) {
return view ('filter', function (filter) {
return items.map (function (item) {
if (item.match (filter)) return ['td', item];
});
});
});
add
set
rem
change
view ('change', 'items', function (items) {
return view ('change', 'filter', function (filter) {
return items.map (function (item) {
if (item.match (filter)) return ['td', item];
});
});
});