diff --git a/ajax_with_jquery_exercise/favorites.html b/ajax_with_jquery_exercise/favorites.html new file mode 100644 index 00000000..e69de29b diff --git a/ajax_with_jquery_exercise/index.html b/ajax_with_jquery_exercise/index.html new file mode 100644 index 00000000..d2ae82d5 --- /dev/null +++ b/ajax_with_jquery_exercise/index.html @@ -0,0 +1,66 @@ + + + + + Hacker News Clone + + + + +
+
+
+ Hack or Snooze + submit | favorites + +
+
+
+
+ +
+
+ +
+
+ + + + +
+ + + + + \ No newline at end of file diff --git a/ajax_with_jquery_exercise/script.js b/ajax_with_jquery_exercise/script.js new file mode 100644 index 00000000..af7e18d0 --- /dev/null +++ b/ajax_with_jquery_exercise/script.js @@ -0,0 +1,135 @@ +$(document).ready(function(){ + var star = ""; + var $linkItemsOl = $(".link-items"); + + $.ajax({ + method: "GET", + url: "https://hacker-news.firebaseio.com/v0/topstories.json?" + }).then(function(topItems){ + var top20 = topItems.slice(0,20); + for (let i = 0; i < top20.length; i++) { + $.ajax({ + method: "GET", + dataType: "json", + url: `https://hacker-news.firebaseio.com/v0/item/${top20[i]}.json?print=pretty` + }).then(function(item){ + addItemToList(item.title, item.url); + console.log(item.title + '\n' + item.url); + //item.title + //item.url + }); + + } + }); + + function addItemToList(itemTitle, itemUrl) { + var $newItem = $("
  • ", { "class" : "item"}); + var aTag = ` ${itemTitle}`; + $newItem.html(star + " " + aTag); + $linkItemsOl.append($newItem); + console.log(aTag); + } + + $(".login").on("click", function(e) { + $(".login-form").toggle(); + $(".signup-form").toggle(); + }); + + $("login-signup-form").on("click", "login-button", function(e){ + e.preventDefault(); + var email = $("#login-email").val(); + var pw = $("#login-pw").val(); + $.ajax({ + method: "POST", + url: "https://hn-favorites.herokuapp.com/login", + //Content-Type: "application/json" + data: { + "email" : email, + "password": pw + } + }).then(function(authKey){ + console.log(authKey); + }); + }); + + $("#signup-form").on("submit", function(e){ + e.preventDefault(); + var email = $("#signup-email").val(); + var pw = $("#signup-pw").val(); + console.log(email + pw); + $.ajax({ + method: "POST", + url: "https://hn-favorites.herokuapp.com/signup", + data: { + "email" : email, + "password": pw + } + }).then(function(authKey){ + console.log(authKey); + }); + }); + + // what to do with the authkey? + // you need it to: + // GET all favorites + // DELETE a favorite + + // when you click the log in button + // post to log in + // + + + // var $submitLink = $(".submit"); + // var $submitForm = $(".submit-form"); + // var $submitBtn = $(".submit-button"); + // var $linkItemsOl = $(".link-items"); + // var star = ""; + // var $title = $("#title"); + // var $url = $("#url"); + // var $favSpan = $(".favorites"); + + // $submitLink.on("click", function(){ + // $submitForm.toggle(); + // }); + + // $("body").on("click", ".glyphicon", function(e){ + // $(e.target).toggleClass("glyphicon-star-empty glyphicon-star"); + // }); + + // $submitBtn.on("click", function(e){ + // e.preventDefault(); + // var title = $("#title").val(); + // var url = $("#url").val(); + // var $newItem = $("
  • "); + // var aTag = ` ${title}`; + // $newItem.html(star + " " + aTag); + // $linkItemsOl.append($newItem); + // console.log(aTag); + // $title.val(""); + // $url.val("https://"); + // }); + + // $favSpan.on("click", function(e){ + // var stars = $(".glyphicon"); + // if ($favSpan.hasClass("favorites")) { + // for (let i = 0; i < stars.length; i++) { + // console.log(stars[i]); + // if ($(stars[i]).hasClass("glyphicon-star-empty")) { + // $(stars[i]).parent().hide(); + // } + // } + // $favSpan.text("all"); + // } + // else if ($favSpan.hasClass("all")) { + // for (let i = 0; i < stars.length; i++) { + // console.log(stars[i]); + // if ($(stars[i]).hasClass("glyphicon-star-empty")) { + // $(stars[i]).parent().show(); + // } + // } + // $favSpan.text("favorites"); + // } + // $favSpan.toggleClass("favorites all"); + // }); + +}); \ No newline at end of file diff --git a/ajax_with_jquery_exercise/style.css b/ajax_with_jquery_exercise/style.css new file mode 100644 index 00000000..c8bf8089 --- /dev/null +++ b/ajax_with_jquery_exercise/style.css @@ -0,0 +1,58 @@ +.item { + margin-bottom: 10px; +} + +.title, .submit, .favorites { + height: 3em; + margin: 5px; +} + +.submit:hover, .favorites:hover, .all:hover, .login:hover, .signup:hover { + text-decoration: underline; + cursor: pointer; +} + +.login { + margin-left: 63%; +} + +.glyphicon:hover { + cursor: pointer; +} + +.title { + font-size: 1.5em; + font-weight: bold; +} + +.wrapper { + background-color: #f6f6ef; + width: 80%; + margin-top: 1em; + margin-left: auto; + margin-right: auto; + color: #828282; +} + + +.panel > .panel-heading, .custom-panel { + background-image: none; + background-color: rgb(255, 102, 0); + color: black; + border: 1px solid rgb(255, 102, 0); +} + +/*.custom-form { + width: 15%; + margin-left: 68em; + margin-bottom: 2em; + display: none; +}*/ + +a, a:hover { + color: black; +} + +.link-items { + margin-bottom: 50px; +} \ No newline at end of file diff --git a/call_apply_bind_exercise/callApplyBind.js b/call_apply_bind_exercise/callApplyBind.js index e69de29b..da9ed2cb 100644 --- a/call_apply_bind_exercise/callApplyBind.js +++ b/call_apply_bind_exercise/callApplyBind.js @@ -0,0 +1,55 @@ +function sumEvenArguments() { + var arr = [].slice.call(arguments); + var sum = 0; + for (let i = 0; i < arr.length; i++) { + if (arr[i] % 2 === 0) { + sum += arr[i]; + } + } + return sum; +} + +function arrayFrom(arrLikeObj) { + var arr = [].slice.call(arrLikeObj); + return arr; +} + +function invokeMax(fn, maxTimes) { + var counter = 0; + return function() { + if (counter >= maxTimes) { + return "Maxed Out!"; + } else { + counter++; + return fn.apply(this, arguments); + } + } +} + +function guessingGame(num) { + var answer = Math.floor(Math.random()*10); + var guesses = 0; + return function(guess) { + if (guesses === num) { + return `No more guesses. The answer was ${answer}.`; + } + else { + guess++; + if (guess === answer) { + return "You got it!"; + } + else if (guess > answer) { + return "You're too high!"; + } + else if (guess < answer) { + return "You're too low!"; + } + } + } +} + + + + + + diff --git a/call_apply_bind_exercise/readme.md b/call_apply_bind_exercise/readme.md index cbc3cd03..7a353703 100644 --- a/call_apply_bind_exercise/readme.md +++ b/call_apply_bind_exercise/readme.md @@ -3,19 +3,28 @@ Fix the following code: ```javascript +// var obj = { +// fullName: "Harry Potter", +// person: { +// sayHi: function(){ +// return "This person's name is " + this.fullName +// } +// } +// } + var obj = { fullName: "Harry Potter", person: { sayHi: function(){ return "This person's name is " + this.fullName - } + }.apply(obj) } } ``` - List two examples of "array-like-objects" that we have seen. - - - - + - arguments + - result of DOM method such as getElementsByTagName ### Functions to write: diff --git a/canvas_exercise/shapes_game/index.js b/canvas_exercise/shapes_game/index.js index 0de5f18a..a7bd2f56 100644 --- a/canvas_exercise/shapes_game/index.js +++ b/canvas_exercise/shapes_game/index.js @@ -1,36 +1,130 @@ window.addEventListener("load", function() { - function clear(ctx, width, heigt) { + function clear(ctx, width, height) { + ctx.clearRect(0, 0, width, height); } function drawRandomShape(ctx, width, height) { + var randomShapeNumber = Math.floor(Math.random()*(4)+1); + var x = Math.floor(Math.random()*642); // multiplied by 692 to ensure shape doesn't go off black screen + var y = Math.floor(Math.random()*592); // multiplied by 642 to ensure shape doesn't go off black screen + + // 1 - White Triangle + if (randomShapeNumber === 1) { + expectedKey = "white0"; + ctx.fillStyle = "white"; + ctx.beginPath(); + ctx.moveTo(x, y); // random point on screen + ctx.lineTo(x+100, y+100); // + ctx.lineTo(x, y+100); + ctx.fill(); + ctx.closePath(); + } + + // 2 - Red Square + if (randomShapeNumber === 2) { + expectedKey = "red1"; + ctx.fillStyle = "red"; + ctx.fillRect(x, y, 100, 100); + } + + + // 3 - Red Triangle + if (randomShapeNumber === 3) { + expectedKey = "red0"; + ctx.fillStyle = "red"; + ctx.beginPath(); + ctx.moveTo(x, y); + ctx.lineTo(x+100, y+100); + ctx.lineTo(x, y+100); + ctx.fill(); + ctx.closePath(); + } + + // 4 - White Square + if (randomShapeNumber === 4) { + expectedKey = "white1"; + ctx.fillStyle = "white"; + ctx.fillRect(x, y, 100, 100); + } + } function drawGameStartText(ctx, width, height, score) { - } + clear(ctx, width, height); // clear the board of any text or shapes + seconds = 30; // restart the seconds + timerSpan.innerText = "30"; // restart the timerSpan + scoreSpan.innerText = "0"; // restart the score + + if (alreadyPlayed) { + ctx.fillStyle = "white"; // re-render start text + ctx.font = "2em Times New Roman"; + ctx.fillText("Score: " + score, 120, 300); + } + + ctx.fillStyle = "white"; // re-render start text + ctx.font = "2.3em Times New Roman"; + ctx.fillText("Press the space bar to start the game.", 120, 350); - function restartGame(ctx, width, height) { + score = 0; } + function runTimer() { + intervalId = setInterval(function(){ + if (seconds === 0) { + clearInterval(intervalId); + drawGameStartText(ctx, width, height, score); + gameOn = !gameOn; + } else { + seconds--; + timerSpan.innerText = seconds; + } + }, 1000); + }; + var canvas = document.getElementById("shapes-game"), height = canvas.scrollHeight, width = canvas.scrollWidth, gameOn = false, + alreadyPlayed = false, expectedKey = undefined, ctx = canvas.getContext('2d'), - // white triangle = up, red square = down, - // red triangle = left, white square = right + // white triangle / white0 = up, red square / red1 = down, + // red triangle / red0 = left, white square / white1 = right expectedKeysMap = {white0: 38, red1: 40, red0: 37, white1: 39}, timerSpan = document.getElementById("time-remaining"), scoreSpan = document.getElementById("score-val"), - seconds = 3, + score = 0, + seconds = 30, // added a 0 to make it 30? intervalId; canvas.width = width; canvas.height = height; - document.addEventListener("keyup", function() { - + document.addEventListener("keyup", function(e) { + // if gameOn is true, check which key is pressed and address accordingly + if (gameOn) { + if (e.keyCode === expectedKeysMap[expectedKey]) { + score++; + scoreSpan.innerText = score; + clear(ctx, width, height); + drawRandomShape(ctx, width, height); + } else { + score--; + scoreSpan.innerText = score; + } + + } else { // if gameOn is false, only start game if space bar is clicked + if (e.keyCode === 32) { + gameOn = !gameOn; + alreadyPlayed = true; + clear(ctx, width, height); + drawRandomShape(ctx, width, height); + runTimer(); + } + } }); + + drawGameStartText(ctx, width, height); }); diff --git a/canvas_exercise/shapes_game/styles.css b/canvas_exercise/shapes_game/styles.css index cbe4fa83..189431e4 100644 --- a/canvas_exercise/shapes_game/styles.css +++ b/canvas_exercise/shapes_game/styles.css @@ -11,8 +11,8 @@ body { padding: 10px; } .canvas-container, #shapes-game { - height: 750px; - width: 800px; + height: 700px; + width: 750px; } .scores { diff --git a/es2015_exercise/readme.md b/es2015_exercise/readme.md index 9e482efa..3d02d4b6 100644 --- a/es2015_exercise/readme.md +++ b/es2015_exercise/readme.md @@ -5,8 +5,8 @@ Convert the following es5 code blocks into es2015 code: ```javascript var person = { fullName: "Harry Potter", - sayHi: function(){ - setTimeout(function(){ + sayHi(){ + setTimeout(() => { console.log("Your name is " + this.fullName) }.bind(this),1000) } @@ -15,26 +15,37 @@ var person = { ```javascript var name = "Josie" -console.log("When " + name + " comes home, so good") +console.log(`When ${name} comes home, so good`); ``` ```javascript -var DO_NOT_CHANGE = 42; -DO_NOT_CHANGE = 50; // stop me from doing this! +// var DO_NOT_CHANGE = 42; +// DO_NOT_CHANGE = 50; // stop me from doing this! + +const DO_NOT_CHANGE = 42 ``` ```javascript +// var arr = [1,2] +// var temp = arr[0] +// arr[0] = arr[1] +// arr[1] = temp + var arr = [1,2] -var temp = arr[0] +let temp = arr[0] arr[0] = arr[1] arr[1] = temp ``` ```javascript +// function double(arr){ +// return arr.map(function(val){ +// return val*2 +// }); +// } + function double(arr){ - return arr.map(function(val){ - return val*2 - }); + return arr.map(val => val*2); } ``` @@ -46,30 +57,38 @@ var obj = { } } -var a = obj.numbers.a; -var b = obj.numbers.b; +// var a = obj.numbers.a; +// var b = obj.numbers.b; + +var {a, b} = obj.numbers ``` ```javascript -function add(a,b){ - if(a === 0) a = 0 - else { - a = a || 10 - } - if(b === 0) b = 0 - else { - b = b || 10 - } +// function add(a,b){ +// if(a === 0) a = 0 +// else { +// a = a || 10 +// } +// if(b === 0) b = 0 +// else { +// b = b || 10 +// } +// return a+b +// } + +function add(a=10, b=10){ return a+b } ``` Research the following functions - what do they do? -`Array.from` - +`Array.from` - The Array.from() method creates a new Array instance from an array-like or iterable object. + +`Object.assign` - The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object. It makes a shallow copy. + +`Array.includes` - The includes() method determines whether an array includes a certain element, returning true or false as appropriate. -`Object.assign` - +`String.startsWith` - The startsWith() method determines whether a string begins with the characters of a specified string, returning true or false as appropriate. -`Array.includes` - -`String.startsWith` - diff --git a/jquery_exercise/index.html b/jquery_exercise/index.html new file mode 100644 index 00000000..1380eae3 --- /dev/null +++ b/jquery_exercise/index.html @@ -0,0 +1,52 @@ + + + + + Hacker News Clone + + + + +
    +
    +
    + Hack or Snooze + submit | favorites +
    +
    +
    +
    + + +
    +
    + + +
    + +
    + + +
    + + + + + \ No newline at end of file diff --git a/jquery_exercise/script.js b/jquery_exercise/script.js new file mode 100644 index 00000000..0eee8a7b --- /dev/null +++ b/jquery_exercise/script.js @@ -0,0 +1,55 @@ +$(document).ready(function(){ + var $submitLink = $(".submit"); + var $submitForm = $(".submit-form"); + var $submitBtn = $(".submit-button"); + var $linkItemsOl = $(".link-items"); + var star = ""; + var $title = $("#title"); + var $url = $("#url"); + var $favSpan = $(".favorites"); + + $submitLink.on("click", function(){ + $submitForm.toggle(); + }); + + $("body").on("click", ".glyphicon", function(e){ + $(e.target).toggleClass("glyphicon-star-empty glyphicon-star"); + }); + + $submitBtn.on("click", function(e){ + e.preventDefault(); + var title = $("#title").val(); + var url = $("#url").val(); + var $newItem = $("
  • "); + var aTag = ` ${title}`; + $newItem.html(star + " " + aTag); + $linkItemsOl.append($newItem); + console.log(aTag); + $title.val(""); + $url.val("https://"); + }); + + $favSpan.on("click", function(e){ + var stars = $(".glyphicon"); + if ($favSpan.hasClass("favorites")) { + for (let i = 0; i < stars.length; i++) { + console.log(stars[i]); + if ($(stars[i]).hasClass("glyphicon-star-empty")) { + $(stars[i]).parent().hide(); + } + } + $favSpan.text("all"); + } + else if ($favSpan.hasClass("all")) { + for (let i = 0; i < stars.length; i++) { + console.log(stars[i]); + if ($(stars[i]).hasClass("glyphicon-star-empty")) { + $(stars[i]).parent().show(); + } + } + $favSpan.text("favorites"); + } + $favSpan.toggleClass("favorites all"); + }); + +}); \ No newline at end of file diff --git a/jquery_exercise/style.css b/jquery_exercise/style.css new file mode 100644 index 00000000..ff6065ee --- /dev/null +++ b/jquery_exercise/style.css @@ -0,0 +1,50 @@ +.title, .submit, .favorites { + height: 3em; + margin: 5px; +} + +.submit:hover, .favorites:hover, .all:hover { + text-decoration: underline; + cursor: pointer; +} + +.glyphicon:hover { + cursor: pointer; +} + +.title { + font-size: 1.5em; + font-weight: bold; +} + +.wrapper { + background-color: #f6f6ef; + width: 80%; + margin-top: 1em; + margin-left: auto; + margin-right: auto; + color: #828282; +} + + +.panel > .panel-heading, .custom-panel { + background-image: none; + background-color: rgb(255, 102, 0); + color: black; + border: 1px solid rgb(255, 102, 0); +} + +.custom-form { + width: 30%; + margin-left: 5em; + margin-bottom: 2em; + display: none; +} + +a, a:hover { + color: black; +} + +.link-items { + margin-bottom: 50px; +} \ No newline at end of file diff --git a/lodash_exercise/index.html b/lodash_exercise/index.html index 01b829ff..8570e625 100644 --- a/lodash_exercise/index.html +++ b/lodash_exercise/index.html @@ -1,7 +1,6 @@ - Document diff --git a/lodash_exercise/lodash.js b/lodash_exercise/lodash.js index 483d734a..6e2206b2 100644 --- a/lodash_exercise/lodash.js +++ b/lodash_exercise/lodash.js @@ -1,99 +1,314 @@ -function drop(){ - +function drop(arr, num=1){ + if (num === 1) { + return arr.slice(1); + } + return arr.slice(num); } -function fromPairs(){ - +function fromPairs(arr){ + // assuming arr is an array of arrays containing key value pairs + // e.g. [[key, value],[key, value],[key, value]] + if (arr.length === 0) { + return {}; + } else { + var result = {}; + for (var i = 0; i < arr.length; i++) { + result[arr[i][0]] = arr[i][1]; + } + return result; + } } -function head(){ - +function head(arr){ + if (arr.length === 0) { + return undefined; + } + return arr[0]; } -function take(){ - +function take(arr, num=1){ + return arr.slice(0, num); } -function takeRight(){ - +function takeRight(arr, num=1){ + if (num === 0) { + return [] + } + return arr.slice(num*-1); } function union(){ - -} - -function zipObject(){ - + // assuming arguments will be an "array" of arrays + var result = []; + for (var i = 0; i < arguments.length; i++) { + for (var j = 0; j < arguments[i].length; j++) { + if (result.indexOf(arguments[i][j]) === -1) { + result.push(arguments[i][j]); + } + } + } + return result; } -function includes(){ - +function zipObject(keysArr, valuesArr){ + var result = {}; + for (var i = 0; i < keysArr.length; i++) { + result[keysArr[i]] = valuesArr[i]; + } + return result; } -function sample(){ - +function includes(collection, val, fromIndex=0){ + // collection can be an array, string, or object + if (typeof collection === "object" && Array.isArray(collection) !== true) { + for (var key in collection) { + if (collection[key] === val) { + return true; + } + } + return false; + } + return collection.slice(fromIndex).indexOf(val) !== -1 ? true : false; } -function cloneDeep(){ - +function sample(arr){ + return arr[Math.floor(Math.random()*arr.length-1)]; } -function sumBy(){ - +function cloneDeep(collection){ // [1, 2, 3, [4, [5]]] + var result; + if (Array.isArray(collection)) { + result = []; + collection.forEach(function(val){ + // we want to make all the references different + result.concat(cloneDeep(val)); + }); + } else { + result = {}; + for (var key in collection) { + result[key] = collection[key]; + } + } + return result; } -function inRange(){ - +function sumBy(arrOfObj, iteratee){ + if (typeof iteratee === "string") { + return arrOfObj.reduce(function(acc, obj){ + acc += obj[iteratee]; + return acc; + }, 0); + } else { + var sum = 0; + for (var i = 0; i < arrOfObj.length; i++) { + sum += iteratee(arrOfObj[i]); + } + return sum; + } } -function has(){ - +function inRange(num, start=0, end){ + // 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. + if (end === undefined) { + end = start; + start = 0; + } + if (start > end) { + var hold = start; + start = end; + end = hold; + } + return (num > start && num < end); } -function omit(){ - +function has(obj, path) { + // returns true if obj.path exists + // returns false if obj.path is not valid + + // if path is just a string, just look for immediate key + if (typeof path === "string") { + for (var key in obj) { + if (key === path) return true; + } + } + + // if path is an array, find if first element is immediate key + // then do again if there's a deeper layer + if (Array.isArray(path)) { + // if path array only has one element + if (path.length === 1) { + for (var key in obj) { + if (key === path[0]) return true; + } + return false; + } + // if the path array contains more than one element + for (var key in obj) { + if (key === path[0]) return has(obj[path[0]], path.slice(1)); + } + } +} + +function omit(obj, arrKeysToOmit){ + var result = {}; + for (var key in obj) { + if (arrKeysToOmit.indexOf(key) === -1) { + result[key] = obj[key]; + } + } + return result; } -function pick(){ - +function pick(obj, arrKeysToPick){ + var result = {}; + for (var key in obj) { + if (arrKeysToPick.indexOf(key) !== -1) { + result[key] = obj[key]; + } + } + return result; } -function pickBy(){ - +function pickBy(obj, callback){ + var result = {}; + for (var key in obj) { + if (callback(obj[key])) { + result[key] = obj[key]; + } + } + return result; } -function omitBy(){ - +function omitBy(obj, callback){ + var result = {}; + for (var key in obj) { + if (!callback(obj[key])) { + result[key] = obj[key]; + } + } + return result; } -function padEnd(){ - +function padEnd(str, finalLength, chars=" "){ + var result = str.slice(); + // if the desired length is less than or equal to the original string's length + // there is nothing to pad to the end, so return it. + // or if we pass in an empty string to pad to the end + if (str.length >= finalLength || chars.length === 0) { + return result; + } + var times = Math.floor((finalLength-str.length)/chars.length); + var remainder = (finalLength-str.length)%chars.length; + for (let i = 0; i < times; i++) { + // so I learned today that .concat() doesn't modify the original string + // and that you need to reassign it to capture the returned new string + // so I'm just going to use += from now on... + result += chars; + } + for (let j = 0; j < remainder; j++) { + result += chars[j]; + } + return result; } -function repeat(){ +function repeat(str, times){ + if (times === 0) return ""; + if (times === 1) return str; + var result = ""; + for (var i = 0; i < times; i++) { + result = result.concat(str); + } + return result; } function upperFirst(str){ - + var result = ""; + return result.concat(str[0].toUpperCase() + str.slice(1)); } -function flatten(){ - +function flatten(arr){ + var result = []; + for (var i = 0; i < arr.length; i++) { + result = result.concat(arr[i]); + } + return result; } -function zip(){ +// BONUS +// passes in X number of arrays +// first array containing first elements, 2nd containing 2nd, etc. +// returns X number of arrays with those elements as listed +// e.g. [a,b,c], [1,2,3], [x,y,z] ==> [[a,1,x], [b,2,y], [c,3,z]] +function zip(){ + var result = []; + for (let n = 0; n < arguments[0].length; n++) { + result.push([]); + } + // there should be N nested arrays for N elements in each array passed in + // e.g. if first array has 10 elements, resulting number of nested arrays is 10 + + // loop through the arguments (they are all arrays) + // grab first/i element of each one, add to a new array + // add that new array to the result + for (let i = 0; i < arguments[0].length; i++) { + for (let j = 0; j < arguments.length; j++) { + result[i].push(arguments[j][i]); + } + } + return result; +} // note that this will only work if the longest array in the arguments is the 1st one passed in +// otherwise we would have to first find the longest array from the arguments + + +function unzip(){ // unzip takes in a result in the format of what's returned from zip + // e.g. [['a', 1, true], ['b', 2, false]], which has a length of 1 + var result = []; + // there should be N nested arrays for N elements in each arg + for (let n = 0; n < arguments[0][0].length; n++) { + result.push([]); + } + + // loop through the arguments (they are all arrays) + // grab first/i element of each one, add to a new array + // add that new array to the result + for (let i = 0; i < result.length; i++) { + for (let j = 0; j < arguments[0].length; j++) { + result[i].push(arguments[0][j][i]); + } + } + return result; } -function unzip(){ - +function flip(callback){ + // callback(arguments) ==> run stuff in callback on arguments.reverse + return function() { + // grab arguments and reverse them + var args = []; + for (var i = 0; i < arguments.length; i++) { + args.push(arguments[i]); + } + args.reverse(); + // spread out arguments so they're not in an array anymore and run through callback + return callback(...args); + } } -function flip(){ - +function flattenDeep(arr){ + var result = []; + for (var i = 0; i < arr.length; i++) { + if (Array.isArray(arr[i])) { + // if the current element is an array, + // we need to go down a layer to flatten that as well + // and then remember to add it to the result and reassign since concat doesn't modify original arr + result = result.concat(flattenDeep(arr[i])); + } else { + result.push(arr[i]); + } + } + return result; } -function flattenDeep(){ - -} diff --git a/lodash_exercise/lodashSpec.js b/lodash_exercise/lodashSpec.js index f0e90e9c..fcd548c8 100644 --- a/lodash_exercise/lodashSpec.js +++ b/lodash_exercise/lodashSpec.js @@ -161,6 +161,9 @@ describe("#has", function(){ it("should handle an array of keys as a parameter as well", function(){ expect(has(object, ['a', 'b'])).to.equal(true) }); + it("should return true if path is valid even with nested objects and >1 keys", function(){ + expect(has({'x': {}, 'a': {'b':3, 'c':4}, 'b': 3}, ['a','c'])).to.equal(true) + }); }); diff --git a/prototypes_exercise/prototypes.js b/prototypes_exercise/prototypes.js index e69de29b..10cf59bb 100644 --- a/prototypes_exercise/prototypes.js +++ b/prototypes_exercise/prototypes.js @@ -0,0 +1,53 @@ +// PART 1 + +function Person(firstName, lastName, favoriteColor, favoriteNumber, favoriteFoods=[]) { + this.firstName = firstName; + this.lastName = lastName; + this.favoriteColor = favoriteColor; + this.favoriteNumber = favoriteNumber; + this.favoriteFoods = favoriteFoods; + this.family = []; +} + +Person.prototype.fullName = function() { + return `${this.firstName} ${this.lastName}`; +} + +Person.prototype.toString = function() { + return `${this.firstName} ${this.lastName}, Favorite Color: ${this.favoriteColor}, Favorite Number: ${this.favoriteNumber}`; +} + +Person.prototype.addToFamily = function(personObj) { + // check if personObj is actually a Person object & if there is a duplicate + if (personObj instanceof Person && this.family.indexOf(personObj) === -1) { + this.family.push(personObj); + } + return this.family.length; +} + +// PART 2 + +Array.prototype.map = function(fn) { + var result = []; + for (let i = 0; i < this.length; i++) { + result.push(fn(this[i], i, this)); + } + return result; +} + +String.prototype.reverse = function() { + var result = []; + let temp = this.split(""); + for (let i = temp.length-1; i >= 0; i--) { + result.push(temp[i]); + } + return result.join(""); +} + +Function.prototype.bind = function(thisArg, ...outerArgs) { // anon func takes thisArg to reset the this, and other arguments if needed + var _this = this; // refers to the function that bind was called on + // _this takes whatever arguments that it usually would + return function(...innerArgs) { + return _this.apply(thisArg, outerArgs.concat(innerArgs)); + } +} \ No newline at end of file diff --git a/recursion_exercise/recursion.js b/recursion_exercise/recursion.js index e69de29b..2be46951 100644 --- a/recursion_exercise/recursion.js +++ b/recursion_exercise/recursion.js @@ -0,0 +1,89 @@ +function productOfArray(arr) { + if (arr.length === 1) { + return arr[0]; + } + return arr[0] * productOfArray(arr.slice(1)); +} + +function collectStrings(obj) { + var strings = []; + function collectStringsHelper(obj) { + for (var key in obj) { + if (typeof(obj[key]) === "string") { + strings.push(obj[key]); + } else { + collectStringsHelper(obj[key]); + } + } + } + collectStringsHelper(obj); + return strings; +} + +function contains(nestedObj, searchTerm) { + for (var key in nestedObj) { + if (typeof(nestedObj[key]) === "object") { + if (contains(nestedObj[key], searchTerm)) { + return true; + }; + } else if (nestedObj[key] === searchTerm) { + return true; + } + } + return false; +} + +function search(arr, val, currentIndex=0) { + if (arr[0] === val) { + return currentIndex; + } + // if an empty array is passed in, value is not found + else if (arr.length === 0) { + return -1; + } + // otherwise, increment the index to keep track of it, and then remove the + // value that was already checked, and pass in a shorter array to search() + else { + currentIndex++; + currentIndex = search(arr.slice(1), val, currentIndex); + } + return currentIndex; +} + +function binarySearch(arr, val) { + // sort the array, or assume sorted + // find the middle, compare + // need some value to store current index of the original array + var pivot = Math.floor(arr.length/2); + if (arr[pivot] === val) { + return pivot; + } + if (arr[pivot] > val) { + return binarySearch(arr.slice(0, pivot), val); + } + if (arr[pivot] < val) { + return binarySearch(arr.slice(pivot), val); + } + return -1; + // remove the middle and everything before or after it, + // depending on the comparison + // repeat +} + +function stringifyNumbers(obj, newObj={}) { +// Write a function called `stringifyNumbers` which takes in an object and +// finds all of the values which are numbers and converts them to strings. +// Return new obj with all numbers as strings + 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; +} \ No newline at end of file diff --git a/recursion_exercise/recursionSpec.js b/recursion_exercise/recursionSpec.js index 5bc841fe..2306ee0a 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) }); }); diff --git a/testing_exercise/testing.js b/testing_exercise/testing.js index e69de29b..3a93df66 100644 --- a/testing_exercise/testing.js +++ b/testing_exercise/testing.js @@ -0,0 +1,48 @@ +function replaceWith(str, replaceThisChar, replacementChar) { + // var arrayOfChars = str.split(""); + // arrayOfChars.forEach(function(val, index){ + // if (val === replaceThisChar) { + // arrayOfChars[index] = replacementChar; + // } + // }); + // return arrayOfChars.join(""); + return str.split("").map(function(val, index, array){ + if (val === replaceThisChar) return replacementChar; + return val; + }).join(""); +} + +function expand(arr, num) { + var result = arr; + for (var i = 1; i < num; i++) { + result = result.concat(arr); + } + return result; +} + +function acceptNumbersOnly() { + for (var i = 0; i < arguments.length; i++) { + if (typeof(arguments[i]) !== "number" || isNaN(arguments[i])) { + return false; + } + } + return true; +} + +function mergeArrays(arr1, arr2) { + var mergedArr = arr1.concat(arr2); + return mergedArr.sort(function(a, b){ + return a - b; + }); +} + +function mergeObjects(obj1, obj2) { + var result = {}; + for (var key in obj1) { + result[key] = obj1[key]; + } + for (var key in obj2) { + result[key] = obj2[key]; + } + return result; +} \ No newline at end of file diff --git a/testing_exercise/testingSpec.js b/testing_exercise/testingSpec.js index aef56b1d..0d9cbecc 100644 --- a/testing_exercise/testingSpec.js +++ b/testing_exercise/testingSpec.js @@ -1,3 +1,71 @@ var expect = chai.expect; -// WRITE YOUR TESTS HERE! \ No newline at end of file +describe("replaceWith", function(){ + it("returns a string", function(){ + expect(replaceWith("test", "t", "x")).to.be.a("string"); + }); + it("removes the designated character", function(){ + expect(replaceWith("test", "t", "x")).to.not.have.string("t"); + }); + it("inserts the designated character", function(){ + expect(replaceWith("test", "t", "x")).to.have.string("x"); + }); + it("replaces specific char with designated char", function() { + expect(replaceWith("awesome", "e", "z")).to.deep.equal("awzsomz"); + expect(replaceWith("Foo", "F", "B")).to.deep.equal("Boo"); + }); + it("is case sensitive", function(){ + expect(replaceWith("aBcBbBbBb", "B", "c")).to.deep.equal("acccbcbcb"); + }); +}); + +describe("expand", function(){ + it("returns an array", function(){ + expect(expand([1,2,3],3)).to.be.an("array"); + }); + it("should return an array that contains the original array a number of times", function(){ + expect(expand([1,2,3],3)).to.include.members([1,2,3]); + expect(expand([1,2,3],3)).to.deep.equal([1,2,3,1,2,3,1,2,3]); + }); +}); + +describe("acceptNumbersOnly", function(){ + it("returns a boolean", function(){ + expect(acceptNumbersOnly(1,2,3,4,5,6,7)).to.equal(true); + expect(acceptNumbersOnly(1,2,3,4,5,6,"hi")).to.equal(false); + }); + it("returns true if all items in array are numbers", function(){ + expect(acceptNumbersOnly(1,2,3,4,5,6,7)).to.be.true; + expect(acceptNumbersOnly(100,200,300,400)).to.be.true; + }); + it("returns false if not all items numbers", function(){ + expect(acceptNumbersOnly(1, "foo")).to.be.false; + }); + it("returns false if NaN is present", function(){ + expect(acceptNumbersOnly(1,2,3,4,5,6,NaN)).to.be.false; + }); +}); + +describe("mergeArrays", function(){ + it("returns an array", function(){ + expect(mergeArrays([2,1],[3,4])).to.be.an("array"); + }); + it("returns the array sorted", function(){ + expect(mergeArrays([2,1],[3,4])).to.deep.equal([1,2,3,4]); + }); +}); + +describe("mergeObjects", function(){ + it("should return an object", function(){ + expect(mergeObjects({hello:1, bye:2}, {hello2:3, bye2:4})).to.be.an("object"); + }); + it("should override value in first passed in obj if both objs have the same key", function(){ + expect(mergeObjects({hello:1, bye:2}, {hello:3, bye:4})).to.deep.equal({hello:3, bye:4}); + }); + it("should return an object with all the keys from both objs", function(){ + expect(mergeObjects({hello:1, bye:2}, {hello2:3, bye2:4})).to.have.all.keys("hello", "bye", "hello2", "bye2"); + }); + it("should not change the key-value pairs", function(){ + expect(mergeObjects({hello:1, bye:2}, {hello2:3, bye2:4})).to.deep.equal({hello:1, bye:2, hello2:3, bye2:4}); + }); +}); \ No newline at end of file