Skip to content

Instantly share code, notes, and snippets.

@5310
Last active September 7, 2017 13:04
Show Gist options
  • Save 5310/68ac677e968eb6d0cfb54913ab975b8d to your computer and use it in GitHub Desktop.
Save 5310/68ac677e968eb6d0cfb54913ab975b8d to your computer and use it in GitHub Desktop.
PracProgW Notes #article
This Gist will collect all code or random notes from out web-dev crash-course.
// Factorial
let factorial = (n) => { // imperative
let fact = 1
for (let i = 1; i <= n; i++) fact *= i
return fact
}
let factorial1 = (n) => n === 1 ? 1 : n * factorial1(--n) // functional, recursive, non-tail-recursive
let factorial2 = (n) => { // functional, tail-recursive
// We need an auxiliary function for invariant recursion, to avoid stack-overflows.
// Our accumulator is the factorial iteself. Our input is the remaining natural number to factorial into.
// At every recursion we decrement the number to factorial, and multiply it into our accumulator.
let fact = (f = 1, m = n) => m === 1 ? f : fact(f * m, --m)
return fact()
}
let factorial3 = (n) => // functional, functorial
Array(n).fill().map((_, i) => i+1) // 1..n
.reduce((a, x) => a*x, 1)
// Count vowels in string.
const VOWELS = ['a', 'e', 'i', 'o', 'u']
let vowelsIn = (word) => { // procedural
let vowels = 0
//let word_ = word.toLowerCase()
// We don't need the above statement because by default such methods never overwrite the original.
for (let c of word)
if (VOWELS.includes(c))
vowels++
return vowels
}
let vowelsIn2 = (word) => word // functional, functorial
.split('')
.filter((c) => VOWELS.includes(c))
.length
let vowelsIn3 = (word) => word.match(/[aeiou]/gi).length // functional, platform idiomatic
// Consider the XRegExp library for Unicode patterns.
// Generate fibonacci series.
let fibonacci = (n) => { // procedural
let fs = []
let a = 0, b = 1, c
for (let i = 0; i < n; i++) {
fs.push(a)
c = a + b
a = b
b = c
}
return fs
}
let fibonacci2 = (n) => { // functional, tail-recursive
// We need an auxiliary function for invariant recursion, to avoid stack-overflows.
// Our accumulator is the series we're generating itself. Our input is the required number of iteration.
let fib = (fs = [0, 1], m = n - 2) => m <= 0
? fs
: fib((fs.push(fs[fs.length-1] + fs[fs.length-2]), fs), --m)
// recurse( updated series with sum of last two values, repeat one step fewer )
if (n <= 0) return []
else if (n == 1) return [1]
else return fib()
}
// I will not repeat basic syntax here. Refer to docs and cheat sheets for a syntax refresher.
// `function`s vs `=>` (arrow) functions and the `this` keyword
// which let's us create functions with dynamic execution contexts
// and therefore methods.
var foo = "dasdsad" // ES6 `let` variables aren't actually exposed to the `window` context, but `var`s are.
let f = function () { // `function` functions have dyamic `this`s
return this.foo
}
console.log(f()) // Here, `this` refers to the global context, which is `window` on the browser
let o = {f, foo: "baz"}
console.log(o.f()) // Here `this` refers to the "parent" context of the object
let g = () => { // Arrow functions are bound on definition. `this` is static
return this.foo
}
console.log(g()) // It still prints the global `foo`
let p = {g, foo: "qux"}
console.log(p.g()) // But even inside an object it prints the global `foo`
// Closure/lexical-scope
// Functions in Js will remember every identifier used inside them
// which were not defined inside them from the moment they were defined.
// This way they can carry around their own scope!
// This let's us create callbacks,
// and other richer higher-order functional programming magic
// like `map` or `filter` functions that access identifiers from the outside.
let makeAdder = (x) => (y) => x + y // Notice how this function returns another function that uses `x`
// This way, we can make custom "increment" functions that remembers the value, (partial application)!
let add5 = makeAdder(5);
let add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
// Prime generators
// A naïve O(n^2) primes implementation that checks divisibility with "every" value under a candidate
let primes = (n) => { // imperative
let primes = []
for (let i = 2; i<=n; i++ ) {
let isPrime = true
for (let j = 2; j <= i/2; j++) {
if(i % j === 0) {
isPrime = false
break
}
}
if (isPrime === true)
primes.push(i) // Notice how we can trivially add an element to an array with `push`, no need for a counter index.
}
return primes
}
// Sieve of Eratosthenes: https://en.wikipedia.org/wiki/Sieve_of_eratosthenes
let sieve = (n) => { // idiomatic, imperative + functional, non-recursive
let cs = Array(n).fill(true)
for (let i = 2; i < n**0.5; i++)
if (cs[i])
for (let j = i**2; j < n; j += i)
cs[j] = false
return cs
.map((c, i) => c ? i : null)
.slice(2)
.filter((c) => c !== null)
}
let sieve2 = (n) => { // idiomatic, functional, recursive, tail-recursive
let f = (primes = [], candidates = Array(n-1).fill(2).map((c, i) => c+i)) =>
candidates.length === 0
? primes
: f(primes.concat(candidates[0]), candidates.slice(1).filter((c) => c % candidates[0] !== 0))
return f()
}
///// Prototypal Inheritance /////
/// Object.create() ///
// We create our "base class".
let person = {
// Both of these become instance properties/methods of the `person` object.
// But prototype properties/methods of any object `create`d from it.
name: 'Parson',
greet: function () {
console.log(`Hullo, I'm ${this.name}!`)
}
}
// Here we use our `person` object by itself.
person.greet()
person.name = 'Steve'
person.greet()
console.log()
// Here we create a prototypal instance from the `person` object.
let aPerson = Object.create(person)
// It can access its prototype's properties (recursively so!)
aPerson.greet()
console.log()
// If the original prototype is changed, so is this fresh instance.
person.name = 'Steven'
person.greet()
aPerson.greet()
console.log()
// Here an instance property is created on `anotherPerson`.
// This "shadows" the prototype property of the same name, but does not modify it.
aPerson.name = 'Estefan'
aPerson.greet()
person.greet()
console.log()
// We create another new prototypal instance.
let loudPerson= Object.create(person)
// This becomes an instance method of the `loudPerson` object,
// likewise shadowing the prototype method by the same name.
loudPerson.greet = function () {
console.log(`Hullo, I'm ${this.name}!`.toUpperCase())
}
// This time we instantiate our "subclass" object before use, just to be neat.
let aLoudPerson = Object.create(loudPerson)
aLoudPerson.name = "André"
aLoudPerson.greet()
loudPerson.greet()
person.greet()
console.log()
// And we can still do subtype checks like so:
console.log(person.isPrototypeOf(aPerson))
console.log(person.isPrototypeOf(aLoudPerson))
/// Object.assign() ///
let person = {
name: 'Parson',
greet: function () {
console.log(`Hullo, I'm ${this.name}!`)
}
}
// And this is the idiomatic way to do manual subtypes, with mixins.
let loudPerson = Object.assign(
Object.create(person), // Inherits from `person` and then extends as follows:
{
// This becomes the instance method of the `loudPerson` object,
// but a prototype method of any objects `create`d from it.
// This is also a syntactical sugary way to define function members
// inside an object, just skip the `: function ` part.
greet() {
console.log(`Hullo, I'm ${this.name}!`.toUpperCase())
}
}
)
let aLoudPerson = Object.create(loudPerson)
aLoudPerson.name = "André"
aLoudPerson.greet()
/// Idiomatic Factory Functions ///
// Factory functions are named like classes in other languages,
// With capitalization.
let Person = function () {
// This becomes an instance property once an object is `new`d.
this.name = 'Parson'
// This is becomes an instance method,
// which would mean creating a new method for every instance
// which is wasteful, so we don't want that.
// this.greet = function () {
// console.log(`Hullo, I'm ${this.name}!`)
// }
}
// Instead we manually define our factory's prototype.
// We could've set an "older" superclass here if we wanted.
Person.prototype = {}
// And then define all our instance props and methods.
Person.prototype.greet = function () {
console.log(`Hullo, I'm ${this.name}!`)
}
// And familiar looking 'new' keyworded initialization.
// Still prototypal inheritance though!
let aPerson = new Person()
let anotherPerson = new Person()
anotherPerson.name = "Poisson"
aPerson.greet()
anotherPerson.greet()
// And here's how you test prototypal inheritance when using idiomatic factories
// and also how you'd do subtype polymorphism if you wanted.
if (anotherPerson instanceof Person)
console.log('`anotherPerson` still looks like a `Person`, yes.')
console.log()
// Let's create an "illegal alien."
let nonPerson
// Yes, this is a closure. Blocks are simply closures.
{
// Unfortunately, the easiest way to do private members in Js is to use closures
// and making variables simply unreachable from elsewhere, like this one.
let speciesID = 1000 + 999 * Math.random()
nonPerson = {
greet () {
console.log(`Greetings fellow-person, I am ${speciesID}.`)
}
}
}
nonPerson.greet()
if (nonPerson instanceof Person)
console.log(':Suspicious eyes:')
else
console.log('`nonPerson` is definitely not a `Person` though.')
/// ES6 "Class" Syntax Sugar ///
// And this is the new and almost universally hated "class syntax" in ES6.
// Don't be fooled, Js still doesn't have classical inheritance,
// it's just syntactic sugar around idiomatic factory functions,
// and demands you use the `new` keyword. `instanceof` works as intended.
class Person {
name = 'Parson';
greet () {
console.log(`Hullo, I'm ${this.name}!`)
}
}
class LoudPerson extends Person {
greet () {
console.log(`Hullo, I'm ${this.name}!`.toUpperCase())
}
}
let aLoudPerson = new LoudPerson()
aLoudPerson.name = 'André'
aLoudPerson.greet()
///// Asynchornous Programming /////
/// Aynchronicity and Callbacks ///
console.log('Waiting 3 seconds.')
setTimeout(() => console.log('And... Done!'), 3*1000)
console.log('Meanwhile, doing things...')
console.log('...some other things...')
console.log('...more things...')
console.log('...anything really...')
setTimeout(() => console.log('...even this asynchronous thing...'), 1*1000)
// Outputs the following at once:
// Waiting 3 seconds.
// Meanwhile, doing things...
// ...some other things...
// ...more things...
// ...anything really...
// Then after 1 second:
// => 3...even this asynchronous thing...
// And finally, after a total of three seconds:
// And... Done!
/// Chaining Asynchronous Operations, ES6 Promises, and ES8 Async/Await ///
// Convential "pyramid of asynchronous doom." //
// Works as expected, but is very unwieldly to code.
// Just imagine doing a hundred of these timeouts!
console.log("Let's go!")
setTimeout(
() => {
console.log("3")
setTimeout(
() => {
console.log("2")
setTimeout(
() => console.log("1"),
1000
)
},
1000
)
},
1000
)
// Flat ES6 Promise Implementation with `.then()` Chaining ///
// Our `promise`ing timeout implementation. Ignore this.
let timeout = (time) => new Promise((_) => setTimeout(_, time))
// We start our async chain with an instantaneous timeout because it's easier.
// And then we just chain and chain and chain for as long as we want,
// with just one trailing error handler if we need one.
// So much simpler than the "pyramid!"
timeout(0)
.then(() => console.log("On a count of three!"))
.then(() => console.log("3"))
.then(() => timeout(1*1000))
.then(() => console.log("2"))
.then(() => timeout(1*1000))
.then(() => console.log("1"))
.then(() => timeout(1*1000))
.then(() => console.log("Times up..."))
.then(() => timeout(1*1000))
.catch(() => console.log("DISMAL FAILURE!"))
// With ES8 `async/await` syntax async code becomes even sweeter to write! No callbacks at all!
async function f() {
console.log('Or we can async like civilized people...')
console.log("3")
await timeout(1*1000)
console.log("2")
await timeout(1*1000)
console.log("1")
await timeout(1*1000)
console.log('Yes, like that.')
}
f()
  • Minimal HTML5 Boilerplate
    • Necessary markup for a valid modern HTML pagge.
    • Evolving standards, HTML5
    • !DOCTYPE
    • html lang attribute
    • meta and character sets
    • img alt attribute
  • Common tags
    • Content tags: p, hN, ul, a, em, strong
    • Semantic tags: article, section, header, footer
    • Structural tags: div span
  • Using the DevTools to inspect style and markup
  • CSS Selectors
  • Common properties
    • background, color
    • font-size
    • position, left, top, etc.
  • Hints towards better layout options.
<!DOCTYPE html>
<!-- https://codepen.io/5310/pen/QdzpgM?editors=1100 -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>Hullo World!</title>
<style>
@import url('https://fonts.googleapis.com/css?family=Lobster');
* {
box-sizing: border-box;
}
:root {
font-size: 1vw;
}
header {
text-align: center;
}
header h1 {
font-family: 'Lobster', cursive;
font-size: 8em;
margin-bottom: -3%;
}
header h2 {
font-family: 'Lobster';
font-size: 3em;
font-weight: 100;
}
header h3 {
font-size: 1.5em;
font-weight: 100;
border-top: .25em solid black;
border-bottom: .25em solid black;
padding: .6em;
}
main {
display: flex;
flex-wrap: wrap;
width: 100vw;
}
main article {
width: 50vw;
padding: 2em;
text-align: justify;
}
main article section {
columns: 2;
column-gap: 2em;
}
main article section p {
margin-top: 0;
}
main article figure {
margin: 0;
}
main article figure img {
width: 100%;
}
main article figure figcaption {
padding: 1.5em 0;
font-size: 0.8em;
font-style: italic;
text-align: center;
}
main article.breaking {
width: 100vw;
}
main article.breaking section {
columns: 2;
}
</style>
</head>
<body>
<header>
<h1>Evening News</h1>
<h2>World Best-selling News Paper</h2>
<h3>22 May 2017, Kolkata</h3>
</header>
<main>
<article class="breaking">
<h1>Donald Trump..Abducted by Alliens or Not??!! </h1>
<section>
<figure>
<img
src="http://loremflickr.com/624/220/Donald_Trump"
alt="Gone for Good?" />
<figcaption>Donald Trump's corn hair....taken by Reuters</figcaption>
</figure>
<p>
Outside assiduously amongst dove conductively one save up necessarily demonstrably jay reserved jeepers squirrel overabundantly one kiwi less yikes gosh inappreciably jeepers was said far far and a into much hey gloated more prudent capybara aesthetically
cuckoo matter-of-factly grinned moaned but wherever prematurely strode the jeez massively more wherever faithful this so that forward goodness and where fawningly one one helpfully as strict that remade that imperative nonsensical capable jeepers
as repusively and alas much slid yikes frequent that the unstinting on satanically jeez more turtle underneath overran the groaned pompously got hey up darn let.
</p>
<p>
And dear crud hello free underneath the friskily commendable manful minutely oh jeepers quaintly that by guffawed much gosh far wildebeest jeepers dashing after that one under far and jeepers tame baboon yikes pending rode deer some some winning so ponderously
bluntly crud this that opposite amidst fox gagged much willfully rooster stealthy far dismissively more next weasel more jeez raccoon circa so less frugal lemming wherever armadillo that insincerely gosh jeez conditionally inset or following under
oh crud more sheared some far crucially sordidly more a in unobtrusively one save.
</p>
</section>
</article>
<article>
<h1>Indian Boy kohli Breaks Bradman's Record... </h1>
<figure>
<img
src="http://loremflickr.com/624/220/Virat_Kohli"
alt="New Rcords" />
<figcaption>Kohli Goes for His 4th Test Double Century...Bangladesh Test</figcaption>
</figure>
<section>
<p>
Outside assiduously amongst dove conductively one save up necessarily demonstrably jay reserved jeepers squirrel overabundantly one kiwi less yikes gosh inappreciably jeepers was said far far and a into much hey gloated more prudent anically jeez more
turtle underneath overran the groaned pompously got hey up darn let.
</p>
<p>
And dear crud hello free underneath the friskily commendable manful minutely oh jeepers quaintly that by guffawed much gosh far wildebeest jeepers dy more next weasel more jeez raccoon circa so less frugal lemming wherever armadillo that insincerely gosh
jeez conditionally inset or following under oh crud more sheared some far crucially sordidly more a in unobtrusively one save.
</p>
<p>
And dear crud hello free underneath the friskily commendable manful minutely oh jeepers quaintly that by guffawed much gosh far wildebeest jeepers dy more nextacetiously hedgehog and and snickered aloof like alas alas gosh ouch drunken aural that and
dazedly around stingily scandalously yikes much moodily the wow outdid the that emoted some even and hawk goodness more far much frlowing under oh crud more sheared some far crucially sordidly more a in unobtrusively one save.
</p>
</section>
</article>
<article>
<h1>King Khan Bangs with his New Movie RAEESE</h1>
<figure>
<img
src="http://loremflickr.com/624/220/Shah_rukh_khan"
alt="Raeese poster" />
<figcaption>New Movie Of SRK bags 300 crores</figcaption>
</figure>
<section>
<p>
And and indisputable flattering built music barbarous hello far or manta submissively oh far overthrew some inoffensively misunderstood that hyena earthword bald hey inclusive intrepidly pangolin upon more reciprocatingly less house regarding some far
impertinently yellow across less broke hence circa resold gregarious darn less fallacious vocal less rapt more occasionally and mounted opposite wow cuckoo thus prudently overran then until behind mallard.
</p>
<p>
Less one one and futile goodness armadillo upon jeez ingenuous darn on appalling cow one ostrich knitted less bat komodo oh and frog chuckled less while flexed aristocratically that naked overheard coughed therefore cuckoo ocelot esoteric admirable rethought
the less trout the proved snugly and jeepers vigorous and outside spread.
</p>
</section>
</article>
</main>
</body>
</html>

