On Github abramhindle / CMPUT404-Javascript-Slides
Created by Abram Hindle abram dot hindle at ualberta dot ca Department of Computing Science University of Alberta Edmonton, Alberta, Canada Earth
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
Good resources:
Where did it come from?
What kind of language is it?
Why?
It runs in browsers (with minimal compatibility issues).
It runs on webservers.
It runs in PDFs.
It is embedded everywhere.
<script type="text/javascript"> //<![CDATA[ // ^^^ do this for XHTML Compatibility if you are going to embed javascript var someJS = "Put your javascript here"; //]]> </script>
<script> var someJS = "This works but isn't XHTML compatible"; </script> <!-- you can embed oneliners within HTML! --> <input value="test me!" type=button onclick="javascript:alert('hey look ma!');"/>
// here's a comment /* here's a variable assignment */ var variable = "A string value"; function init() { f = "Globally available don't do this!"; } function testF() { return f; } function testVariable() { var variable = "A local value!"; return variable; } init();
// Good style dictates all variables should be defined with var // this avoid confusion var variable = "A string value"; // var causes variables to be defined in their initially scope // and are made available to all functions defined within their scope. function lexical() { var shared = "share!"; // defined in this scope return function() { // shared is also defined (and shared) in this function return shared; // note how this function references shared }; // did you also see we just returned an } // anonymous function! alert( // so now we call lexical() get a function and then ( lexical() )() // call that function using () );
// Closures are functions who reference another scope // First we make a named function called makeCounter function makeCounter() { var counter = 0; // note that functions are values! var count = function() { return counter++; //post increment counter } return count; } var myCounter = makeCounter(); myCounter(); myCounter(); myCounter(); // myCounter returned 2
function cpsAdd(val1, val2, continuation) { continuation(val1 + val2); } function add1234(continuation) { cpsAdd(1,2, function(x) { cpsAdd(x,3, function(x) { // x is shadowed cpsAdd(x,4, continuation); }); }); } add1234(alert);
function cpsAddR(val1, val2) { return function(continuation) { continuation(val1 + val2); }; } function addR(continuation) { // if you don't have a return the last value // is implicitly returned! cpsAddR(4,5)( function(x) { cpsAddR(x,6)( function(y) { // both x and y are available here cpsAddR(x,y)( continuation ); }) }); } addR(alert);
var aString = "Strings"; var break = "not allowed!"; var BREAK = "This is allowed!"; var BrEAK = "Try not to abuse case sensitivity";
var aNumber = 10; var aNumber = 11.11; var aNumber = 1e-100; var aNumber = 1E+100; var nan = NaN; var inf = Infinity; var negativeInfinity = -Infinity;
var aString = ""; var anotherString ="Hi how are you"; var escapesString = "\r\n\t\f\b\/\\\\'\""; var snowMan = "\u2603"; snowMan.length === 1; aString.length === 0;
false null undefined '' 0 NaN
var empty = []; var arrayInitialized = [1,2,3,4,'5'];//mixed! var arr = new Array(10); arr[0] === undefined; arr[0] = 'Assigned'; 'Assigned' === arr[0]; arrayInitialized[4] === '5'; arrayInitialized.length === 5; arrayInitialized.splice(3,1); // delete 4 from the array (slow)
var empty = {}; var abram = { "name":"Abram Hindle", "job":"Throwing Down JS", "favorite tea":"puerh" }; var dog = { paws: 4 // note I didn't quote paws }; dog.paws === 4; abram["favorite tea"] === "puerh"; abram.name === "Abram Hindle"; abram["favorite tea"] = "oolong";
undefined.property; // Throws a type error undefined && undefined.property // returns undefined var empty = {}; empty.property === undefined; var abram = { "name":"Abram Hindle", "job":"Throwing Down JS", "favorite tea":"puerh" }; keys(abram); // produces ["name","job","favorite tea"] //prototype! var abramChild = Object.create(abram) keys(abramChild); // produces [] abramChild.name === "Abram Hindle"; // inherits keys from abram
var abram = { "name":"Abram Hindle", "job":"Throwing Down JS", "favorite tea":"puerh", "sayName": function() { alert(this.name); } }; abramChild = Object.create(abram); abramChild.name = "Child"; function doit() { abram.sayName(); abramChild.sayName(); }
var abram = { "name":"Abram Hindle", "job":"Throwing Down JS", "favorite tea":"puerh", "sayName": function() { alert(this.name); } }; abramChild = Object.create(abram); abramChild.name = "Child"; function doit() { abram.sayName(); abramChild.sayName(); }
// we can use new on person now! var Person = function() { // function is an object this.name = "Abram Hindle"; // this is the current function this.job = "Throwing Down JS"; this["favorite tea"] = "puerh"; var self = this; // you could do this if you like perl var that = this; // this is more idiomatic this.sayName = function() { var thatNameAccessor = function () { return that.name; }; var thisNameAccessor = function () { return this.name; }; alert("this:" + thisNameAccessor() + " that:" + thatNameAccessor()); } }; function doit2() { var p = new Person(); p.sayName(); }
// look a constructor! var Animal = function(name) { // function is an object this.name = name; // this is the current function this.odd = (Math.random() > 0.5); var that = this; this.likesNumber = function(x) { return (x%2 == 1)?this.odd:!this.odd; } }; function doit3() { var animal = new Animal(prompt("Name your Animal")); var num = prompt("A number your animal might like!"); alert( animal.likesNumber( num ) ? "Yes!"+animal.name+" loves it" : "No "+animal.name+" hates it!" ); }
// look a constructor! var Counter = function(name) { // function is an object this.name = name; // this is the current function this.count = 0; this.inc = function() { ++this.count; } }; function counterTest() { var counter1 = new Counter("sheep"); var counter2 = new Counter("people"); for (var i = 0 ; i < 10; i++) { counter1.inc(); counter2.inc(); } // Dynamically Add a method to all counters in the system Counter.prototype.dec = function() { --this.count }; counter2.dec(); alert("Counter1:"+counter1.count+" Counter2:"+counter2.count); }
<h1>A header title</h1> <div> Hi! <a href="http://google.ca">Click me!</a> </div>
Document
document
Get children
document.children // a list (only Elements) document.childNodes // a list of Nodes (includes text) // oh look you can dynamically make elements! var elm = document.createElement("div"); // textContent returns text of childNodes! elm.textContent = "Here's some text in that div"; elm.childNodes.length === 1; // TextNode is a node child elm.children.length === 0; // no Element children // Append it to the body document.children[0].children[1].appendChild(elm);
// Get all DIVs var divs = document.getElementsByTagName("div"); // gets all elements with class divider var dividers = document.getElementsByClassName("divider"); // get the element with the ID main var main = document.getElementById('main'); // get the element by name var ups = document.getElementsByName('up');
function addToExample() { // gets all elements with class divider var example = document.getElementsByClassName("example")[0]; var elm = document.createElement("div"); elm.textContent = "Add me!"; example.appendChild(elm); }
<div class="example"> Hi! I'm Example! </div>
function modifyStyle() { // gets all elements with class divider var examples = document.getElementsByClassName("example2"); examples.map( function(example) { example.style.borderWidth = int(10*Math.random())+"px"; }); }
<div class="example2">Hi! I'm Example2!</div> <div class="example2">So am I!</div>
$( document ).ready(function() { // Do everything you have to now that the page has loaded }
// How many slides in this document? alert( $( "section" ).length );
function note( event ) { alert("Clicked"); } /* For all list items add a click listener */ function selectExample() { $("li").click( note ); } // for all list items remove that listener we added function removeSelectExample() { $("li").off("click","",note); }
function hideIt() { $("li").hide(); } function showIt() { $("li").show(); }
function hideIt2() { $("li").fadeOut(); } function showIt2() { $("li").fadeIn(); }
function censor() { $( "button.censor" ).html("CENSORED"); }
<button class="censor" onclick="javascript:censor()"> I think _____ about ____ </button>
function getSomeJSON() { var xhr = new XMLHttpRequest(); xhr.open('GET', 'some.json'); // This is a call back xhr.onreadystatechange = function(){ // readystate tells you how the transfer is going // 4 is done if( xhr.readyState === 4 ){ // This is the HTTP Code if(xhr.status === 200){ alert(xhr.responseText); } else { alert("There was an error " + xhr.status); } } }; // finally send it xhr.send(null); }
Let's make a generic GET
function getJSON( url, successCallback ) { var xhr = new XMLHttpRequest(); xhr.open('GET', url); // This is a call back xhr.onreadystatechange = function(){ // readystate tells you how the transfer is going // 4 is done if( xhr.readyState === 4 ){ // This is the HTTP Code if(xhr.status === 200){ successCallback( xhr.responseText ); } else { alert("There was an error " + xhr.status); } } }; // finally send it xhr.send(null); }
Now let's try to do something dynamic! With callbacks
window.setInterval Lets run a function at a set interval.
window.setTimeout Lets you run a function after a period of time.
var myInterval; function startGetting() { myInterval = window.setInterval( function() { //callback var now = new Date(); var s = 1 + (now.getSeconds() % 3); var url = s + ".json"; getJSON( url, function( ourJSON ) { //another $("#ajaxy").text( ourJSON ); //callback }); },1000); // 1 second or 1000 ms }
<div id="ajaxy">AJAXY</div>
Now let's try to do something dynamic! With callbacks
window.setInterval Lets run a function at a set interval.
window.setTimeout Lets you run a function after a period of time.
function startGettingJQuery() { var myInterval = window.setInterval( function() { //callback var now = new Date(); var s = 1 + (now.getSeconds() % 3); var url = s + ".json"; $.getJSON( url, function( data ) { // JSON Parsing $("#ajaxy2").text( data.message ); }); },1000); // 1 second or 1000 ms }
<div id="ajaxy2">AJAXY2</div>
Strict subset of Javascript see http://json.org for details
function hotDogs() { var obj = { "food":"hotdog", "condiments":["ketchup","mustard","cheese"], "sausage":"weiner" }; $("#hotdog").text( JSON.stringify( obj, null, " " ) ); //pretty print var newObj = JSON.parse($("#hotdog").text()); $("#sausage").text( newObj.sausage ); }
<div id="sausage">sausage</div> <pre><span id="hotdog">hotdog</span></pre>
hotdog
Copyright 2014 (C) Abram Hindle
The textual components of this slide deck are placed under the Creative Commons Attribute-ShareAlike 4.0 International License (CC BY-SA 4.0)
The source code to this slide deck is:
Copyright (C) 2013 Hakim El Hattab, http://hakim.se Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN