From e116c71a9cb6febbe5816c7f8d7f101da2621f69 Mon Sep 17 00:00:00 2001 From: Brian Harris Date: Mon, 31 Jul 2017 16:56:07 -0700 Subject: [PATCH 01/19] testing exercises complete --- .DS_Store | Bin 0 -> 8196 bytes testing_exercise/testing.js | 46 +++++++++++++++++++++++++++++++ testing_exercise/testingSpec.js | 47 +++++++++++++++++++++++++++++++- 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..b2cb537566e0a1488e7090636348eb9776bd0bc4 GIT binary patch literal 8196 zcmeHM-EPw`6h7X@NQF=OI=v>OC=fk4=ieU2S}$M)xwTE`_K(HaB|qE#YtkXhC)p*SP) zd(NlQf@!Hi3gC%4G^B`fI)rAEWxz6E8L$jk1}p=ABLg_IIXOQ#_w`#_S_Uiw|0M(b z``{w8Y#KSyQvGzGP$2;15}H+l&fx%KTqB!CPPD`uB%z^@8Y)bPAv7HAuIbk_a-yY% zlQ6-DFe3{Sp$IiP?7ONviKdpevEJRx;Y4IyGpkbY@@X(97VXhcz9r zl`}YfSKzd!xXaZp^iT$U*1v0VG+HE9gN7I9Ye8E>{UfC ziJ9>(@g2}ly+$w_Mf6qpNeVpgP7Z(R17Et^?0do~@Kk|~5HkqCY)H3I2D7s!Ff)U= zq7Ys9LW=RUCzQ<{J~m^crgnloj6M9IbnWn?-^2UEtZ%-!Pkuj+vbFG|9+(EaJ-C<)}S zB?n26DLW6m{18|*P^Y#w8Z{c5+w1N|V|%>rj&^qH>+a_5?eW-gR&F%z?(O$ZUX5Ol z-@L~TBMEb8Q&rce Date: Tue, 1 Aug 2017 22:24:03 -0700 Subject: [PATCH 02/19] recursion exercises w/ last bonus --- .DS_Store | Bin 8196 -> 8196 bytes recursion_exercise/recursion.js | 200 ++++++++++++++++++++++++++++++++ 2 files changed, 200 insertions(+) diff --git a/.DS_Store b/.DS_Store index b2cb537566e0a1488e7090636348eb9776bd0bc4..2764d300b41e248e0862bd997fdee0a5458fa49c 100644 GIT binary patch delta 68 zcmZp1XmOa}&nUDpU^hRb&}JS1cjn3b!m5+E2v1@&)lo1qHkj-q;s_R6C&IfqP&kWm WW04foW_F2hER# arr[searchIndex]) { + foundIndex += searchIndex + 1; + helpSearch(arr.slice(searchIndex + 1), val); + } else if (val < arr[searchIndex]) { + foundIndex -= searchIndex - 1; + helpSearch(arr.slice(0, searchIndex), val); + } else if (val === arr[searchIndex]) { + foundIndex+=searchIndex; + return; + } + + } + + helpSearch(arr, val); + + return foundIndex; +} + +// base case: if the value is never found, return -1 +// Helper Function + // foundIndex should be set to offsets combined +console.log(binarySearch([1],5)); // -1 +console.log(binarySearch([1,2,3,4,5],5)); // 4 +console.log(binarySearch([1,2,3,4,5],15)); // -1 + + + +function stringifyNumbers(obj) { + +} + +var obj = { + num: 1, + test: [], + data: { + val: 4, + info: { + isRight: true, + random: 66 + } + } +} +console.log(stringifyNumbers(obj1)); +/*/ +{ + num: "1", + test: [], + data: { + val: "4", + info: { + isRight: true, + random: "66" + } + } +} +/*/ + + + + + + + + + From a30832d075c5747c2de1091935d25e14cd697151 Mon Sep 17 00:00:00 2001 From: Brian Harris Date: Tue, 1 Aug 2017 22:57:47 -0700 Subject: [PATCH 03/19] recursion exercises w/ last bonus --- recursion_exercise/recursion.js | 48 ++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/recursion_exercise/recursion.js b/recursion_exercise/recursion.js index 503ab18b..9a65b831 100644 --- a/recursion_exercise/recursion.js +++ b/recursion_exercise/recursion.js @@ -161,21 +161,51 @@ console.log(binarySearch([1,2,3,4,5],15)); // -1 function stringifyNumbers(obj) { - + var newObj = {}; + + for (var key in obj) { + if (typeof obj[key] === 'number') { + newObj[key] = obj[key].toString(); + } else if (typeof obj[key] === 'object' && Array.isArray(obj[key]) === false) { + newObj[key] = stringifyNumbers(obj[key]); + } else { + newObj[key] = obj[key]; + } + } + + return newObj; } -var obj = { - num: 1, - test: [], - data: { +// Store data in a new object +// No need for Helper +// Base Case: when the for loop ends! +// Examine each key's type + // If the type is object, set the element to the result of recurse! + // If not, add the key,value pair to the object and move on + // Of course, if it's a number, stringify that crap! + // Return the new object! + +var obj1 = { + num: 1, + test: [], + data: { val: 4, info: { - isRight: true, - random: 66 + isRight: true, + random: 66, + nested: { + inner: { + nestedInner: { + another: { + num: 10 + } + } + } + } } + } } -} -console.log(stringifyNumbers(obj1)); +console.log(JSON.stringify(stringifyNumbers(obj1))); /*/ { num: "1", From 120083ab51ee5bd5d522ff36ae399e02c105691e Mon Sep 17 00:00:00 2001 From: Brian Harris Date: Thu, 3 Aug 2017 06:21:01 -0700 Subject: [PATCH 04/19] almost done with lodas basic exercises --- lodash_exercise/lodash.js | 318 +++++++++++++++++++++++++++++++++++--- 1 file changed, 293 insertions(+), 25 deletions(-) diff --git a/lodash_exercise/lodash.js b/lodash_exercise/lodash.js index 483d734a..c10595a0 100644 --- a/lodash_exercise/lodash.js +++ b/lodash_exercise/lodash.js @@ -1,77 +1,345 @@ -function drop(){ - +// Create a slice of array with n elements dropped from the beginning +// Starts at the element just past the dropped elements, adds to a temp array and returns when loop is done +// This could also be implemented with slice but where is the fun in that? +function drop(arr, num=1){ + var temp = []; + if (num > arr.length) return temp; + for (var i = num; i < arr.length; i++) { + temp.push(arr[i]); + } + return temp; } -function fromPairs(){ - +// Example inputs / outputs +console.log(drop([1,2,3,4,5,6], 2)); // [3,4,5,6] + +// Changes an array of key-value pairs (represented as arrays, themselves) into an object and returns the object +// Loop through the array, creating a key for the object from sub-array[0] and passing the value from sub-array[1] +function fromPairs(arr){ + var temp = {}; + for (var i = 0; i < arr.length; i++) { + temp[arr[i][0]] = arr[i][1]; + } + return temp; } -function head(){ +// Example inputs / outputs +console.log(fromPairs([['a', 1], ['b', 2]])); // {'a': 1, 'b': 2} +// Returns the first element of an array +function head(arr){ + return arr[0]; } -function take(){ - +console.log(head([1,2,3])); // 1 +console.log(head([])); // undefined; + +// Creates a slice of array with n elements taken from the beginning. +// Start at the beginning, loop through add n elements to a temp array and return it. +function take(arr, num=1){ + var temp = []; + if (num > arr.length) return arr; + for (var i = 0; i < num; i++) { + temp.push(arr[i]); + } + return temp; } -function takeRight(){ +console.log(take([1, 2, 3]));// => [1] +console.log(take([1, 2, 3], 2));// => [1, 2] +console.log(take([1, 2, 3], 5));// => [1, 2, 3] + +// Creates a slice of array with n elements taken from the end. +// Start at the length-1 - num, loop through add n elements to a temp array and return it. +function takeRight(arr, num=1){ + var temp = []; + if (num > arr.length) return arr; + for (var i = arr.length-num; i < arr.length; i++) { + temp.push(arr[i]); + } + return temp; } +console.log("takeRight: " + takeRight([1, 2, 3]));// => [3] +console.log("takeRight: " + takeRight([1, 2, 3], 2));// => [2, 3] +console.log("takeRight: " + takeRight([1, 2, 3], 5));// => [1, 2, 3] + +// Creates an array of unique values, in order, from all given arrays using SameValueZero for equality comparisons. +// Create a lookup object. create a key for all found elements and push element into array, as long as the key didn't +// previously exist function union(){ + var lookup = {} + var temp = []; + var newArr = []; -} + if (arguments.length === 0) return newArr; + if (arguments.length === 1) return arguments[0]; -function zipObject(){ + for (var i = 0; i < arguments.length; i++) { + temp = temp.concat(arguments[i]); + } + for (var j = 0; j < temp.length; j++) { + if (temp[j] in lookup === false) { + lookup[temp[j]] = true; + newArr.push(temp[j]); + } + } + + return newArr; } -function includes(){ +console.log(union([2], [1, 2]));// => [2, 1] -} +function zipObject(arr1, arr2){ + var temp = {}; + if (arr1.length === 0 || arr2.length === 0) return null; -function sample(){ + for (var i = 0; i < arr1.length; i++) { + temp[arr1[i]] = arr2[i]; + } + return temp; +} +console.log(zipObject(['a', 'b'], [1, 2]));// => { 'a': 1, 'b': 2 } + +//Checks if value is in collection. If collection is a string, it's checked for a substring of value, +// otherwise SameValueZero is used for equality comparisons. If fromIndex is negative, it's used as the offset +// from the end of collection. +function includes(collection, value, fromIndex=0){ + if (Array.isArray(collection)) { + // Do array things + if (fromIndex > collection.length) return false; + if (fromIndex >= 0) { + for (var i = fromIndex; i < collection.length; i++) { + if (collection[i] === value) return true; + } + } else { + for (var i = collection.length-fromIndex; i >= 0; i--) { + if (collection[i] === value) return true; + } + } + + } else if (typeof collection === 'object') { + // Do object things + for (var key in collection) { + if (collection[key] === value) return true; + } + } else if (typeof collection === 'string') { + // Do string things + if (collection.search(value) > -1) return true; + } + + // How did you get here?! You should not be here! + return false; } -function cloneDeep(){ +console.log("includes: " + includes([1, 2, 3], 1, -1));// => true +console.log(includes('abcd', 'bc'));// => true +// Gets a random element from collection. +function sample(collection){ + if (collection.length === 0) return collection[0]; + return collection[Math.floor(Math.random() * collection.length)]; } -function sumBy(){ +// +function cloneDeep(value){ + if (!value) return {}; + + if (Array.isArray(value)) { + var temp = []; + for (var i = 0; i < value.length; i++) { + temp.push(cloneDeep(value[i])); + } + return temp; + } else if (typeof value === 'object') { + var obj = {}; + for (var key in value) { + obj[key] = cloneDeep(value[key]); + } + return obj; + } else { + return value; + } +} +var objectsToClone = [{ 'a': 1 }, { 'b': 2 }]; +var shallow = cloneDeep(objectsToClone); +console.log("clone deep: " + JSON.stringify(shallow)); +console.log(shallow[0] === objectsToClone[0]);// => true + +var objey = { + stuff: "foo", + data: { + val: { + thing: { + info: "bar", + moreInfo: { + evenMoreInfo: { + weMadeIt: "baz" + } + } + } + } + } } -function inRange(){ +var cloney = cloneDeep(objey); +console.log("clone deep: " + JSON.stringify(cloney)); + +//This method is like _.sum except that it accepts iteratee which is invoked for each element in array to +//generate the value to be summed. The iteratee is invoked with one argument: (value). +function sumBy(arr, iteratee=null){ + var sum = 0; + for (var i = 0; i < arr.length; i++) { + if (typeof iteratee === 'function') { + sum += iteratee(arr[i]); + } else if (typeof iteratee == 'string') { + sum += arr[i][iteratee]; + } else { + sum += arr[i]; + } + } + + return sum; +} +var objects1 = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }]; +console.log("sumBy: " + sumBy(objects1, 'n')); +// => 20 + +//Checks if n is between start and up to, but not including, end. If end is not specified, +// it's set to start with start then set to 0. If start is greater than end the params are +// swapped to support negative ranges. +function inRange(num, start, end){ + if (arguments.length === 2) { + end = start; + start = 0; + } else if (start > end) { + var temp = end; + end = start; + start = temp; + } + + if (num >= start && num < end) + return true; + + return false; +} +console.log("inRange: " + inRange(4,8)); + +// Checks if path is a direct property of object. +// Base Case: if we do not find the object after all possible depth tests +function has(object, path){ + if (path.length === 0) return false; + if (Array.isArray(path)) { + if (path.length === 0) return false; // Can it ever really get here? + if (path.length === 1) return path[0] in object; + + if (path[0] in object) { + return has(object[path[0]], path.slice(1)); + } else { + return false; + } + } else if (typeof path === 'string') { + if (path.length > 1) { + return has (object[path[0]], path.split(".")); + } else { + return path in object; + } + } } -function has(){ +var hasObject = { 'a': { 'b': 2 } }; +console.log("has: " + has(hasObject, ['a', 'b'])); -} -function omit(){ +//this method creates an object composed of the own and inherited enumerable property +//paths of object that are not omitted. +// Base Case: we've run out of elements in paths +function omit(object, paths){ + var omitObj = {}; + var newObj = {}; -} + for (var i = 0; i < paths.length; i++) { + omitObj[paths[i]] = true; + } -function pick(){ + for (var key in object) { + if (key in omitObj === false) { + newObj[key] = object[key]; + } + } + return newObj; } -function pickBy(){ +function pick(object, paths){ + var newObj = {}; + for (var i = 0; i < paths.length; i++) { + newObj[paths[i]] = object[paths[i]]; + } + + return newObj; } -function omitBy(){ +function pickBy(object, testFunc){ + var newObj = {}; + if (typeof testFunc !== "function") return {}; + + for (var key in object) { + if (testFunc(object[key])) + newObj[key] = object[key]; + } + return newObj; } -function padEnd(){ +function omitBy(object, testFunc){ + var omitObj = {}; + var newObj = {}; + if (typeof testFunc !== "function") return {}; + + for (var key in object) { + if (testFunc(object[key])) + omitObj[key] = object[key]; + } + for (var key in object) { + if (key in omitObj === false) { + newObj[key] = object[key]; + } + } + + return newObj; +} + +function padEnd(string='', length=0, chars=' '){ + var paddedStr = string; + while (paddedStr.length < length) { + paddedStr = paddedStr.concat(chars); + } + if (length > string.length) + return paddedStr.slice(0, length); + else + return paddedStr; } -function repeat(){ +console.log("padEnd: " + padEnd('abc', 6)); +// => 'abc ' + +function repeat(string='', n=1){ + var repeatedStr = string; + if (n === 0) return ""; + + for (var i = 1; i < n; i++) { + repeatedStr = repeatedStr.concat(string); + } + return repeatedStr; } function upperFirst(str){ From 0f423a075a86862c37897df025f662f528488c69 Mon Sep 17 00:00:00 2001 From: Brian Harris Date: Thu, 3 Aug 2017 09:07:25 -0700 Subject: [PATCH 05/19] Basic Lodash exercises finished --- lodash_exercise/lodash.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lodash_exercise/lodash.js b/lodash_exercise/lodash.js index c10595a0..5307ed03 100644 --- a/lodash_exercise/lodash.js +++ b/lodash_exercise/lodash.js @@ -343,11 +343,24 @@ function repeat(string='', n=1){ } function upperFirst(str){ - + return str.charAt(0).toUpperCase() + str.slice(1); } -function flatten(){ +// Flattens array a single level deep. +// Base Case: We run out of elements in the aray (any) +function flatten(array){ + var flattenedArr = []; + + for (var i = 0; i < array.length; i++) { + if (Array.isArray(array[i])) { + for (var j = 0; j < array[i].length; j++) + flattenedArr.push(array[i][j]); + } else { + flattenedArr.push(array[i]); + } + } + return flattenedArr; } function zip(){ From 0eac2bd7facfc663f2a37f038c54a508876cdb65 Mon Sep 17 00:00:00 2001 From: Brian Harris Date: Thu, 3 Aug 2017 14:23:00 -0700 Subject: [PATCH 06/19] Finished Random Shape Game --- canvas_exercise/.DS_Store | Bin 0 -> 6148 bytes canvas_exercise/shapes_game/index.js | 92 ++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 canvas_exercise/.DS_Store diff --git a/canvas_exercise/.DS_Store b/canvas_exercise/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c4c55869e3848cc8a1b30aa11c03af106a661c33 GIT binary patch literal 6148 zcmeHK&1%~~5T141R>qY2P)KvzOCSda;dES zNZzO~(8o!>{c%WeeN9c7f!S{~n%UKUyXM)Yv~qE4dD!bF9L(A(oPbm!Ixtd&{eG#k0B z-{B~UvwUywk0@=FpFMx!RVrTPrT4u%RMT!AVw}bFFj;6iZ z>#r)!gE)=G55iAR;&h;+$cM-^1NCZKv)PBYAM0|r*=)?~a<;$!sV?8Y zYtHAMx4GT;(&=CP_&K|p|GG9aB7t3O zGT_cDuez=u$lt{bFa!UL0ewD5s7BvmVbL5NXiNzJEW>RCw*FbvIntr;u&{_X5Mfh+ zHdVM1L)diqrHk_&78Y$f30HgwH?nXQiZG+2e`&%=_!hZk2AF}z4CvYqQq%YU!Rq?o z1aZR*Fa!T51ESpSwp*B+yIYrLsqb0|?L)QbxWeLn3Jh} Date: Thu, 3 Aug 2017 16:09:59 -0700 Subject: [PATCH 07/19] Added a low-rent particle system --- canvas_exercise/shapes_game/index.js | 86 +++++++++++++++++++++++++--- 1 file changed, 79 insertions(+), 7 deletions(-) diff --git a/canvas_exercise/shapes_game/index.js b/canvas_exercise/shapes_game/index.js index ed9df84a..bb2dab72 100644 --- a/canvas_exercise/shapes_game/index.js +++ b/canvas_exercise/shapes_game/index.js @@ -10,6 +10,11 @@ window.addEventListener("load", function() { var x = Math.random() * (width - 100); var y = Math.random() * (height - 100); + effectOn = false; + clearInterval(initParticlesTimer); + clearInterval(particlesInterval); + clearTimeout(stopParticleTimer); + switch(shapeNum) { case 0: // Red Triangle ctx.fillStyle = "red"; @@ -20,10 +25,16 @@ window.addEventListener("load", function() { ctx.lineTo(x,y); ctx.fill(); ctx.closePath(); + initParticlesTimer = setTimeout(function() { + blastShape(x,y); + }, 800); return "red0"; case 1: // White Square ctx.fillStyle = "white"; ctx.fillRect(x,y,100,100); + initParticlesTimer = setTimeout(function() { + blastShape(x,y); + }, 800); return "white1" case 2: // White Triangle ctx.fillStyle = "white"; @@ -34,12 +45,17 @@ window.addEventListener("load", function() { ctx.lineTo(x,y); ctx.fill(); ctx.closePath(); + initParticlesTimer = setTimeout(function() { + blastShape(x,y); + }, 800); return "white0"; default: // Red Square ctx.fillStyle = "red"; ctx.fillRect(x,y,100,100); + initParticlesTimer = setTimeout(function() { + blastShape(x,y); + }, 800); return "red1"; - } } @@ -62,11 +78,11 @@ window.addEventListener("load", function() { } function startTimer(timerSpan) { - var timer = setInterval(function() { - timerSpan.innerText = Number(timerSpan.innerText) - 1; + intervalId = setInterval(function() { + timerSpan.innerText = Number(timerSpan.innerText) - 1; if (Number(timerSpan.innerText) === 0) { - clearInterval(timer); + clearInterval(intervalId); endGame(); } }, 1000); @@ -75,11 +91,51 @@ window.addEventListener("load", function() { function endGame() { expectedKey = undefined; gameOn = false; - // return undefined :D + effectOn = false; restartGame(ctx, width, height, scoreSpan, timerSpan); } - // NEED TO HAVE AN END-GAME SCREEN and input moves to a reset game. + // MAYBE implement this + function randomEffect(randomNum) { + + } + + function blastShape(x, y) { + + clear(ctx, height, width); + var tempX = 0; + var tempY = 0; + effectOn = true; + for (var i = 0; i < particles.length; i++) { + particles[i].x = Math.floor(Math.random() * 50) + x; + particles[i].y = Math.floor(Math.random() * 50) + y; + particles[i].velX = Math.floor(Math.random() * 5 - 2.5); + particles[i].velY = Math.floor(Math.random() * 5 - 2.5); + } + + + particlesInterval = setInterval(function() { + if (effectOn) { + clear(ctx, canvas.width, canvas.height); + for (var j = 0; j < particles.length; j++) { + ctx.fillRect(particles[j].x,particles[j].y,2,2); + particles[j].x += particles[j].velX; + particles[j].y += particles[j].velY; + } + particleTimer = setTimeout(function() { + if (effectOn) { + clearInterval(particlesInterval); + effectOn = false; + clear(ctx, canvas.width, canvas.height); + } + }, 2000); + } + }, 50); + } + +/* + Initialize game and variables +*/ var canvas = document.getElementById("shapes-game"), height = canvas.scrollHeight, @@ -93,11 +149,27 @@ window.addEventListener("load", function() { timerSpan = document.getElementById("time-remaining"), scoreSpan = document.getElementById("score-val"), seconds = 3, - intervalId; + intervalId, + particles = [], + initParticlesTimer, + particlesInterval, + stopParticleTimer, + effectOn = false;; canvas.width = width; canvas.height = height; + // Set up the particles only once;. + for (var i = 0; i < 50; i++) { + var particle = { + x: 0, + y: 0, + velX: 10, + velY: 10 + } + particles.push(particle); + } + document.addEventListener("keyup", function(event) { if (gameOn === false) { startTimer(timerSpan); From 5f33877396028303d560122349ea724becd6c823 Mon Sep 17 00:00:00 2001 From: Brian Harris Date: Thu, 3 Aug 2017 16:15:50 -0700 Subject: [PATCH 08/19] Fixed particle timer bug --- canvas_exercise/shapes_game/index.js | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/canvas_exercise/shapes_game/index.js b/canvas_exercise/shapes_game/index.js index bb2dab72..1754a442 100644 --- a/canvas_exercise/shapes_game/index.js +++ b/canvas_exercise/shapes_game/index.js @@ -11,7 +11,7 @@ window.addEventListener("load", function() { var y = Math.random() * (height - 100); effectOn = false; - clearInterval(initParticlesTimer); + clearTimeout(initParticlesTimer); clearInterval(particlesInterval); clearTimeout(stopParticleTimer); @@ -103,8 +103,6 @@ window.addEventListener("load", function() { function blastShape(x, y) { clear(ctx, height, width); - var tempX = 0; - var tempY = 0; effectOn = true; for (var i = 0; i < particles.length; i++) { particles[i].x = Math.floor(Math.random() * 50) + x; @@ -112,7 +110,14 @@ window.addEventListener("load", function() { particles[i].velX = Math.floor(Math.random() * 5 - 2.5); particles[i].velY = Math.floor(Math.random() * 5 - 2.5); } - + + particleTimer = setTimeout(function() { + if (effectOn) { + clearInterval(particlesInterval); + effectOn = false; + clear(ctx, canvas.width, canvas.height); + } + }, 2000); particlesInterval = setInterval(function() { if (effectOn) { @@ -122,13 +127,6 @@ window.addEventListener("load", function() { particles[j].x += particles[j].velX; particles[j].y += particles[j].velY; } - particleTimer = setTimeout(function() { - if (effectOn) { - clearInterval(particlesInterval); - effectOn = false; - clear(ctx, canvas.width, canvas.height); - } - }, 2000); } }, 50); } From 5eeddf30e5277c4ccba4e995734449c23d1e7b4b Mon Sep 17 00:00:00 2001 From: Brian Harris Date: Thu, 3 Aug 2017 16:34:26 -0700 Subject: [PATCH 09/19] speed up particles, no biggie --- canvas_exercise/shapes_game/index.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/canvas_exercise/shapes_game/index.js b/canvas_exercise/shapes_game/index.js index 1754a442..3187ffd2 100644 --- a/canvas_exercise/shapes_game/index.js +++ b/canvas_exercise/shapes_game/index.js @@ -27,14 +27,14 @@ window.addEventListener("load", function() { ctx.closePath(); initParticlesTimer = setTimeout(function() { blastShape(x,y); - }, 800); + }, 500); return "red0"; case 1: // White Square ctx.fillStyle = "white"; ctx.fillRect(x,y,100,100); initParticlesTimer = setTimeout(function() { blastShape(x,y); - }, 800); + }, 500); return "white1" case 2: // White Triangle ctx.fillStyle = "white"; @@ -47,14 +47,14 @@ window.addEventListener("load", function() { ctx.closePath(); initParticlesTimer = setTimeout(function() { blastShape(x,y); - }, 800); + }, 500); return "white0"; default: // Red Square ctx.fillStyle = "red"; ctx.fillRect(x,y,100,100); initParticlesTimer = setTimeout(function() { blastShape(x,y); - }, 800); + }, 500); return "red1"; } } @@ -107,8 +107,8 @@ window.addEventListener("load", function() { for (var i = 0; i < particles.length; i++) { particles[i].x = Math.floor(Math.random() * 50) + x; particles[i].y = Math.floor(Math.random() * 50) + y; - particles[i].velX = Math.floor(Math.random() * 5 - 2.5); - particles[i].velY = Math.floor(Math.random() * 5 - 2.5); + particles[i].velX = Math.floor(Math.random() * 10 - 5); + particles[i].velY = Math.floor(Math.random() * 10 - 5); } particleTimer = setTimeout(function() { From d0ad58d1c23bdcf84c7a7942aea5adb00394991a Mon Sep 17 00:00:00 2001 From: Brian Harris Date: Thu, 3 Aug 2017 16:38:24 -0700 Subject: [PATCH 10/19] fixed bug with decrementing score --- canvas_exercise/shapes_game/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/canvas_exercise/shapes_game/index.js b/canvas_exercise/shapes_game/index.js index 3187ffd2..639ca754 100644 --- a/canvas_exercise/shapes_game/index.js +++ b/canvas_exercise/shapes_game/index.js @@ -179,6 +179,8 @@ window.addEventListener("load", function() { if (expectedKey !== undefined) { if (event.keyCode === expectedKeysMap[expectedKey]) { scoreSpan.innerText = Number(scoreSpan.innerText) + 1; + } else if (event.keyCode == 38 || event.keyCode=== 40 || event.keyCode=== 37 || event.keyCode=== 39){ + scoreSpan.innerText = Number(scoreSpan.innerText) - 1; } } From a6ec5643baa3c554f4d98e5432e84774ad42fc79 Mon Sep 17 00:00:00 2001 From: Brian Harris Date: Mon, 7 Aug 2017 17:24:51 -0700 Subject: [PATCH 11/19] finished hacker news clone --- jquery_exercise/.DS_Store | Bin 0 -> 6148 bytes jquery_exercise/Files/.DS_Store | Bin 0 -> 6148 bytes jquery_exercise/Files/logo | Bin 0 -> 11421 bytes jquery_exercise/Files/logo.png | Bin 0 -> 11421 bytes jquery_exercise/app.css | 107 ++++++++++++++++++ jquery_exercise/app.js | 86 ++++++++++++++ jquery_exercise/index.html | 61 ++++++++++ ...inserthtml.com.custom-checkbox-radio-2.zip | Bin 0 -> 1695 bytes 8 files changed, 254 insertions(+) create mode 100644 jquery_exercise/.DS_Store create mode 100644 jquery_exercise/Files/.DS_Store create mode 100644 jquery_exercise/Files/logo create mode 100644 jquery_exercise/Files/logo.png create mode 100644 jquery_exercise/app.css create mode 100644 jquery_exercise/app.js create mode 100644 jquery_exercise/index.html create mode 100644 jquery_exercise/inserthtml.com.custom-checkbox-radio-2.zip diff --git a/jquery_exercise/.DS_Store b/jquery_exercise/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ddc8cd3903267cf83e15d3b0caa8233570afdcc9 GIT binary patch literal 6148 zcmeHK(QeZ)6usWMEgeGi0jYb;3lc(OYT3jdCZwnvNP9ynf(Jlb(o{5%##NHiu~L*5 z{$YFqf5IQ|A$$OwYr9pJ!YfqBx3bUm^*wfT+}Je{iOx7|6E%p)L1C$_N6uWf8@IrX|zzv;a0 z4&T~OIA zgLC)-r}TvHyJ-^3eOGqW%^6rpCv_^wJP;c2wBRlq86U4eDoZ1DO2 z_|NzM>m=K<3RngHD+NUDqx>EZaSby3by*f_7ys3@q+ajYCZig!?yq0eOp W=ou_DA_B921e6T6vI_iF1%3hQLaKHE literal 0 HcmV?d00001 diff --git a/jquery_exercise/Files/.DS_Store b/jquery_exercise/Files/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a077ef92a6484c028cb8db39721b2814cd3bc64c GIT binary patch literal 6148 zcmeHKF;2ul474FdB%14>Oi6`AO|v>31vMW)2hueWp`lO5vth>eA#xEd1sY5CWY?aJ zGDW;LGvB_y+?s97tcMfrgJEsV(^qy@J4ELh599Q_AE!Omao~!v-XOQL(Iz|Cbi%(w z?)ozpM?A5C3KUUy`(v0#e{#Dd64iaks@MRc~E=9DD5me}W$k owNZ``tr!@s7z?)Is~>d(pOJ5cb7Ii3A9SED0@Ot&1^z;TFRtDt>i_@% literal 0 HcmV?d00001 diff --git a/jquery_exercise/Files/logo b/jquery_exercise/Files/logo new file mode 100644 index 0000000000000000000000000000000000000000..f287ec174723e5e8068ace6e3def179884c39bfd GIT binary patch literal 11421 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 literal 0 HcmV?d00001 diff --git a/jquery_exercise/Files/logo.png b/jquery_exercise/Files/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f287ec174723e5e8068ace6e3def179884c39bfd GIT binary patch literal 11421 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 literal 0 HcmV?d00001 diff --git a/jquery_exercise/app.css b/jquery_exercise/app.css new file mode 100644 index 00000000..03f9bca2 --- /dev/null +++ b/jquery_exercise/app.css @@ -0,0 +1,107 @@ +.container { + display: flex; + justify-content: center; +} + +.content_column { + background-color: #f4deab; +} + +.header { + height: 48; + display: inline-flex; + align-items: center; + background-color: #f9571b; + width: 800px; +} + +.border_round { + border-radius: 4px; +} + +.border_round_sm { + border-radius: 2px; + border-width:1px; + border-style: solid; +} + +#logo { + width: 32px; + height: 32px; + margin-left: 12px; +} + +#title_page { + margin-left: 12px; + margin-right: 12px; +} + +#subFav_links { + margin-left: 24px; + padding-left: 12px; +} + +#submission { + margin-left: 128px; + padding-left: 12px; + margin-bottom: 32px; +} + +#form_submit { + margin-top: 12px; + margin-bottom: 12px; +} + +.input { + margin-top: 8px; + margin-bottom: 8px; +} + +#input_label1 { + position: relative; + text-align: right; + left: 0px; +} + +#input_label2 { + position: relative; + text-align: right; + left: 8px; +} + +#input_text1 { + position:relative; + left: 30px; + width: 128px; + height: 24px; +} + +#input_text2 { + position:relative; + left: 37px; + width: 128px; + height: 24px; +} + +#button_submit { + position:relative; + left: 60px; + width: 64px; + height: 32px; +} + +.visible { + display:list-item; +} + +.invisible { + display:none; +} + +.tiny_text { + font-size: 10px; +} + +.link_filter { + text-decoration: none; +} \ No newline at end of file diff --git a/jquery_exercise/app.js b/jquery_exercise/app.js new file mode 100644 index 00000000..d5536dfa --- /dev/null +++ b/jquery_exercise/app.js @@ -0,0 +1,86 @@ +$(document).ready(function() { + var $linkSubmit = $("#link_submit"); + var $formSubmit = $("#submission"); + var $btnSubmit = $("#form_submit"); + var $list = $("#list_links"); + var $btnFavorites = $("#link_fav"); + var favoritesOnly = false; + var urlFilterOn = false; + + $linkSubmit.on("click", function() { + $formSubmit.eq(0).slideToggle(250); + }); + + $btnSubmit.on("submit", function (e) { + e.preventDefault(); + + // GRAB THE TEXT BOXES HERE + var $title = $('#input_text1').val(); + var $url = ($('#input_text2').val()).replace("http://", ""); + + var $listItem = $("
  • ", { + }); + + $listItem.html(` + ${$title} + (${$url}) + `); + + $list.append($listItem); + + $formSubmit.eq(0).slideToggle(250); + }); + + $btnFavorites.on("click", function() { + favoritesOnly = !favoritesOnly; + + $("#list_links li").each(function() { + if (urlFilterOn === false) { + var $checkbox = $(this).children().eq(0); + + if ($checkbox.prop("checked") === false) { + $(this).toggleClass("visible invisible"); + } + } else { + $(this).addClass("visible"); + $(this).removeClass("invisible"); + } + }); + + if (urlFilterOn) { + urlFilterOn = false; + favoritesOnly = false; + $btnFavorites.text("favorites"); + } + + if (favoritesOnly === true) { + $list.css("list-style-type", "none"); + } else { + $list.css("list-style-type", "decimal"); + } + + // Just in case this was off! + $list.on('click', ".link_filter", listCallback); + }); + + $list.on('click', ".link_filter", listCallback); + + function listCallback(e) { + $btnFavorites.text("all"); + urlFilterOn = true; + favoritesOnly = false; + var $urlLink = $(e.target).text(); + + + $("#list_links li").each(function() { + var $linkText = $(this).children().eq(2).children().eq(0).text(); + if ($linkText !== $urlLink) { + $(this).toggleClass("visible invisible"); + }; + }); + + $list.css("list-style-type", "none"); + $list.off('click'); + + }; +}); \ No newline at end of file diff --git a/jquery_exercise/index.html b/jquery_exercise/index.html new file mode 100644 index 00000000..71abbd4f --- /dev/null +++ b/jquery_exercise/index.html @@ -0,0 +1,61 @@ + + + + + Document + + + + +
    +
    +
    + +
    +

    Hack or Snooze

    +
    + +
    + +
    + +
    +
    + + \ No newline at end of file diff --git a/jquery_exercise/inserthtml.com.custom-checkbox-radio-2.zip b/jquery_exercise/inserthtml.com.custom-checkbox-radio-2.zip new file mode 100644 index 0000000000000000000000000000000000000000..f70655d274ee4973c08f0a29bcd7c68731ea1882 GIT binary patch literal 1695 zcmZXVdo0kACNr&hPU%&v~Bboaekh|GZz%8)FR-k^)56IuErM4Qwbe z009sJy?sLW`-Kn#oLx5o=d&@GGEEGI50V1PZ=p%IwYOb=!E>qKNmdR#`dUs8S>lr`M$=Y4C}Eu z!92%DB3-@raAVRQ`{YKqhK|IO-y}bhY<6WG|CDTQNxKz`rKoAaDv+)*yWfgSCJb}1 z(}t-!c$WFOMj!n;FOnD)`%YbEsv#3}Kp^bmbc$=4bmDtZT#8GY8P5oPM)u*6$!LsJ z&>o+LI??QN${e1D~kB0(pd8fdfWwT-_H%HIGzfBx~Kad?aM3yM;S+L`{w$v@& z=rcaPD!q>+$n_IM1u6^}uY5;E6G|X-(>;{(9D{L*t!{~{LHX^t%z_<*{y${g7-?U9 zsX-noL~-^CO@=gSJGlGoO!qWdt62}qY%#QJlOH|!*Ut2#M)8NE7nq}p+MuhTjzgdZ z;k;Ow-<*8^n~5+2z0=ppGoM+hZlO2Mh(@R9Gg-$1qYxff? zgFA+8#X_!y(Bum7X8Hy1jt`~Ie}3V|qG@@v(Wr{7i*EYyMu9YxTv?Kd(>^jFZ$4s= zZx))gd;Um`)8;+(L5PpI?K!u^Otyh-32B8We1A2b-!7Z+OytpArb?5d#mmjFO+euy zFq;DCke}`HR;DQ#*R&8Rbw2zkkLoWOSV3|f*7yO&Sc`~ungr*-!2obh3;-~{UFEL% zKUW2ZPy&2(_v3?u*IgALX^&Z7>#kzs9M)Wgh_H)@W%#kGV`VH}A9Bj7B{;I_&J!Ms zK~bR6{pQaJeYQ(qP+Z`85~J@RLDLG#UkY0s3eT0h`7Lv0TcT;)jH8AgWoMFQii!)@ z0d%4JpM#1s(i9-G`cxzB5_e8z>)|5o{VQHoEbxbhnbO|=E0Q%Qh=>bfx{CRj%;~-p zUz6u1MzSTh7>vod@7x?~wxy@oCBRa{AigsOd-E#{nFnqm6jWpZZ;-x`a3$X5;f!=B zbv&vvyCxf#dN!qK2mJL7-R(nEuR)#eHiw#rcjpGdJhN!=l2NeWVDcqXnqq-O`Bst{7q0rEcYYm9j?bGcS!dnZ|@_mqDY49Q_V_D z?_rIiCuNWF%Z*~8VY3g7v4wK+~sn^7STa(1N_RP=i)#Lv7OGo;+p6)u!blfK7 zgB?%;p56rEa=H{$AV+treq=aeJ5z9CVFS}X@AwZpL!5hDR&&&?4=@&Pv|r8&OfOWq zY#U=X_f`s;E|Jzh=3tvgLpU=`-^1E#E?#)**Tl)o;n`{45%9)I9Ya)m{f8fW8l3s8 zao8PQJ={L+^4S~>5$&+1fL(4{-|x@+^H!6ioGYKi?Du|0PNYdSR)?RNGNwXMy{fIb zz4>mb#n-&!Z@J^yXo61Z?ds;$D27a=OvDhe@!3e46`%6MzH4knB~H*Ik!=5j^n-<0{C2DbD@|zL`%k?5QU!0b_$f1P` zJ7g}}2u|LaQXctSglEkmz#i5nHp)uPqP-qHBBYnN;#qJQ&B!=H!v4*2Ra${O=kLg$ zs0t(tC-D#faM-ktDhMnM`5gfpF%|>X9{g7(cdxD=HU@&|uR!=iV-5I?`hRNR);@@h X_>2C+A7c#_UY`J7>$tTY^z-&F2tDrG literal 0 HcmV?d00001 From 2dba1a0e81a1d2200a29fababa31e303eb6b987e Mon Sep 17 00:00:00 2001 From: Brian Harris Date: Tue, 8 Aug 2017 23:27:15 -0700 Subject: [PATCH 12/19] First commit, signup appears close to ready --- ajax_with_jquery_exercise/.DS_Store | Bin 0 -> 6148 bytes ajax_with_jquery_exercise/app.css | 117 +++++++++++++ ajax_with_jquery_exercise/index.html | 77 +++++++++ ajax_with_jquery_exercise/index.js | 246 +++++++++++++++++++++++++++ 4 files changed, 440 insertions(+) create mode 100644 ajax_with_jquery_exercise/.DS_Store create mode 100644 ajax_with_jquery_exercise/app.css create mode 100644 ajax_with_jquery_exercise/index.html create mode 100644 ajax_with_jquery_exercise/index.js diff --git a/ajax_with_jquery_exercise/.DS_Store b/ajax_with_jquery_exercise/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d146cfece060e3836c0817715c35d3d53ca12e13 GIT binary patch literal 6148 zcmeHKyG{c!5S)cb9MGhsbV(J7n&uRRf|?&7$ss{>A&7uPc?}=K_wfNR>)ngE;|eN- z&~D_NwY_7XM~WW+Wcpm40b>9Ki=t>SVA?#`wdctrqU14_*kXHGZY)tv$7JqD{`p+G1Q3WNfoz>gH*nXOhF8-@=BLV-|Vr-1GciAAw=Yz*_( zL6@HZM7>65W2~2E>Q*7v*Q`x8>+{)HJWr ofX29U31CI{k(1nM{Yhiym5z;}j-u_EPK=8{79?CK@Cyoj0@1-k82|tP literal 0 HcmV?d00001 diff --git a/ajax_with_jquery_exercise/app.css b/ajax_with_jquery_exercise/app.css new file mode 100644 index 00000000..7a7c225d --- /dev/null +++ b/ajax_with_jquery_exercise/app.css @@ -0,0 +1,117 @@ +.container { + display: flex; + justify-content: center; +} + +.content_column { + background-color: #f4deab; +} + +.header { + height: 48; + display: inline-flex; + align-items: center; + background-color: #f9571b; + width: 800px; +} + +.border_round { + border-radius: 4px; +} + +.border_round_sm { + border-radius: 2px; + border-width:1px; + border-style: solid; +} + +#logo { + width: 32px; + height: 32px; + margin-left: 12px; +} + +#title_page { + margin-left: 12px; + margin-right: 12px; +} + +#fav_links { + margin-left: 24px; + padding-left: 12px; +} + +.loginSignup_div { + margin-left: 128px; + padding-left: 12px; + margin-bottom: 32px; +} + +#form_submit { + margin-top: 12px; + margin-bottom: 12px; +} + +.input { + margin-top: 8px; + margin-bottom: 8px; +} + +.inputA { + position: relative; + text-align: right; + left: 0px; +} + +.inputB { + position: relative; + text-align: right; + left: 0px; +} + +.input_textA { + position:relative; + left: 24px; + width: 128px; + height: 24px; +} + +.input_textB { + position:relative; + left: 24px; + width: 128px; + height: 24px; +} + +#button_submit { + position:relative; + left: 92px; + width: 64px; + height: 32px; +} + +.visible { + visibility: hidden; +} + +.invisible { + visibility: visible; +} + +.tiny_text { + font-size: 10px; +} + +.link_menu{ + text-decoration: none; +} + +.signup_link { + position:relative; + right: -410px; +} + +.login_link { + position:relative; + right: -420px; +} \ No newline at end of file diff --git a/ajax_with_jquery_exercise/index.html b/ajax_with_jquery_exercise/index.html new file mode 100644 index 00000000..8c2e8cea --- /dev/null +++ b/ajax_with_jquery_exercise/index.html @@ -0,0 +1,77 @@ + + + + + Document + + + + +
    +
    +
    +
    +

    Hack or Snooze

    +
    + + + +
    + + +
    + +
    +
    + + \ No newline at end of file diff --git a/ajax_with_jquery_exercise/index.js b/ajax_with_jquery_exercise/index.js new file mode 100644 index 00000000..cf34d412 --- /dev/null +++ b/ajax_with_jquery_exercise/index.js @@ -0,0 +1,246 @@ +$(document).ready(function() { + var loggedIn = JSON.parse(localStorage.getItem("hos_loggedIn")); + console.log(loggedIn); + var $list = $("#list_links"); + var $lnkFavorites = $("#link_fav"); + var $lnkLogin = $("#link_login"); + var $lnkSignup = $("#link_signup"); + var $loginDiv = $("#login_div"); + var $signupDiv = $("#signup_div"); + var $btnLogin = $("#login_form"); + var $btnSignup = $("#signup_form"); + + /* DEV SETTINGS */ + //localStorage.removeItem("hos_top10Cached"); + var top10Cached = JSON.parse(localStorage.getItem("hos_top10Cached")); + //loggedIn=true; + //localStorage.setItem("hos_loggedIn", false); + /* DEV SETTINGS */ + + // A few things need to change if user is logged in... + if (loggedIn === true) { + // The formatting is super ugly when it goes to log out... + $lnkLogin.text("log out"); + $lnkSignup.addClass("invisible"); + $lnkSignup.removeClass("visible"); + } + + if (top10Cached) { + $list.append(buildList(top10Cached, loggedIn)); + } else { + createTopStoryList(10).then(function(response) { + $list.append(buildList(response, loggedIn)); + + /* DEV SETTINGS */ + localStorage.setItem("hos_top10Cached", JSON.stringify(response)); + /* DEV SETTINGS */ + }) + .fail(function(err) { + console.log("ERROR: " + err); + }); + } + + $lnkLogin.on('click', function() { + if (loggedIn === false) { + $loginDiv.eq(0).slideToggle(250); + } else { + $lnkLogin.text("log in"); + localStorage.setItem("hos_loggedIn", false); + } + }); + + $lnkSignup.on('click', function() { + $signupDiv.eq(0).slideToggle(250); + }); + + $btnSignup.on('click', function(event) { + // *********MUST CHECK IF THE USERNAME AND PW WAS EVEN VALID! + + var username = $("#input_text3").val(); + var password = $("#input_text4").val(); + console.log($(event.target).attr("id")) + if ($(event.target).attr("id") === "signup_submit") { + $.ajax({ + method: "POST", + headers: { + "Content-Type": "application/json" + }, + url: "https://hn-favorites.herokuapp.com/signup", + data: JSON.stringify({ + email: username, + password: password + }) + }) + .then(function(data) { + console.log(data.auth_token); + localStorage.setItem("hos_autoToken", data.auth_token); + }) + .fail(err => console.warn(err)); + } + + // Tried to do it this way: + /*$.post("https://hn-favorites.herokuapp.com/signup", { + headers: { + "Content-Type": "application/json" + }, + email: username, + password: password + }) + .then(function(response) { + console.log(response); + })*/ + }) + + /*$btnSubmit.on('click', function() { + + });*/ + + //$btnSubmit.on('click'); + /*var $linkSubmit = $("#link_submit"); + var $formSubmit = $("#submission"); + + + var $btnFavorites = $("#link_fav"); + var favoritesOnly = false; + var urlFilterOn = false;*/ + + /*$linkSubmit.on("click", function() { + $formSubmit.eq(0).slideToggle(250); + }); + + $btnSubmit.on("submit", function (e) { + e.preventDefault(); + + // GRAB THE TEXT BOXES HERE + var $title = $('#input_text1').val(); + var $url = ($('#input_text2').val()).replace("http://", ""); + + var $listItem = $("
  • ", { + }); + + $listItem.html(` + ${$title} + (${$url}) + `); + + $list.append($listItem); + + $formSubmit.eq(0).slideToggle(250); + }); + + $btnFavorites.on("click", function() { + favoritesOnly = !favoritesOnly; + + $("#list_links li").each(function() { + if (urlFilterOn === false) { + var $checkbox = $(this).children().eq(0); + + if ($checkbox.prop("checked") === false) { + $(this).toggleClass("visible invisible"); + } + } else { + $(this).addClass("visible"); + $(this).removeClass("invisible"); + } + }); + + if (urlFilterOn) { + urlFilterOn = false; + favoritesOnly = false; + $btnFavorites.text("favorites"); + } + + if (favoritesOnly === true) { + $list.css("list-style-type", "none"); + } else { + $list.css("list-style-type", "decimal"); + } + + // Just in case this was off! + $list.on('click', ".link_filter", listCallback); + }); + + $list.on('click', ".link_filter", listCallback); + + function listCallback(e) { + $btnFavorites.text("all"); + urlFilterOn = true; + favoritesOnly = false; + var $urlLink = $(e.target).text(); + + + $("#list_links li").each(function() { + var $linkText = $(this).children().eq(2).children().eq(0).text(); + if ($linkText !== $urlLink) { + $(this).toggleClass("visible invisible"); + }; + }); + + $list.css("list-style-type", "none"); + $list.off('click'); + + };*/ +}); + +function createTopStoryList(n) { + // This function needs to pull the list of top stories, then iterate through the top n, + // doing a get request for each + + return $.get("https://hacker-news.firebaseio.com/v0/topstories.json?") + .then(function(response) { + var promises = response.slice(0, n).map(function(currentVal) { + return $.get(`https://hacker-news.firebaseio.com/v0/item/${currentVal}.json`) + }); + + return Promise.all(promises) + }); +} + +function buildList(responseList, loggedIn) { + var $listItems = []; + var $listItem; + var url; + var index; + var visible = loggedIn? "visible" : "invisible"; + + responseList.forEach(function(val) { + $listItem = $("
  • ", { + }); + + //url = val.url; + index = val.url.indexOf("://"); + url = val.url.slice(index+3); + index = url.indexOf("/"); + url = url.slice(0, index); + + $listItem.html(` + ${val.title} + (${url}) + `); + + $listItems.push($listItem); + }); + return $listItems; +} + +function setVisible($list, visible) { + $list.each(function(val) { + if (visible) { + val.addClass("visible_checkbox"); + val.removeClass("invisible"); + } else { + val.removeClass("visible_checkbox"); + val.addClass("invisible"); + } + }); +} + + + + + + + + + + From 35c5f7e4fed37ffe4774c0406a1813234bf12021 Mon Sep 17 00:00:00 2001 From: Brian Harris Date: Tue, 8 Aug 2017 23:59:02 -0700 Subject: [PATCH 13/19] A few small bug fixes, cleanup, 'working' login menu top bar --- ajax_with_jquery_exercise/app.css | 16 +++++++++--- ajax_with_jquery_exercise/index.html | 4 +-- ajax_with_jquery_exercise/index.js | 37 +++++++++++++++++++--------- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/ajax_with_jquery_exercise/app.css b/ajax_with_jquery_exercise/app.css index 7a7c225d..20b9fbf5 100644 --- a/ajax_with_jquery_exercise/app.css +++ b/ajax_with_jquery_exercise/app.css @@ -83,19 +83,27 @@ height: 24px; } -#button_submit { +.button_submit { position:relative; - left: 92px; + left: 70px; width: 64px; height: 32px; } .visible { - visibility: hidden; + visibility: visible; } .invisible { - visibility: visible; + visibility: hidden; +} + +.displayNone { + display:none; +} + +.displayBlock { + display:block; } .tiny_text { diff --git a/ajax_with_jquery_exercise/index.html b/ajax_with_jquery_exercise/index.html index 8c2e8cea..4834faca 100644 --- a/ajax_with_jquery_exercise/index.html +++ b/ajax_with_jquery_exercise/index.html @@ -34,7 +34,7 @@

    Hack or Snooze

    - +
    @@ -49,7 +49,7 @@

    Hack or Snooze

    - +
    diff --git a/ajax_with_jquery_exercise/index.js b/ajax_with_jquery_exercise/index.js index cf34d412..d2edf333 100644 --- a/ajax_with_jquery_exercise/index.js +++ b/ajax_with_jquery_exercise/index.js @@ -1,6 +1,7 @@ $(document).ready(function() { var loggedIn = JSON.parse(localStorage.getItem("hos_loggedIn")); - console.log(loggedIn); + console.log("Logged In: " + loggedIn); + var $list = $("#list_links"); var $lnkFavorites = $("#link_fav"); var $lnkLogin = $("#link_login"); @@ -18,12 +19,7 @@ $(document).ready(function() { /* DEV SETTINGS */ // A few things need to change if user is logged in... - if (loggedIn === true) { - // The formatting is super ugly when it goes to log out... - $lnkLogin.text("log out"); - $lnkSignup.addClass("invisible"); - $lnkSignup.removeClass("visible"); - } + toggleLoginMenuMode($lnkLogin, $lnkSignup, loggedIn); if (top10Cached) { $list.append(buildList(top10Cached, loggedIn)); @@ -44,8 +40,10 @@ $(document).ready(function() { if (loggedIn === false) { $loginDiv.eq(0).slideToggle(250); } else { - $lnkLogin.text("log in"); - localStorage.setItem("hos_loggedIn", false); + loggedIn = false; + localStorage.setItem("hos_loggedIn", loggedIn); + toggleLoginMenuMode($lnkLogin, $lnkSignup, loggedIn); + setChecksVisible($list, loggedIn); } }); @@ -58,7 +56,7 @@ $(document).ready(function() { var username = $("#input_text3").val(); var password = $("#input_text4").val(); - console.log($(event.target).attr("id")) + if ($(event.target).attr("id") === "signup_submit") { $.ajax({ method: "POST", @@ -74,6 +72,9 @@ $(document).ready(function() { .then(function(data) { console.log(data.auth_token); localStorage.setItem("hos_autoToken", data.auth_token); + localStorage.setItem("hos_loggedIn", true); + loggedIn = true; + toggleLoginMenuMode($lnkLogin, $lnkSignup, loggedIn); }) .fail(err => console.warn(err)); } @@ -223,7 +224,8 @@ function buildList(responseList, loggedIn) { return $listItems; } -function setVisible($list, visible) { +// NOT CURRENTLY WORKING +function setChecksVisible($list, visible) { $list.each(function(val) { if (visible) { val.addClass("visible_checkbox"); @@ -235,6 +237,19 @@ function setVisible($list, visible) { }); } +function toggleLoginMenuMode($lnkLogin, $lnkSignup, loggedIn) { + if (loggedIn === true) { + // The formatting is super ugly when it goes to log out... + debugger; + $lnkLogin.text("log out"); + $lnkSignup.addClass("displayNone"); + $lnkSignup.removeClass("displayBlock"); + } else { + $lnkLogin.text("log in"); + $lnkSignup.addClass("displayBlock"); + $lnkSignup.removeClass("displayNone"); + } +} From 094eb689e432831b543210c825b2adeb850a8f81 Mon Sep 17 00:00:00 2001 From: Brian Harris Date: Wed, 9 Aug 2017 13:16:53 -0700 Subject: [PATCH 14/19] got login and sign out working --- ajax_with_jquery_exercise/app.css | 8 +- ajax_with_jquery_exercise/index.html | 25 ++----- ajax_with_jquery_exercise/index.js | 105 ++++++++++++++++++++------- 3 files changed, 93 insertions(+), 45 deletions(-) diff --git a/ajax_with_jquery_exercise/app.css b/ajax_with_jquery_exercise/app.css index 20b9fbf5..c3ced98b 100644 --- a/ajax_with_jquery_exercise/app.css +++ b/ajax_with_jquery_exercise/app.css @@ -107,7 +107,7 @@ } .tiny_text { - font-size: 10px; + font-size: 11px; } .link_menu{ @@ -122,4 +122,10 @@ .login_link { position:relative; right: -420px; +} + +.text_by { + position: relative; + left:22px; + font-size: 12px; } \ No newline at end of file diff --git a/ajax_with_jquery_exercise/index.html b/ajax_with_jquery_exercise/index.html index 4834faca..6f001f8c 100644 --- a/ajax_with_jquery_exercise/index.html +++ b/ajax_with_jquery_exercise/index.html @@ -27,11 +27,11 @@

    Hack or Snooze

    - +
    - +
    @@ -42,11 +42,11 @@

    Hack or Snooze

    - +
    - +
    @@ -55,21 +55,8 @@

    Hack or Snooze

    +
    diff --git a/ajax_with_jquery_exercise/index.js b/ajax_with_jquery_exercise/index.js index d2edf333..1db830ff 100644 --- a/ajax_with_jquery_exercise/index.js +++ b/ajax_with_jquery_exercise/index.js @@ -3,6 +3,7 @@ $(document).ready(function() { console.log("Logged In: " + loggedIn); var $list = $("#list_links"); + var $favs = $("#list_favs"); var $lnkFavorites = $("#link_fav"); var $lnkLogin = $("#link_login"); var $lnkSignup = $("#link_signup"); @@ -18,6 +19,8 @@ $(document).ready(function() { //localStorage.setItem("hos_loggedIn", false); /* DEV SETTINGS */ + /* Initialization */ + // A few things need to change if user is logged in... toggleLoginMenuMode($lnkLogin, $lnkSignup, loggedIn); @@ -51,9 +54,34 @@ $(document).ready(function() { $signupDiv.eq(0).slideToggle(250); }); - $btnSignup.on('click', function(event) { - // *********MUST CHECK IF THE USERNAME AND PW WAS EVEN VALID! + // Combine these two into a single function and pass whether login or signup? + $btnLogin.on('click', function(event) { + var username = $("#input_text3").val(); + var password = $("#input_text4").val(); + + if ($(event.target).attr("id") === "login_submit") { + $.ajax({ + method: "POST", + headers: { + "Content-Type": "application/json" + }, + url: "https://hn-favorites.herokuapp.com/login", + data: JSON.stringify({ + email: username, + password: password + }) + }) + .then(function(data) { + loginMaintenance(data); + }) + .fail(function(err) { + console.warn("Auth Token Error: " + err); + alert("Log In: Please enter a valid email address and password!"); + }); + } + }) + $btnSignup.on('click', function(event) { var username = $("#input_text3").val(); var password = $("#input_text4").val(); @@ -70,27 +98,50 @@ $(document).ready(function() { }) }) .then(function(data) { - console.log(data.auth_token); - localStorage.setItem("hos_autoToken", data.auth_token); - localStorage.setItem("hos_loggedIn", true); - loggedIn = true; - toggleLoginMenuMode($lnkLogin, $lnkSignup, loggedIn); + loginMaintenance(data); }) - .fail(err => console.warn(err)); + .fail(function(err) { + console.warn("Auth Token Error: " + err); + alert("Sign Up: Please enter a valid email address and password!"); + }); + } + }); + + function loginMaintenance(data) { + console.log(data.auth_token); + localStorage.setItem("hos_autoToken", data.auth_token); + localStorage.setItem("hos_loggedIn", true); + loggedIn = true; + $loginDiv.eq(0).slideUp(250); + $signupDiv.eq(0).slideUp(250); + toggleLoginMenuMode($lnkLogin, $lnkSignup, loggedIn); + setChecksVisible($list, loggedIn); + } + + $list.on('click', function(event){ + if ($(event.target).attr('type') === 'checkbox') { + if ($(event.target).is(':checked')) { + // REQUEST IT BE A FAVORITE + } else { + // REQUEST IT BE REMOVED FROM FAVORITES + } } + }); - // Tried to do it this way: - /*$.post("https://hn-favorites.herokuapp.com/signup", { - headers: { - "Content-Type": "application/json" - }, - email: username, - password: password + $lnkFavorites.on('click', function() { + $.ajax({ + method: "GET", + headers: { + "Authorization": localStorage.getItem("hos_autoToken") + }, + url: "https://hn-favorites.herokuapp.com/stories.json", }) - .then(function(response) { - console.log(response); - })*/ - }) + .then(function(response) { + console.log(response); + + // HERE IS WHERE WE WILL FILL THE FAVORITES LIST + }); + }); /*$btnSubmit.on('click', function() { @@ -217,6 +268,7 @@ function buildList(responseList, loggedIn) { $listItem.html(` ${val.title} (${url}) +
    by ${val.by}
    `); $listItems.push($listItem); @@ -226,13 +278,17 @@ function buildList(responseList, loggedIn) { // NOT CURRENTLY WORKING function setChecksVisible($list, visible) { - $list.each(function(val) { + var $children = $list.children(); + + $children.each(function(index) { + var $subChildren = $children.eq(index).children(); + if (visible) { - val.addClass("visible_checkbox"); - val.removeClass("invisible"); + $($subChildren[0]).addClass("visible"); + $($subChildren[0]).removeClass("invisible"); } else { - val.removeClass("visible_checkbox"); - val.addClass("invisible"); + $($subChildren[0]).removeClass("visible"); + $($subChildren[0]).addClass("invisible"); } }); } @@ -240,7 +296,6 @@ function setChecksVisible($list, visible) { function toggleLoginMenuMode($lnkLogin, $lnkSignup, loggedIn) { if (loggedIn === true) { // The formatting is super ugly when it goes to log out... - debugger; $lnkLogin.text("log out"); $lnkSignup.addClass("displayNone"); $lnkSignup.removeClass("displayBlock"); From a36e07aa642e281c1af23662e9bde9f6ec1eaf93 Mon Sep 17 00:00:00 2001 From: Brian Harris Date: Wed, 9 Aug 2017 17:02:37 -0700 Subject: [PATCH 15/19] complete --- call_apply_bind_exercise/callApplyBind.js | 107 ++++++++++++++++++++++ call_apply_bind_exercise/readme.md | 10 +- 2 files changed, 111 insertions(+), 6 deletions(-) diff --git a/call_apply_bind_exercise/callApplyBind.js b/call_apply_bind_exercise/callApplyBind.js index e69de29b..cd51dbe3 100644 --- a/call_apply_bind_exercise/callApplyBind.js +++ b/call_apply_bind_exercise/callApplyBind.js @@ -0,0 +1,107 @@ +// - Write a function called `sumEvenArguments` which takes all of the arguments passed to a function and returns the sum of the even ones. +function sumEvenArguments() { + var args = [].slice.call(arguments); + console.log(args); + var sum = 0; + for (var i = 0; i < args.length; i++) { + if (args[i] % 2 === 0) sum += args[i]; + } + return sum; +} + +// ```javascript +console.log(sumEvenArguments(1,2,3,4)); // 6 +console.log(sumEvenArguments(1,2,6)); // 8 +console.log(sumEvenArguments(1,2)); // 2 +// ``` + + +// - Write a function called `arrayFrom` which converts an array-like-object into an array. + +function arrayFrom() { + return [].slice.apply(arguments); +} + + +// ```javascript +// function sample(){ +// var arr = arrayFrom(arguments) +// if(!arr.reduce) throw "This is not an array!" +// return arr.reduce(function(acc,next){ +// return acc+next; +// },0) +// } +// ``` + +// Write a function called `invokeMax` which accepts a function and a maximum amount. `invokeMax` should return a +// function that when called increments a counter. If the counter is greater than the maximum amount, the inner +// function should return "Maxed Out" + +function invokeMax(fn, maximum) { + var counter = 0; + + return function () { + + if (++counter > maximum) + return "Maxed Out!"; + + return fn.apply(this, arguments); + } +} + +function sayHi(count) { + console.log("Hi! Count: " + count); +} + + +// ```javascript +// function add(a,b){ +// return a+b +// } + +// var addOnlyThreeTimes = invokeMax(add,3); +// addOnlyThreeTimes(1,2) // 3 +// addOnlyThreeTimes(2,2) // 4 +// addOnlyThreeTimes(1,2) // 3 +// addOnlyThreeTimes(1,2) // "Maxed Out!" +// ``` + + +function guessingGame(amount) { + var answer = Math.floor(Math.random() * 11); + var guesses = 0; + var alreadyWon = false; + + return function(guess) { + if (alreadyWon) return "Dude you already won! Restart this beast." + if (guesses >= amount) return "Sorry buddy, you have exceeded your guesses!"; + guesses++; + if (guess === answer) { + alreadyWon = true; + return "You got it! Guesses: " + guesses;; + } + else if (guess < answer) { + return "You're too low! Guesses Remaining: " + (amount - guesses); + } else { + return "You're too high! Guesses Remaining: " + (amount - guesses); + } + } +} + +var game = guessingGame(5); +console.log(game(1)); +console.log(game(2)); +console.log(game(7)); +console.log(game(8)); +console.log(game(9)); +console.log(game(4)); + + + + + + + + + + diff --git a/call_apply_bind_exercise/readme.md b/call_apply_bind_exercise/readme.md index cbc3cd03..756b82b3 100644 --- a/call_apply_bind_exercise/readme.md +++ b/call_apply_bind_exercise/readme.md @@ -5,17 +5,15 @@ Fix the following code: ```javascript var obj = { fullName: "Harry Potter", - person: { - sayHi: function(){ - return "This person's name is " + this.fullName - } + sayHi: function(){ + return "This person's name is " + this.fullName } } ``` - List two examples of "array-like-objects" that we have seen. - - - - + - arguments + - Rest operator ### Functions to write: From d7a7d5236bfde5cf5ef24a17f8d584fbf499c784 Mon Sep 17 00:00:00 2001 From: Brian Harris Date: Wed, 9 Aug 2017 22:28:57 -0700 Subject: [PATCH 16/19] Broken! POST list.on returns Bad --- ajax_with_jquery_exercise/index.js | 145 ++++++++++------------------- 1 file changed, 50 insertions(+), 95 deletions(-) diff --git a/ajax_with_jquery_exercise/index.js b/ajax_with_jquery_exercise/index.js index 1db830ff..ba875bd4 100644 --- a/ajax_with_jquery_exercise/index.js +++ b/ajax_with_jquery_exercise/index.js @@ -3,8 +3,6 @@ $(document).ready(function() { console.log("Logged In: " + loggedIn); var $list = $("#list_links"); - var $favs = $("#list_favs"); - var $lnkFavorites = $("#link_fav"); var $lnkLogin = $("#link_login"); var $lnkSignup = $("#link_signup"); var $loginDiv = $("#login_div"); @@ -12,6 +10,11 @@ $(document).ready(function() { var $btnLogin = $("#login_form"); var $btnSignup = $("#signup_form"); + // FAVORITES + var $favs = $("#list_favs"); + var $lnkFavorites = $("#link_fav"); + var favContainer = {}; + /* DEV SETTINGS */ //localStorage.removeItem("hos_top10Cached"); var top10Cached = JSON.parse(localStorage.getItem("hos_top10Cached")); @@ -79,7 +82,7 @@ $(document).ready(function() { alert("Log In: Please enter a valid email address and password!"); }); } - }) + }); $btnSignup.on('click', function(event) { var username = $("#input_text3").val(); @@ -121,7 +124,44 @@ $(document).ready(function() { $list.on('click', function(event){ if ($(event.target).attr('type') === 'checkbox') { if ($(event.target).is(':checked')) { - // REQUEST IT BE A FAVORITE + + var $siblings = $(event.target).siblings(); // Get Parent + var $key = $(event.target).attr('id'); + // Add this checkbox to the local container of favorites. + favContainer[$key] = { + $url: $($siblings[1]).text().replace("(", "").replace(")", ""), + $by: $($siblings[2]).text().slice(3), + $title: $($siblings[0]).text() + } + + // FAIL + $.ajax({ + method: "POST", + headers: { + "Content-Type": "application/json", + "Authorization": localStorage.getItem("hos_autoToken") + }, + url: "https://hn-favorites.herokuapp.com/stories.json", + data: { + hacker_news_story: { ///// THIS IS FAILING. JSON Turns this into a bad string + by: favContainer.$by, + story_id: favContainer.$key, + title: favContainer.$title, + url: favContainer.$url + } + } + }) + .then(function(data) { + console.log("Favorite Data Returned: " + data); + }) + .fail(function(err) { + var loc = localStorage.getItem("hos_autoToken") + console.warn("Add Favorite Error: " + err); + //alert("Log In: Please enter a valid email address and password!"); + }); + + + } else { // REQUEST IT BE REMOVED FROM FAVORITES } @@ -140,98 +180,14 @@ $(document).ready(function() { console.log(response); // HERE IS WHERE WE WILL FILL THE FAVORITES LIST + // Also hide the regular list and show the favorites only. + }) + .fail(function(response) { + // What happens when we fail? }); }); - /*$btnSubmit.on('click', function() { - - });*/ - - //$btnSubmit.on('click'); - /*var $linkSubmit = $("#link_submit"); - var $formSubmit = $("#submission"); - - - var $btnFavorites = $("#link_fav"); - var favoritesOnly = false; - var urlFilterOn = false;*/ - - /*$linkSubmit.on("click", function() { - $formSubmit.eq(0).slideToggle(250); - }); - - $btnSubmit.on("submit", function (e) { - e.preventDefault(); - - // GRAB THE TEXT BOXES HERE - var $title = $('#input_text1').val(); - var $url = ($('#input_text2').val()).replace("http://", ""); - - var $listItem = $("
  • ", { - }); - - $listItem.html(` - ${$title} - (${$url}) - `); - - $list.append($listItem); - - $formSubmit.eq(0).slideToggle(250); - }); - - $btnFavorites.on("click", function() { - favoritesOnly = !favoritesOnly; - - $("#list_links li").each(function() { - if (urlFilterOn === false) { - var $checkbox = $(this).children().eq(0); - - if ($checkbox.prop("checked") === false) { - $(this).toggleClass("visible invisible"); - } - } else { - $(this).addClass("visible"); - $(this).removeClass("invisible"); - } - }); - - if (urlFilterOn) { - urlFilterOn = false; - favoritesOnly = false; - $btnFavorites.text("favorites"); - } - - if (favoritesOnly === true) { - $list.css("list-style-type", "none"); - } else { - $list.css("list-style-type", "decimal"); - } - - // Just in case this was off! - $list.on('click', ".link_filter", listCallback); - }); - - $list.on('click', ".link_filter", listCallback); - - function listCallback(e) { - $btnFavorites.text("all"); - urlFilterOn = true; - favoritesOnly = false; - var $urlLink = $(e.target).text(); - - $("#list_links li").each(function() { - var $linkText = $(this).children().eq(2).children().eq(0).text(); - if ($linkText !== $urlLink) { - $(this).toggleClass("visible invisible"); - }; - }); - - $list.css("list-style-type", "none"); - $list.off('click'); - - };*/ }); function createTopStoryList(n) { @@ -258,14 +214,13 @@ function buildList(responseList, loggedIn) { responseList.forEach(function(val) { $listItem = $("
  • ", { }); - - //url = val.url; + index = val.url.indexOf("://"); url = val.url.slice(index+3); index = url.indexOf("/"); url = url.slice(0, index); - $listItem.html(` + $listItem.html(` ${val.title} (${url})
    by ${val.by}
    From bd3b0afbbec8793b9ca9dcdd982aa080059cccb5 Mon Sep 17 00:00:00 2001 From: Brian Harris Date: Thu, 10 Aug 2017 15:00:40 -0700 Subject: [PATCH 17/19] up to part II --- prototypes_exercise/prototypes.js | 59 +++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/prototypes_exercise/prototypes.js b/prototypes_exercise/prototypes.js index e69de29b..d3414c73 100644 --- a/prototypes_exercise/prototypes.js +++ b/prototypes_exercise/prototypes.js @@ -0,0 +1,59 @@ +function Person(firstName, lastName, favoriteColor, favoriteNumber) { + this.firstName = firstName; + this.lastName = lastName; + this.favoriteColor = favoriteColor; + this.favoriteNumber = favoriteNumber; + this.favoriteFoods = []; + this.family = []; +} + +Person.prototype.fullName = function() { + return this.firstName + " " + this.lastName; +} + +var p = new Person("Shana", "Malarkin", "Green", 38); +console.log(p.fullName()); // Shana Malarkin + +Person.prototype.toString = function() { + return this.firstName + " " + this.lastName + ", Favorite Color: " + this.favoriteColor + + ", Favorite Number: " + this.favoriteNumber; +} + +//var p1 = new Person("Shana", "Malarkin", "Green", 38); +console.log(p.toString()); // Shana Malarkin, Favorite Color: Green, Favorite Number: 38 + +Person.prototype.addToFamily = function(object) { + if (object instanceof Person) + if (this.family.indexOf(object) === -1) + this.family.push(object); + + return this.family.length; +} + +Array.prototype.map = function(fn, thisArg) { +// if (thisArg) this = thisArg; How do we handle this?! + var newArray = []; + + for (var i = 0; i < this.length; i++) { + newArray.push(fn(this[i], i, this)); + } + + return newArray; +} + +String.prototype.reverse = function() { + var reverse = ""; + + for (var i = this.length - 1; i >= 0; i--) { + reverse = reverse.concat(this[i]); + } + + return reverse; +} + +Function.prototype.bind = function(thisArg, ...outerArgs) { + var _this = this; + return function() { + return _this.apply(thisArg, [...outerArgs, ...arguments]); + } +} \ No newline at end of file From b8520f1b8abff2218c36007a31bd817f2a8265cf Mon Sep 17 00:00:00 2001 From: Brian Harris Date: Thu, 10 Aug 2017 16:02:02 -0700 Subject: [PATCH 18/19] add reduce function --- ajax_with_jquery_exercise/readme.md | 4 +- call_apply_bind_exercise/readme.md | 2 +- oop_examples/flash-card-oop/Card.js | 4 + oop_examples/flash-card-oop/CardView.css | 41 +++++++ oop_examples/flash-card-oop/CardView.js | 59 +++++++++++ oop_examples/flash-card-oop/FlashCardDeck.js | 25 +++++ oop_examples/flash-card-oop/index.html | 19 ++++ oop_examples/flash-card-oop/main.js | 13 +++ oop_examples/tetris-oop/css/global.css | 6 ++ oop_examples/tetris-oop/index.html | 23 ++++ oop_examples/tetris-oop/js/grid.js | 103 ++++++++++++++++++ oop_examples/tetris-oop/js/gridItem.js | 3 + oop_examples/tetris-oop/js/main.js | 7 ++ oop_examples/tetris-oop/js/point.js | 4 + oop_examples/tetris-oop/js/shape.js | 42 ++++++++ oop_examples/tetris-oop/js/tetris.js | 106 +++++++++++++++++++ oop_examples/tetris-oop/js/tetromino.js | 105 ++++++++++++++++++ oop_examples/tetris-oop/readme.md | 16 +++ prototypes_exercise/prototypes.js | 53 +++++++++- prototypes_exercise/prototypesSpec.js | 31 +++++- recursion_exercise/recursionSpec.js | 6 +- 21 files changed, 664 insertions(+), 8 deletions(-) create mode 100644 oop_examples/flash-card-oop/Card.js create mode 100644 oop_examples/flash-card-oop/CardView.css create mode 100644 oop_examples/flash-card-oop/CardView.js create mode 100644 oop_examples/flash-card-oop/FlashCardDeck.js create mode 100644 oop_examples/flash-card-oop/index.html create mode 100644 oop_examples/flash-card-oop/main.js create mode 100644 oop_examples/tetris-oop/css/global.css create mode 100644 oop_examples/tetris-oop/index.html create mode 100644 oop_examples/tetris-oop/js/grid.js create mode 100644 oop_examples/tetris-oop/js/gridItem.js create mode 100644 oop_examples/tetris-oop/js/main.js create mode 100644 oop_examples/tetris-oop/js/point.js create mode 100644 oop_examples/tetris-oop/js/shape.js create mode 100644 oop_examples/tetris-oop/js/tetris.js create mode 100644 oop_examples/tetris-oop/js/tetromino.js create mode 100644 oop_examples/tetris-oop/readme.md diff --git a/ajax_with_jquery_exercise/readme.md b/ajax_with_jquery_exercise/readme.md index 25afa52e..7dd5c354 100644 --- a/ajax_with_jquery_exercise/readme.md +++ b/ajax_with_jquery_exercise/readme.md @@ -90,9 +90,9 @@ curl -H "Content-Type: application/json" \ https://hn-favorites.herokuapp.com/stories.json ``` -__Stories API - DELETE /stories/:story_id.json__ +__Stories API - DELETE /stories/:id.json__ -To delete a favorite story, you will need the id created by the api. For example, a delete request might to the following url: +To delete a favorite story, you will need the id created by the api. For example, a delete request might be to the following url: ``` https://hn-favorites.herokuapp.com/stories/2.json diff --git a/call_apply_bind_exercise/readme.md b/call_apply_bind_exercise/readme.md index 756b82b3..1cdfee71 100644 --- a/call_apply_bind_exercise/readme.md +++ b/call_apply_bind_exercise/readme.md @@ -39,7 +39,7 @@ function sample(){ } ``` -Write a function called `invokeMax` which accepts a function and a maximum amount. `invokeMax` should return a function that when called increments a counter. If the counter is greater than the maximum amount, the inner function should return "Maxed Out" +Write a function called `invokeMax` which accepts a function and a maximum amount. `invokeMax` should return a function that when called increments a counter. If the counter is greater than the maximum amount, the inner function should return "Maxed Out!" ```javascript function add(a,b){ diff --git a/oop_examples/flash-card-oop/Card.js b/oop_examples/flash-card-oop/Card.js new file mode 100644 index 00000000..b4d98c26 --- /dev/null +++ b/oop_examples/flash-card-oop/Card.js @@ -0,0 +1,4 @@ +function Card(front, back) { + this.front = front; + this.back = back; +} diff --git a/oop_examples/flash-card-oop/CardView.css b/oop_examples/flash-card-oop/CardView.css new file mode 100644 index 00000000..df39e982 --- /dev/null +++ b/oop_examples/flash-card-oop/CardView.css @@ -0,0 +1,41 @@ +.card { + width: 270px; + height: 400px; + padding: 5px; + background-color: grey; + border-radius: 15px; + text-align: center; + font-size: 2em; +} + +.inner-card { + width: 100%; + height: 100%; + border-radius: 15px; + line-height: 400px; +} + +.front-card { + background-color: white; +} + +.back-card { + background-color: lightgrey; +} + +.hidden { + display: none; +} + +.next-button { + background-color: #008CBA; + border: none; + color: white; + padding: 15px 32px; + text-align: center; + text-decoration: none; + border-radius: 20px; + display: inline-block; + font-size: 16px; + margin: 10px; +} diff --git a/oop_examples/flash-card-oop/CardView.js b/oop_examples/flash-card-oop/CardView.js new file mode 100644 index 00000000..879c7639 --- /dev/null +++ b/oop_examples/flash-card-oop/CardView.js @@ -0,0 +1,59 @@ +function CardView(containerDivId, card=null) { + this.containerDivId = containerDivId; + this.containerDiv = document.getElementById(containerDivId); + this.card = card; + + this.cardDiv = document.createElement('div'); + this.cardDiv.className = "card"; + + var front = document.createElement('div'); + front.className = 'inner-card front-card'; + if (this.card) { + front.innerHTML = this.card.front; + } + var back = document.createElement('div'); + back.className = 'inner-card back-card hidden'; + + if (this.card) { + back.innerHTML = this.card.back; + } + + this.cardDiv.append(front); + this.cardDiv.append(back); + this.containerDiv.append(this.cardDiv); + + this.cardDiv.addEventListener('click', this.flip.bind(this)); +} + +CardView.prototype.flip = function() { + var divs = this.cardDiv.getElementsByTagName('div'); + if (divs.length === 2 && divs[0].className.indexOf("hidden") >= 0) { + var index = divs[0].className.indexOf("hidden") + divs[0].className = divs[0].className.slice(0, index - 1); + divs[1].className = divs[1].className + " hidden"; + } else if (divs.length === 2) { + var index = divs[0].className.indexOf("hidden") + divs[1].className = divs[1].className.slice(0, index - 1); + divs[0].className = divs[0].className + " hidden"; + } +} + +CardView.prototype.updateCard = function(card) { + this.card = card; + var divs = this.cardDiv.getElementsByTagName('div'); + if (divs.length === 2) { + divs[0].innerHTML = this.card.front; + divs[1].innerHTML = this.card.back; + } +} + + + + + + + + + + + diff --git a/oop_examples/flash-card-oop/FlashCardDeck.js b/oop_examples/flash-card-oop/FlashCardDeck.js new file mode 100644 index 00000000..4f032e58 --- /dev/null +++ b/oop_examples/flash-card-oop/FlashCardDeck.js @@ -0,0 +1,25 @@ +function FlashCardDeck(cards) { + this.cards = cards.map(function(c) { + return new Card(c[0], c[1]); + }); +} + +FlashCardDeck.prototype.shuffle = function() { + var currentIndex = this.cards.length, + temporaryValue, + randomIndex; + while (0 !== currentIndex) { + randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex -= 1; + + temporaryValue = this.cards[currentIndex]; + this.cards[currentIndex] = this.cards[randomIndex]; + this.cards[randomIndex] = temporaryValue; + } +} + +FlashCardDeck.prototype.randomCard = function() { + var card = this.cards.shift(); + this.cards.push(card); + return card; +} diff --git a/oop_examples/flash-card-oop/index.html b/oop_examples/flash-card-oop/index.html new file mode 100644 index 00000000..fff7383c --- /dev/null +++ b/oop_examples/flash-card-oop/index.html @@ -0,0 +1,19 @@ + + + + + + + Flash Cards + + + + + + + +
    +
    + + + diff --git a/oop_examples/flash-card-oop/main.js b/oop_examples/flash-card-oop/main.js new file mode 100644 index 00000000..3fa0d66c --- /dev/null +++ b/oop_examples/flash-card-oop/main.js @@ -0,0 +1,13 @@ +document.addEventListener("DOMContentLoaded", function() { + const data = [['Hello', 'Hola'], ['Food', 'Comida'], ['Cat', 'Gato'], + ['Moxie', 'La Gata Mejor'], ['Sun', 'Sol'], ['Blue', 'Azul']]; + const deck = new FlashCardDeck(data); + deck.shuffle(); + let card = deck.randomCard(); + const cardView = new CardView("container", deck.randomCard()); + + const button = document.getElementById('next-button') + button.addEventListener('click', function() { + cardView.updateCard(deck.randomCard()); + }); +}); diff --git a/oop_examples/tetris-oop/css/global.css b/oop_examples/tetris-oop/css/global.css new file mode 100644 index 00000000..4e885db7 --- /dev/null +++ b/oop_examples/tetris-oop/css/global.css @@ -0,0 +1,6 @@ +#gameboard { + border:1px solid #d3d3d3; + background-color: black; + height: 600px; + width: 300px; +} \ No newline at end of file diff --git a/oop_examples/tetris-oop/index.html b/oop_examples/tetris-oop/index.html new file mode 100644 index 00000000..af0fece4 --- /dev/null +++ b/oop_examples/tetris-oop/index.html @@ -0,0 +1,23 @@ + + + + + + Tetris + + + + + + + + + + + + + +

    Tetris

    + + + \ No newline at end of file diff --git a/oop_examples/tetris-oop/js/grid.js b/oop_examples/tetris-oop/js/grid.js new file mode 100644 index 00000000..30d45f94 --- /dev/null +++ b/oop_examples/tetris-oop/js/grid.js @@ -0,0 +1,103 @@ +function Grid(context, squareSize, squaresX, squaresY) { + this.context = context; + + this.squareSize = squareSize; + + this.squaresX = squaresX + this.squaresY = squaresY; + this.gridData = []; + + for (var y = 0; y < this.squaresY; y++) { + this.gridData.push((new Array(this.squaresX)).fill(null)); + } +} + +Grid.prototype.draw = function() { + for (var y = 0; y < this.squaresY; y++) { + for (var x = 0; x < this.squaresX; x++) { + this.context.beginPath(); + this.context.lineWidth="2"; + this.context.strokeStyle="white"; + this.context.rect(x*this.squareSize+.25,y*this.squareSize+.25,this.squareSize,this.squareSize); + this.context.stroke(); + + if (this.gridData[y][x] !== null) { + this.context.fillStyle = this.gridData[y][x].color; + this.context.fillRect(x*this.squareSize+.5,y*this.squareSize+.5,this.squareSize-.25,this.squareSize-.25) + } + } + } +}; + +Grid.prototype.linesToClear = function() { + lines = []; + for (var y = 0; y < this.squaresY; y++) { + clearLine = true; + + for (var x = 0; x < this.squaresX; x++) { + if (this.gridData[y][x] === null) { + clearLine = false; + break; + } + } + + if (clearLine) { + lines.push(y); + } + } + + return lines; +}; + +Grid.prototype.addToGrid = function(tetromino) { + tetromino.shape.points.forEach(function(p) { + this.gridData[p.y][p.x] = new GridItem(tetromino.shape.color()); + }, this); +}; + +Grid.prototype.checkCollisions = function(tetromino) { + points = tetromino.shape.bottomPoints(); + + var collision = false; + for (var i = 0; i < points.length; i++) { + if (points[i].y + 1 === this.squaresY) { + collision = true; + console.log("COLLISION: with bottom") + break; + } + } + + if (!collision) { + for (var j = 0; j < points.length; j++) { + var p = points[j]; + var x = p.x; + var y = p.y + 1; + if (x < this.squaresX && + y < this.squaresY && + this.gridData[y][x] !== null) { + collision = true; + console.log("COLLISION: with other item") + break; + } + } + } + + return collision; +}; + +Grid.prototype.validPosition = function(points) { + return points.reduce(function(acc, point) { + var inbounds = point.x >= 0 && point.x < this.squaresX && + point.y >= 0 && point.y < this.squaresY; + if (inbounds) { + var gridItem = this.gridData[point.y][point.x]; + if (gridItem !== null) { + acc = false; + } + } else { + acc = false; + } + + return acc; + }, true); +}; \ No newline at end of file diff --git a/oop_examples/tetris-oop/js/gridItem.js b/oop_examples/tetris-oop/js/gridItem.js new file mode 100644 index 00000000..a83f2243 --- /dev/null +++ b/oop_examples/tetris-oop/js/gridItem.js @@ -0,0 +1,3 @@ +function GridItem(color) { + this.color = color +} \ No newline at end of file diff --git a/oop_examples/tetris-oop/js/main.js b/oop_examples/tetris-oop/js/main.js new file mode 100644 index 00000000..fe435614 --- /dev/null +++ b/oop_examples/tetris-oop/js/main.js @@ -0,0 +1,7 @@ +window.addEventListener("load", function() { + var canvas = document.getElementById("gameboard"); + + var tetris = new Tetris(canvas); + + tetris.play(); +}); \ No newline at end of file diff --git a/oop_examples/tetris-oop/js/point.js b/oop_examples/tetris-oop/js/point.js new file mode 100644 index 00000000..0c6278dc --- /dev/null +++ b/oop_examples/tetris-oop/js/point.js @@ -0,0 +1,4 @@ +function Point(x, y) { + this.x = x; + this.y = y; +} \ No newline at end of file diff --git a/oop_examples/tetris-oop/js/shape.js b/oop_examples/tetris-oop/js/shape.js new file mode 100644 index 00000000..7b30a13d --- /dev/null +++ b/oop_examples/tetris-oop/js/shape.js @@ -0,0 +1,42 @@ +function Shape(points, gridItem) { + this.gridItem = gridItem; + this.points = points; +} + + +Shape.copyShape = function(shape) { + s = new Shape([], new GridItem(shape.gridItem.color)); + for (var i = 0; i < shape.points.length; i++) { + s.points.push(new Point(shape.points[i].x, shape.points[i].y)); + } + + return s; +}; + + +Shape.prototype.color = function() { + return this.gridItem.color; +}; + + +Shape.prototype.bottomPoints = function() { + var bottomPoints = []; + for (var i = 0; i < this.points.length; i++) { + var p = this.points[i]; + var lowest = true; + + // y values count downward, so the higher the number + // the lower the y value + for (var j = 0; j < this.points.length; j++) { + if (i !== j && p.x === this.points[j].x) { + if (p.y < this.points[j].y) { + lowest = false; + } + } + } + + if (lowest) bottomPoints.push(p); + } + + return bottomPoints; +} \ No newline at end of file diff --git a/oop_examples/tetris-oop/js/tetris.js b/oop_examples/tetris-oop/js/tetris.js new file mode 100644 index 00000000..4ad0e1a8 --- /dev/null +++ b/oop_examples/tetris-oop/js/tetris.js @@ -0,0 +1,106 @@ +function Tetris(canvas, fps=40) { + this.canvas = canvas; + this.fps = fps; + this.height = canvas.height; + this.width = canvas.width; + this.context = canvas.getContext('2d'); + this.intervalId = undefined; + + this.squareSize = Math.floor(this.height / 20)-.05; + this.squaresX = 10; + this.squaresY = 20; + + this.nextTetromino = this.createRandomTetromino(); + + this.fallingTetromino = null; + this.fallingSpeed = this.fps; + this.frameCount = 0; + + this.addKeyBindings(); + + + this.grid = new Grid(this.context, this.squareSize, this.squaresX, this.squaresY); +} + + +Tetris.prototype.addKeyBindings = function() { + var keys = {up: 38, left: 37, right: 39, down: 40, space: 32} + document.addEventListener("keydown", function(event) { + if (this.fallingTetromino !== null) { + var moved = false + if (event.which === keys.left) { + this.fallingTetromino.move("l"); + moved = true; + } else if (event.which === keys.right) { + this.fallingTetromino.move("r"); + moved = true; + } else if (event.which === keys.down) { + this.fallingTetromino.move("d"); + moved = true; + } else if (event.which === keys.up) { + this.fallingTetromino.rotate(); + moved = true; + } + + if (moved) { + this.checkCollisions(); + } + } + }.bind(this)); +} + +Tetris.prototype.play = function() { + if (this.fallingTetromino === null) { + this.newFallingTetromino(); + } + this.intervalId = setInterval(this.update.bind(this), 1000 / this.fps); +}; + +Tetris.prototype.createRandomTetromino = function() { + var shape = Tetromino.createRandomShape(); + return new Tetromino(this.context, + shape, + this.squareSize, + this.squaresX, + this.squaresY); +} + +Tetris.prototype.pause = function() { + clearInterval(this.intervalId); + this.intervalId = undefined; +}; + +Tetris.prototype.clear = function() { + this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); +}; + +Tetris.prototype.update = function() { + this.clear(); + this.draw(); +}; + +Tetris.prototype.draw = function() { + this.frameCount++; + this.updateFall(); + this.grid.draw(); + this.fallingTetromino.draw(); +}; + +Tetris.prototype.updateFall = function() { + if (this.frameCount % this.fps === 0 && this.fallingTetromino) { + this.fallingTetromino.move('d'); + this.checkCollisions(); + } +} + +Tetris.prototype.checkCollisions = function() { + if (this.grid.checkCollisions(this.fallingTetromino)) { + this.grid.addToGrid(this.fallingTetromino); + this.newFallingTetromino(); + } +} + +Tetris.prototype.newFallingTetromino = function() { + this.fallingTetromino = this.nextTetromino; + this.nextTetromino = this.createRandomTetromino(); +} \ No newline at end of file diff --git a/oop_examples/tetris-oop/js/tetromino.js b/oop_examples/tetris-oop/js/tetromino.js new file mode 100644 index 00000000..f5cd22c3 --- /dev/null +++ b/oop_examples/tetris-oop/js/tetromino.js @@ -0,0 +1,105 @@ +function Tetromino(context, shape, squareSize, squaresX, squaresY ) { + this.context = context; + this.shape = shape; + this.squareSize = squareSize; + this.squaresX = squaresX; + this.squaresY = squaresY; +} + + +Tetromino.prototype.possibleShapes = []; + +// L-left +Tetromino.prototype.possibleShapes.push( + new Shape([new Point(4, 0), new Point(4, 1), + new Point(5, 1), new Point(6, 1)], + new GridItem("blue"))); + +// L-right +Tetromino.prototype.possibleShapes.push( + new Shape([new Point(4, 1), new Point(5, 1), + new Point(6, 1), new Point(6, 0)], + new GridItem("darkorange"))); + +// T +Tetromino.prototype.possibleShapes.push( + new Shape([new Point(4, 1), new Point(5, 1), + new Point(6, 1), new Point(5, 0)], + new GridItem("rebeccapurple"))); + +// Z-left +Tetromino.prototype.possibleShapes.push( + new Shape([new Point(4, 0), new Point(5, 0), + new Point(5, 1), new Point(6, 1)], + new GridItem("red"))); + +// Z-right +Tetromino.prototype.possibleShapes.push( + new Shape([new Point(4, 1), new Point(5, 1), + new Point(5, 0), new Point(6, 0)], + new GridItem("green"))); + +// Square +Tetromino.prototype.possibleShapes.push( + new Shape([new Point(4, 0), new Point(4, 1), + new Point(5, 0), new Point(5, 1)], + new GridItem("gold"))); + +// Line +Tetromino.prototype.possibleShapes.push( + new Shape([new Point(3, 0), new Point(4, 0), + new Point(5, 0), new Point(6, 0)], + new GridItem("dodgerblue"))); + +Tetromino.createRandomShape = function() { + var index = Math.floor(Math.random() * Tetromino.prototype.possibleShapes.length); + + var shape = Tetromino.prototype.possibleShapes[index]; + + return Shape.copyShape(shape); +} + +Tetromino.prototype.draw = function() { + var point; + for (var i = 0; i < this.shape.points.length; i++) { + point = this.shape.points[i] + this.context.fillStyle = this.shape.color(); + this.context.fillRect(point.x*this.squareSize+.5,point.y*this.squareSize+.5,this.squareSize-.25,this.squareSize-.25) + } +} + + +// "d", "l", "r" +Tetromino.prototype.move = function(direction) { + var xAdd = 0; + var yAdd = 0; + + if (direction === "d") yAdd = 1; + else if (direction === "l") xAdd = -1; + else if (direction === "r") xAdd = 1; + + var newPoints = []; + var allowed = true; + var newPoint; + for (var i = 0; i < this.shape.points.length; i++) { + newPoint = new Point(this.shape.points[i].x + xAdd, this.shape.points[i].y + yAdd); + if (this.__validPoint(newPoint)) { + newPoints.push(newPoint); + } else { + allowed = false; + } + } + + if (allowed) { + this.shape.points = newPoints; + } +} + +Tetromino.prototype.rotate = function() { + console.log("rotate"); +} + +Tetromino.prototype.__validPoint = function(point) { + return point.x >= 0 && point.x < this.squaresX && + point.y >= 0 && point.y < this.squaresY; +} \ No newline at end of file diff --git a/oop_examples/tetris-oop/readme.md b/oop_examples/tetris-oop/readme.md new file mode 100644 index 00000000..126bee0b --- /dev/null +++ b/oop_examples/tetris-oop/readme.md @@ -0,0 +1,16 @@ +# Tetris + +The goal of the application is to create a javascript version of tetris that uses object oriented programming to solve the problem. + +### Requirements + +As a user, I should be able to: + +* Start the game +* get a random falling shape every x seconds +* rotate the shape +* move the shape left, right, down +* pause the game +* see the next shape that will fall +* clear complete lines from the board (no spaces across a row) +* keep track of the number of lines cleared \ No newline at end of file diff --git a/prototypes_exercise/prototypes.js b/prototypes_exercise/prototypes.js index d3414c73..84d1bdab 100644 --- a/prototypes_exercise/prototypes.js +++ b/prototypes_exercise/prototypes.js @@ -56,4 +56,55 @@ Function.prototype.bind = function(thisArg, ...outerArgs) { return function() { return _this.apply(thisArg, [...outerArgs, ...arguments]); } -} \ No newline at end of file +} + +/* +array = [1,2,3,4]; +array.reduce(function(acc, el) { + return `${acc}${el}`; +}, ""); +// "1234" +*/ + +Array.prototype.reduce = function(fn, startVal) { + var startValue = startVal? startVal : this[0]; + var i = startVal? 0 : 1; + + for (i ; i < this.length; i++) { + startValue = fn(startValue, this[i], i, this); + } + + return startValue; +} + + +var numArray = [1,2,3,4]; +console.log(numArray.reduce(function(acc, el) { + return `${acc}${el}`; +}, "")); +// "1234" + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/prototypes_exercise/prototypesSpec.js b/prototypes_exercise/prototypesSpec.js index 3a7eb030..d3f70815 100644 --- a/prototypes_exercise/prototypesSpec.js +++ b/prototypes_exercise/prototypesSpec.js @@ -99,6 +99,35 @@ describe("Array.prototype.map", function(){ }); }); +describe("Array.prototype.reduce", function(){ + var arr = [1,2,3,4] + it("adds numbers without an initial value", function(){ + expect(arr.reduce((acc,v) => acc+v)).to.equal(10) + }); + it("adds numbers with an initial value", function() { + expect(arr.reduce((acc,v) => acc+v, 10)).to.equal(20) + }) + it("has an index as the 3rd parameter", function() { + expect(arr.reduce((acc,v, i) => i === 3 ? "blah": null, 10)).to.equal("blah") + }) + it("has an index array as the 4th parameter", function() { + expect(arr.reduce((acc,v, i, arr) => arr.length, 10)).to.equal(4) + }) + it("can return any type of data", function() { + var init = {name: "Tim", age: "33", numbers: []}; + var res = arr.reduce((acc,v, i, arr) => { + acc.numbers.push(v); + return acc; + }, init); + expect(res).to.equal(init) + expect(res.numbers).to.be.a("array"); + expect(res.numbers).to.equal(init.numbers); + expect(res.numbers.length).to.equal(4); + expect(res.numbers).to.deep.equal(arr); + }) + +}); + describe("String.prototype.reverse", function(){ it("returns a new reversed string", function(){ expect("test".reverse()).to.equal("tset"); @@ -117,4 +146,4 @@ describe("Function.prototype.bind", function(){ expect(add.bind(this,3)(4)).to.equal(7); expect(add.bind(this)(3,4)).to.equal(7); }); -}); \ No newline at end of file +}); diff --git a/recursion_exercise/recursionSpec.js b/recursion_exercise/recursionSpec.js index 5bc841fe..ac7f80a8 100644 --- a/recursion_exercise/recursionSpec.js +++ b/recursion_exercise/recursionSpec.js @@ -78,8 +78,8 @@ describe("#search", function(){ expect(search([1,2,3,4,5,6,7],6)).to.equal(5) }); it("should return -1 if the value is not found", function(){ - expect(search([1,2,3,4]),0).to.equal(-1) - expect(search([1,2]),11).to.equal(-1) + expect(search([1,2,3,4],0)).to.equal(-1) + expect(search([1,2],11)).to.equal(-1) }); }); @@ -191,4 +191,4 @@ describe("#stringifyNumbers", function(){ } expect(stringifyNumbers(obj)).to.deep.equal(answer) }); -}); \ No newline at end of file +}); From 4304e55bbe6358806504e5c686a4de6497528c82 Mon Sep 17 00:00:00 2001 From: Brian Harris Date: Thu, 10 Aug 2017 22:57:37 -0700 Subject: [PATCH 19/19] tic tac toe finished --- intermediate_oop/tic_tac_toe/.DS_Store | Bin 0 -> 6148 bytes intermediate_oop/tic_tac_toe/index.html | 9 ++-- intermediate_oop/tic_tac_toe/js/board.js | 41 ++++++++++++++++ intermediate_oop/tic_tac_toe/js/game.js | 54 ++++++++++++++++++++++ intermediate_oop/tic_tac_toe/js/main.js | 2 + intermediate_oop/tic_tac_toe/js/player.js | 5 ++ 6 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 intermediate_oop/tic_tac_toe/.DS_Store create mode 100644 intermediate_oop/tic_tac_toe/js/board.js create mode 100644 intermediate_oop/tic_tac_toe/js/game.js create mode 100644 intermediate_oop/tic_tac_toe/js/player.js diff --git a/intermediate_oop/tic_tac_toe/.DS_Store b/intermediate_oop/tic_tac_toe/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..11474080a9ae50b8edfed18debc373a07ac4800d GIT binary patch literal 6148 zcmeHK!EO^V5FIBe-LyjFfLe}wLE;cq3D8ssA+16=^oA4!2SDj=H*FSe)>U@X6hhEm z_y+n5dzAdlpEV|!*SKd=Lzz$U$LjY(QNi+|Ol2 zYNllqC^&~a3St?c#_6nB1}pc-r>AC@e+f?G zD9t*ZucB6OtX*4onoXy9-FZD2%lRPlvsv2rr!Q443P*vlpGg`2vi;zBG@1`vHy_I+ z^P^-mEx5mW5hbCV_vI`JQx7WS<#|x#V zUs#Ei)Zrx5$jDcdd(Zh{D2txkeQNWv*jo@Kt;ZMG5*`Hh`YN TTq9Z__D4X`V3lRyuQKohU7PIh literal 0 HcmV?d00001 diff --git a/intermediate_oop/tic_tac_toe/index.html b/intermediate_oop/tic_tac_toe/index.html index 00c74eb9..a0fe6bbb 100644 --- a/intermediate_oop/tic_tac_toe/index.html +++ b/intermediate_oop/tic_tac_toe/index.html @@ -11,9 +11,12 @@ - - - + + + + + +

    Tic Tac Toe

    diff --git a/intermediate_oop/tic_tac_toe/js/board.js b/intermediate_oop/tic_tac_toe/js/board.js new file mode 100644 index 00000000..8f6dbc0e --- /dev/null +++ b/intermediate_oop/tic_tac_toe/js/board.js @@ -0,0 +1,41 @@ +function Board() { + this.row = [0, 0, 0]; + this.col = [0, 0, 0]; + this.diagUpperLeft = 0; + this.diagUpperRight = 0; + this.boardSize = 3; // I am aware this is extraneous! May support n-size boards one day :D +} + +Board.prototype.makeMark = function(x, y, adjuster){ + this.row[x] += adjuster; + this.col[y] += adjuster; + + // Middle spot, vs diagonals... + if (x === 1 && y === 1) { + this.diagUpperLeft += adjuster; + this.diagUpperRight += adjuster; + } else if (x === y) { // Wrote it out the long way and noticed the pattern :D + this.diagUpperLeft += adjuster; + } else if (Math.abs(x - y) === this.boardSize-1) { + this.diagUpperRight += adjuster; + } +} + +// Question: Do I need to bother with "else if" for formatting purposes, if each condition returns?? +Board.prototype.testWinCondition = function(x, y, adjuster) { + if (this.row[x] === adjuster * this.boardSize) return true; + if (this.col[y] === adjuster * this.boardSize) return true; + if (this.diagUpperLeft === adjuster * this.boardSize) return true; + if (this.diagUpperRight === adjuster * this.boardSize) return true; + + return false; +} + +Board.prototype.clearBoard = function() { + for (var i = 0; i < this.row.length; i++) { + this.row[i] = 0; + this.col[i] = 0; + } + this.diagUpperLeft = 0; + this.diagUpperRight = 0; +} \ No newline at end of file diff --git a/intermediate_oop/tic_tac_toe/js/game.js b/intermediate_oop/tic_tac_toe/js/game.js new file mode 100644 index 00000000..a4c5a14a --- /dev/null +++ b/intermediate_oop/tic_tac_toe/js/game.js @@ -0,0 +1,54 @@ +function Game() { + this.players = []; + this.players.push(new Player("Brian", "X", 1)); + this.players.push(new Player("Jenny", "O", -1)); + this.currentPlayer = 0; + this.message = document.getElementById("message"); + + this.board = new Board(); + this.containerDiv = document.getElementById("board"); + this.containerDiv.addEventListener('click', this.attemptMark.bind(this)); + this.newGameBtn = document.getElementById("new-game"); + this.newGameBtn.addEventListener('click', this.newGame.bind(this)); +} + +Game.prototype.attemptMark = function(event) { + // this is bound to GAME so we can call game's board's functions, and more! + // Also remember to use Player's mark + var targetIdStr = event.target.id; + + if (event.target.className !== "square") { + return; + } + + var x = Number.parseInt(targetIdStr[7]); + var y = Number.parseInt(targetIdStr[9]); + + if (event.target.innerText === "") { + console.log(`Player ${this.currentPlayer+1}: Marking Board with: ${this.players[this.currentPlayer].mark}`); + this.board.makeMark(x, y, this.players[this.currentPlayer].adjuster); + event.target.innerText = this.players[this.currentPlayer].mark; + if (this.testWin(x, y)) { + this.message.innerText = `Player ${this.currentPlayer+1} Wins!`; + } + this.currentPlayer = this.currentPlayer === 0? 1 : 0; + } else { + alert("That square is occupied!"); + } +} + +Game.prototype.testWin = function(x, y) { + return this.board.testWinCondition(x, y, this.players[this.currentPlayer].adjuster); +} + +Game.prototype.newGame = function() { + this.currentPlayer = 0; + this.board.clearBoard(); + this.message.innerText = ""; + var squares = document.getElementsByClassName("square"); + for (var i = 0; i < squares.length; i++) { + squares[i].innerText = ""; + } +} + + diff --git a/intermediate_oop/tic_tac_toe/js/main.js b/intermediate_oop/tic_tac_toe/js/main.js index 379d891d..3cc3f6ce 100644 --- a/intermediate_oop/tic_tac_toe/js/main.js +++ b/intermediate_oop/tic_tac_toe/js/main.js @@ -1,2 +1,4 @@ document.addEventListener("DOMContentLoaded", function() { + var game = new Game(); }); + diff --git a/intermediate_oop/tic_tac_toe/js/player.js b/intermediate_oop/tic_tac_toe/js/player.js new file mode 100644 index 00000000..36b8d68c --- /dev/null +++ b/intermediate_oop/tic_tac_toe/js/player.js @@ -0,0 +1,5 @@ +function Player(name="", mark="ERR", adjuster = 0) { + this.name = name; + this.mark = mark; + this.adjuster = adjuster; +} \ No newline at end of file