I forgot to introduce you all to the following too reference sites for the most commonly used HTML5 and CSS3 properties. Use these when you have access to the internet but MDN is too much of a hassle.

We went over what @media-queries were and how to design responsively.

On top of CSS features which are inherently responsive, such as automatically wrapping flexboxes and grids, conditional styles with @media let us do sophisticated overrides based on screen size, and even a lot of other properties of the device.

And to wrap off "advanced layouts:" We didn't really go over the convenient one-page reference for Flexbox, but we did mention it and use it once.

We also saw how awesome CSS Grid can be—I demoed my complex newspaper layout as a demo of what can be done with it—but we didn't delve too deep into Grids because even though it's the most stable and well-supported CSS spec till date, no currently-released browser actually has it yet, they're implemented in the versions to come in the next month or so. But I am also including the one-page ref for Grid properties, as well as an almost canonical site with very helpful practical layout examples.

In the process we used the CSS and HTML preprocessors/templating-languages LESS and Slim.

They are incredibly useful time-savers when marking up HTML or creating complex nested stylesheets. CodePen supports both, and we'll use both when we're on CodePen since the whole point of CodePen is to make these things take as little effort as possible.

In case you want port LESS/Slim code to pure CSS/HTML, you can always copy the compiled CSS/HTML from CodePen. And in case you want to do the reverse, to convert pure CSS/HTML into LESS/CSS. Well, LESS is a superset of CSS, so any CSS is already valid LESS. And I've included a tool to convert HTML to Slim.

