This is a very brief introduction to programming for the web, focused on the “front end”. We’ll talk about
First, some resources to go more in depth after this primer.
You don’t need much to start
http-server (installed with npm)python3 -m http.serverFor more serious work, you’ll need
node the stand-alone JavaScript runtimenpm the package manager included with node.jsA website is separated into 3 parts:
The HTML/CSS are used to create the DOM, while JavaScript interacts with it.
We can inspect the DOM using Developer tools in any browser, by menu, or right-click > inspect.
Things to notice:
document)offsetHeight)HyperText Markup Language
<tag-name attribute="value">innerHTML</tag-name>
<tag-name attribute="value" />
<!-- comments -->
Things to note in this document:
<head> contains metadata about the page, including
<body> contains the actual pagesection in body, and h1 in section and text in h1 like the DOMh1 is a headingp is a paragraphul is an unordered list with li elements inside of ita is an “anchor” (a link, or a marker in the current document)nav is a navigation bar/menuclass or id
red-box<div class="hidden slide"><nav id='main-nav'></nav>href, alt, or anything elseWriting raw HTML with all the opening and closing tags can be be quite tedious.
so a lot of developers use Markdown to write content. The text in .md format can be passed through a parser and compiled into HTML. This can be done with most markup languages.
Even with the content written in a nicer language, the boiler-plate and layout is often repetitive, so templating languages like mustache are popular.
Cascading style sheets describe the appearance of elements.
“Cascading” refers to the way rules/declarations are applied:
Syntax:
selector { property: value; ... }
The whole statement is a “rule”. Each property: value; pair is a “declaration”.
Describe the elements in the DOM. There are,
a, div, p, section, asdf, ….class-name, a.class1.class2#
#main-nav, #start-buttonSelectors can also be combined to describe where an element falls in the DOM hierarchy.
> is an immediate descendent+~div.red-box vs. div .red-box)I read these from right to left: the selected element matches the rightmost selector, the rest describes its place in the DOM Example:
section > p + h1 {
color: blue;
}
Selects the top-level heading directly adjacent to a paragraph which is the child of a section.
[attr] has the attribute attr,[attr=val] has the attribute attr with the value val,[attr~=val] has the attribute attr containing val in a space-separated list.div:hover affects a div if the mouse is hovering over ith1:first-child only selects h1 if it is the first child tooh1:first-of-type selects the first h1 of its siblingsp:nth-of-type(2n+1) selects all odd paragraphs::
[href^=http]::after { content: '⤴'; }property: value;)These describe the way an element is drawn. Different elements can have their own special properties, but no error will be given if a property doesn’t apply.
Common properties include:
color : values can be like red, #f00, #fa0000, rgba(255, 0, 0, .5)background : as abovedisplay : block, inline, block-inline, flex, etc.margin-top: a length 0em, 0.3rem, 4px, 1%visibleYou’ll have to look up a reference for all the possibilities.
It’s worth mentioning the box model for element sizing/spacing.
margin’s are the spaces between objectsborder’s are the size of the drawn borderpadding is the space between the border and the contentwidth and height describe the size of the element
box-sizing: content-box is default where width/height does not include margins, borders or padding.box-sizing: border-box makes width/height include padding and borders (easier math in many cases)Sites with more complicated layout will often use
* { box-sizing: content-box; },
to make the sizes consistent regardless of borders and padding.
CSS lacks some features that can be very useful/convenient, like
This is good for browser performance, but a pain for developers. There are lots of pre-processors for CSS that add all these features and more
JavaScript is the scripting language supported by modern browsers. It’s specified as ECMAScript, the latest standard being ECMAScript 2015 (aka ES6). All modern browsers support ES5.1, and most of ES6
JavaScript is a scripting language with
ES6 adds
""" in Python, but with ${expressions})let instead of varThere are primitive types:
Then there are notably,
Variables can be declared with var or let. You’ll probably use var most.
var x = 1;
var s = 'hello world';
var u; // undefined
var f = function() {
console.log('function f called');
};
var o = {name: 'some object', callMe: f, 1: 'one'}
let is for block-scope which is good for loop variables.
for (let i=0; i<10; i++) {
console.log(i)
}
console.log(i) // error
Can be anonymous:
(function() {console.log('hello world')})()
Named throughout current scope (“hoisted”):
foo() // logs "bar"
function foo() {
console.log('bar');
}
Attached to a variable:
bar() // error
var bar = function () {
console.log('foo')
}
bar() // logs "foo"
The scope describes what variables are accessible and their names. In JavaScript, the scope of a variable defined with var is the current function. JS also has a lexical scope, so functions inherit the scope of their parents.
// example of isolating scope with a function
var x = 10;
(function () {
var x = document.createElement('section');
x.innerHTML = '<h1>From Demo</h1>';
x.className = 'slide shown';
document.getElementById('content').appendChild(x);
})()
console.log(x);
Variables can become private.
// Example of a closure
var counter = (function() {
var i = 0;
return function () {
return i++;
};
})();
console.log(counter())
console.log(counter())
We can make factories
// Bigger example of a closure
var countBy = function(inc) {
var count = -inc;
return function() {
count += inc;
return count;
}
};
c = countBy(6);
d = countBy(2);
console.log(c())
console.log(d())
console.log(c())
console.log(d())
Object properties can be accessed with either . or [].
o.name;
o['callMe']();
o[1]
And properties can always be added/reassigned
f.name = 'asdf';
f.obj = o;
Object properties that are methods have a special variable this added to scope.
var f = function (arg1, arg2) {
arg2 = arg2 || 'earth';
console.log(`called by ${this.name}`)
console.log('object', this);
console.log('arg1', arg1);
console.log('arg2', arg2);
}
var foo = {name: 'bar', method: f}
The following are equivalent
foo.method('hi');
f.bind(foo)('hi');
f.apply(foo, ['hi');
f.call(foo, 'hi');
The if/else if/else statement is same as in C
if (condition) {
codeBlock;
}
else if (condition2)
statement;
else {
codeBlock;
}
There is also switch..case, which we’ll see in this app’s code.
There are two equalities in JavaScript
== or != perform casting when comparing values so 12 == true is true=== or !== don’t cast, so 1 === true is `falseCasting also happens for <, <=, etc.
A logical “not” is the operator !, which does cast to booleans. So you can do !!undefined to get true.
There are while, do...while, and for loops. All follow classic C syntax, but there are special forms of for loops
var shoppingList = ['banana', 'apple', 'bread'];
shoppingList.title = 'My Groceries';
/* This will print the object's properties */
for (let i in shoppingList)
console.log(i);
/* and this prints the elements in the _iterable_ object */
for (let x of shoppingList)
console.log(x);
/* for arrays you could still do */
for (let i=0; i<shoppingList.length; i++) {
console.log(shoppingList[i]);
}
The for...of syntax behaves most like Python’s for...in loop.
Go over the code for this “app”.
Note:
Element.getElementById and .getElementsByClassNameclassList.add/remove()JavaScript is prototype-based. This is different from class-based, but has similar functionality.
var obj = new MyClass();MyClass.prototype = {foo: function() { return 'foo';}, bar: 'bar'}ownProperty
function MyClass() { this.asdf = function() {return this.bar;}obj.toString() would go to Object.prototype.toString.apply(obj)function A() {
this.varA = 'a';
}
function B() {
A.call(this);
this.varB = 'b';
}
A.prototype = { foo: 1, bar: function(x) { return this.foo + 1;}};
B.prototype = Object.create(A.prototype);
B.prototype.foo = 3;
a = new A();
b = new B();
a.bar(1);
b.bar(1);
B.prototype.foo = -1;
b.bar(1);
Just a syntactic wrapping of what we covered before.
class C extends B {
constructor(c) {
super();
this.foo = -1;
this.varC = c;
};
get foo() {
return this._foo;
};
set foo(b) {
this._foo = b;
};
}
The current state of modules is a bit complicated because of many players coming up with many solutions. See AMD, CommonJS, RequireJS, Browserify, or home-spun versions.
I won’t be covering those here, because it is so complicated.
However, after all of that, a module is often accessible as an object with the supplied functions as properties. (e.g. marked and hljs in the current site).
Many libraries can be installed with npm.