And Rajesh briefly talked about cool slanted tabs in pure CSS. We didn't look at them. but I'm including a Pen for the record.

We then moved onto forms. You already know all about forms, even the new HTML5 elements. We decided that we'd lay one out as a modern webpage because despite teaching you guys HTML5 input elements your class insists on laying then out old-school.

The most annoying thing about forms is that the overloaded attributes. In order to link a label to an input you have to use an for and id elements with the same values respectively. Even with that id the input needs a name value to identify it within the form procedurally. And let's not even get started on confusion of when to use fieldset or section or just div.

Rules of thumb: Semantic before Generic. If your grouping has a meaning (radio-buttons, all the fields for an address) then use fieldset, if it's a logical grouping or a section of related fields or field-sets, use section, and if it's just for layout use div.

The next most annoying thing about forms is that even with the new HTML5 elements the UI widgets implemented in the core of HTML is pretty small, leaving useful stuff like tabs, and hybrid datalist–comboboxes, and other sophisticated elements like, say, a map widget! This is where we learned that we need not be limited to the built-in elements but rather make our own, or use other people's. We saw some webcomponents.

On top of some short form references (shortform short form references ;) I'm including the page Pranay developed here. And once I make my own version of the same form, I'll also add it here.

Next class we'd go about how and what to do with forms once you submit them.

Didn't cover what we were actually supposed to cover and instead revised layout and form queries.

Did introduce VS Code and Prepos for more convenient offline and yet prefixed code-editing

  • Visual Studio Code
    • I recommend installing a linter extension for languages you use, especially HTML and CSS.
  • Prepos
    • If you do use preprocessors, remember select your file and then process them once to start the watcher.

Addendum:

Susmita left her personal newspaper layout project for me to tinker with and I have. The main layout decisions persist, but I didn't really go for the aesthetic that she originally designed simply because I didn't want to have to actually make that magnifying-glass logo in SVG like I keep telling her to.

And then I actually went and finished the Madlibs demo for old-school form submission, GET requests, and URL query parameters. We'll go over it in class, but I'm leaving it here since it's done.

They're both standalone "offline" webpages. The newspaper didn't need to be, but since Susmita refuses to sketch online, I went ahead offline anyway. But the Madlibs demo needed to be offline as CodePen can't support query parameters.

Preview links to load these Gists as pages are on the Gists themselves.

We went over the basics of how to handle forms or dynamic content in general.

We started with the the "old-school" way of setting an action endpont and REST method for form submission. Followed up with making use of action submitted forms by parsing URL parameters with the Madlibs example.

And then we continued with our hands-on for the day, making a dynamic currency conversion app. We learned how to do dynamic content loading (what used to be popularly called AJAX and is now pretty much how the web works anyway,) and used it to fetch the latest currency conversion rates from an API.

We almost implemented the entire thing. The app was supposed to auto convert between either currency values when edited, but we only implemented one half of the interaction and left the other half as an exercise.

But we hit a wall when the API we were going to use to get a list of the currency symbols around the world refused to work because of broken cross-domain configs on their end. We can't really do much about it, so we left it at that. But I later went back and just used the list of currencies from the currency conversion API itself which I hadn't noticed before. Not only did it simplify our code significantly, I also reimplemented the whole thing using slightly more modern (upcoming) JavaScript features, async/await, which created far cleaner code!

We mostly talked about four-way crossings.

Then we explored the PokéAPI by making a type-searcher: CodePen

Further polish to the app in the form fixing a bug with displaying monotype pokémon after a dual-type is shown, and notifications for non-existent pokémon are in order.

We also decided to move directly onto a proper personal app project. Respectvely Evodex, an evolution-searcher using PokéAPI; and a Sudoku interface.

Next session we will start off with HTML5 Templates and Web Components, followed by looking at the app projects with a focus on how to "architect" them.

From here on in, we'll specifically look at problems we come across while working on these apps, and learn what we need to address them. I forsee some fancy animations for Evodex, and funcitional reactive architecture, localstorage, etc. for Sudoku.

We went over some layout and procedural issues with the Typedex and Sudoku prototype.

In case of the Typedex, we fixed the monotype error and also cleared the second typing in their case, and learned how to do a loading message.

And we quickly figured out that in order for it all to work smoothly we need to implement "debouncing:" We should only trigger the whole fetching routing at most once every 500ms or so, which is to say we must debounce the keyup events coming from the input field by 500ms, skipping every successive event that occurs within 500ms.

I've left the actual implementation open for now because, while it can certainly be done in pure JavaScript right now, depending on the application architecture we use, it might be easier to do! As a teaser, take a look at this diagram: http://rxmarbles.com/#debounce

Then we moved onto the main topic of the session, procedurally generating DOM with dynamic values, e.g. a Twitter-like feed from a list of messages which we can even fetch from an API.

We already can do it by manually interpolating strings and innerHTML, but we learned more practical ways to do it.

Starting with JavaScript templating engines, like Pug! Pug isn't just a convenient option to write HTML, it's also a fully fledged templating engine: a library that given a simplified template and some data will fill in the data into slots within that template to generate dynamic DOM elements. We defined our entire stream, a series of multiple posts, in Pug, and then generated that template against our data model.

Then we moved onto the platform-standard way to do templates these days, with the HTML5 <template> tag. In this method, we define our template in the markup and mark our slots via classes, which we then stamp out duplicates of and override with our data. It takes more effort, as we have to implement the function that overrides those marked slots with data, but it's really fast because it's part of the platform now!

Then use learned how to turn our div-soup post into a stand-alone custmom element with very minimal and intuitive markup! We first have to define this custom-element, and then just fill it with innerText and attributes. Using just the platform, we still have to manually hook up our slots, but such data-binding becomes trivial with a helper library like Google's Polymer which we only looked at briefly.

And finally, we learned how to use virtual-DOM Hyperscript functions to create our nodes dynamically. Virtual-DOM is a way to manupilate the DOM super fast with a better interface than wrangling the raw DOM that has become the backbone of many of the best web app development frameworks out there (especially Facebook's React which we didn't take a look at.) We only used it to generate our elements though, it's real power lies in updating an already created virtual element on the fly which we will be sure to use if we go the FRP application architecture and learn then.

Next session we'll learn how to plan and architect an application and some architectures to choose from. With this knowledge we'll be ready to start our personal app projects on our best foot!

We had an awful class today and I apologise for that. I just didn't look at the material we were going to cover since last week.

We did look at our implementations for debounding event callbacks (or indeed, any functions:) http://codepen.io/5310/pen/PpaQLe?editors=1010

And then we fixed the layout for prototype interface for the Evodex: http://codepen.io/5310/pen/vxQERr?editors=1100

And then we tried to separate the Sudoku project's model and view partially: http://codepen.io/nandyraj/pen/gmQGoO

We made very little progress on our actual topic for the day: architectures and project planning.

We did talk about why it's important to separate model and view and why modularity is important when developing complex software projects.

We were also supposed to look at the Functional Reactive Programming and Two-Way Data-Binding based application development architectural patterns. But we didn't, because I could remember none of the rhetoric.

Instead we briefly looked at example code for Cycle.js (FRP) and Polymer (2WDB) and asked you all to decide which of the architectures to follow for your own projects.

Except that I've changed my mind. You don't get to choose. For the Evodex, we'll use Two-Way Data-binding Polymer. And for Sudoku we'll use Cycle.js and Functional Reactive Programming.

Next week, I'll give you each a scaffold for your respective architectures and then you'll port in your existing work into it. If you don't like it, you can then throw it away, but it's important to take a look at these two technologies.

We implemented a trivial calculator: http://codepen.io/5310/pen/wJbKxv?editors=0010

And then looked into practical FRP by understanding the Cycle.js scaffold-port I made for the Sudoku app which was then extended with puzzle-parsing and cell-freezing.

In the process we learned that Observables/Streams are what Promises for multiple elements, and how all apps, interactive or otherwise, are ultimately about data-flow which is very easily modelled with streams.

We've skipped a lot of sessions, and left more without a transcript because none were necessary. But this session had us look at Progressive Web Apps and Service Workers, which deserve some referencing:

Noting that we need to host our PWAs under HTTPS (I mean, EVERYTHING should be hosted with HTTPS/2, not just PWAs and "banking" sites,) I also mentioned Glitch and Surge:

  • Glitch
    • Is a free standalone web-app development environment with full Node.js access and gives us free 3LDs with HTTPS to host our apps on. It's also an excellent place to collaborate on web apps in a low-fuss manner. It is still lower-level than CodePen, but that also means it's more capable than CodePen, you can maintain an entire file-tree (for free) and even write your own (Node.js) serverside code!
  • Surge.sh
    • Is a free static site host. If you just want to host your PWA that you developed locally (or anywhere else, really) Surge is the place to go to. HTTPS included, and you can even point your own domain name if their 3LD isn't cutting it for you!
  • GitHub Pages
    • Every GitHub repo gets its own HTTPS 3LD to host a site on. It's a no-brainer if you're already hosting your code on GH.
    • In case you really like developing in the browser and not having to maintain your own local dev environment, you can actually still continue to do that even after you host on GitHub (or any other modern code-hosting platform, really.)
      • Glitch supports importing and exporting to and from GH.
      • But there's also an entire web-based virtual development environment (where you can develop any kind of code, not just Node.js) called Cloud9. It's a very useful tool.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment