diff --git a/ajax_with_jquery_exercise/index.html b/ajax_with_jquery_exercise/index.html
new file mode 100644
index 00000000..b9a0ff4b
--- /dev/null
+++ b/ajax_with_jquery_exercise/index.html
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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..7cfdd132
--- /dev/null
+++ b/ajax_with_jquery_exercise/script.js
@@ -0,0 +1,162 @@
+"use strict";
+//////EVENT LISTENERS //////
+
+// $(function(){
+
+//On page refresh validate auth_key by getting favorites then last viewed page or top stories
+ checkIfLoggedIn()
+
+
+//// Top nav Login/Sign Up and Sign out BUTTONS////
+ // Signout hide, reset
+ $('#signOutBtn').click(function(){
+ var gliphicons = $('.glyphicon')
+
+ //reset to log out display
+ $loggedIn.toggleClass('display-hide')
+ gliphicons.removeClass("glyphicon-star-empty")
+ gliphicons.removeClass("glyphicon-star")
+
+ //clear stored data
+ localStorage.removeItem('auth_key')
+ auth_key = false;
+ favoriteStoryIds = {};
+
+ if(currentStory === 'favorites'){
+ currentStory = 'top'
+ displayStories()
+ }
+
+
+ })
+
+ // Hide/Show login form
+ $navLoginBtn.click(function(){
+ $errorMsgLoc.text('')
+ $mainLoginForm.toggleClass('display-hide')
+
+ })
+
+
+//// MAIN Login / Sign up FORM ////
+ //Toggle between login and sign up.
+ $loginSignUpTabs.on('click', function(){
+ $formLogin.toggleClass('active')
+ $formSignUp.toggleClass('active')
+ })
+
+ // Login Sign up Form
+ $mainLoginForm.on('submit', function(e){
+ var $email= $('#email');
+ var $password = $('#password');
+ var $loginSignup = $('.active').text() === 'login'? 'login' : 'signup';
+
+ e.preventDefault();
+
+ postData('favorites', $loginSignup , //login or signup request
+ function(result){
+
+ if(result.status > 299){ //If error, display error message.
+ $errorMsgLoc.text(errorMsgs.login)
+ } else {
+ //store auth key
+ localStorage.setItem("auth_key", result.auth_token)
+ auth_key = result.auth_token
+
+ //get favorites
+ if($loginSignup === 'login' ){
+ getData('favorites', 'stories', function(result){ // get favories
+ getFavoriteStoryIds(result) //Store favorites
+ })
+ }
+ $loggedIn.toggleClass('display-hide') // show logged in content (link to favorites, log out button)
+ displayGliphicon('justLogged') // display star gliphicon
+ $errorMsgLoc.text('') //clear error message
+ $mainLoginForm.toggleClass('display-hide') // hide login form
+ }
+ }
+ ,$email.val(), $password.val())
+
+ //Clear email and password form.
+ $email.val('')
+ $password.val('')
+ })
+
+//// END MAIN Login / Sign up FORM ////
+
+
+/// TOP NAV BUTTONS ////
+ $navBtns.click(function(e){
+ currentStory = $(e.target).attr('id');
+ localStorage.setItem("current_story", currentStory)
+
+ $dataDisplay.empty()
+
+ if(currentStory === 'favorites'){
+ favoritesList.forEach(story =>{
+ newData(story.title, story.url, story.created, story.by, story.story_id)
+ })
+ } else {
+ checkIfLoggedIn()
+ }
+ })
+/// END TOP NAV BUTTONS ////
+
+///Star Buttons - select favorites ///
+ $dataDisplay.on('click', '.glyphicon', function(e){
+ var location = $(e.target);
+ var locationParent = location.parent().children();
+ var storyId = location.parent().attr('id').trim()
+
+ e.preventDefault();
+
+ //Add favorite
+ if($(e.target).hasClass('glyphicon-star-empty')){
+ //Fav object. content scrapped from HTML
+ var addFav = {
+ hacker_news_story:{
+ by: locationParent.eq(3).children().text().trim(),
+ story_id: storyId,
+ title: locationParent.eq(1).text().trim(),
+ url: locationParent.eq(2).attr('href').trim()
+ }
+ }
+ postData('favorites', 'add', function(result){
+ if(result.status > 299){
+ $errorMsgLoc.text(errorMsgs.favorites)
+ } else {
+ location.toggleClass('glyphicon-star-empty glyphicon-star')
+ //Returning 'undefined' should return ID. Must refresh favorites to get id,
+ getData('favorites', 'stories', function(result){
+ if(result.status > 299){
+ auth_key = false
+ } else {
+ getFavoriteStoryIds(result)
+ }
+ })
+ }
+ }, addFav)
+ } else {
+ //Remove favorite
+ deleteData('favorites', 'delete', function(result){
+ if(result.status > 299){
+ $errorMsgLoc.text(errorMsgs.favorites)
+ } else {
+ location.toggleClass('glyphicon-star-empty glyphicon-star')
+ if(currentStory === 'favorites'){
+ $('#'+ storyId).remove()
+ }
+ }
+ }, favoriteStoryIds[location.parent().attr('id')])
+ }
+ })
+
+///End Star Buttons - select favorites ///
+
+
+
+// })
+
+
+
+
diff --git a/ajax_with_jquery_exercise/script_ajax.js b/ajax_with_jquery_exercise/script_ajax.js
new file mode 100644
index 00000000..514cfa17
--- /dev/null
+++ b/ajax_with_jquery_exercise/script_ajax.js
@@ -0,0 +1,88 @@
+"use strict";
+
+/////Ajax requests////
+function getData(name, type, fn, id){
+ var headers = name === 'favorites' ? {"Authorization": auth_key} : {};
+ $.ajax({
+ method: "GET",
+ headers: headers,
+ url: urls[name + type[0].toUpperCase() + type.slice(1)] + (!!id? id +'.json' : '')
+ })
+ .then(stories => fn(stories))
+ .fail(error => fn(error))
+}
+
+function postData(name, type, fn, arg, password){ //arg === id or email
+ var data = '';
+ var header = '';
+
+ if(type === 'login' || type === 'signup'){
+ data = JSON.stringify({
+ email: arg,
+ password: password
+ })
+ }
+
+ if(type === 'add'){
+ data = JSON.stringify(arg);
+ header = auth_key
+ }
+
+ $.ajax({
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": header
+ },
+ url: urls[name + type[0].toUpperCase() + type.slice(1)],
+ data: data
+ })
+ .then(stories => fn(stories))
+ .fail(error => fn(error))
+}
+
+function deleteData(name, type, fn, id){
+ $.ajax({
+ method: "DELETE",
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": auth_key
+ },
+ url: urls[name + type[0].toUpperCase() + type.slice(1)] + id + '.json'
+
+ })
+ .then(stories => fn(200))
+ .fail(error => fn(error))
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ajax_with_jquery_exercise/script_global_variables.js b/ajax_with_jquery_exercise/script_global_variables.js
new file mode 100644
index 00000000..4bce618f
--- /dev/null
+++ b/ajax_with_jquery_exercise/script_global_variables.js
@@ -0,0 +1,55 @@
+ "use strict";
+
+ //URLs//
+ //NOTE!!!
+ //Keys must be in the follow format 'name + type' eg (top + Stories), must be camel cased.
+ //See Ajax getData Url (name + type)
+ var urls = {
+ topStories : 'https://hacker-news.firebaseio.com/v0/topstories.json',
+ newStories: 'https://hacker-news.firebaseio.com/v0/newstories.json',
+ bestStories: 'https://hacker-news.firebaseio.com/v0/beststories.json',
+ itemStories: 'https://hacker-news.firebaseio.com/v0/item/', // id + .json --> get detail
+ favoritesStories : 'https://hn-favorites.herokuapp.com/stories.json',
+ favoritesAdd : 'https://hn-favorites.herokuapp.com/stories.json',
+ favoritesDelete : 'https://hn-favorites.herokuapp.com/stories/', // id + .json --> delete + ID.json
+ favoritesLogin: 'https://hn-favorites.herokuapp.com/login',
+ favoritesSignup: 'https://hn-favorites.herokuapp.com/signup'
+ }
+
+ //Error messages//
+ var $errorMsgLoc = $('.error'); // Error message placement in HTML
+
+ var errorMsgs ={
+ favoritesNone: "No favorites selected.",
+
+ //Ajax error messages
+ favorites : "Could not load favorites at this time. Please try logging in again.",
+ login : "Invalid username or password. Please try again.",
+ stories: "Could not load stories. Please check your internet connection or try back later."
+ }
+
+//Content Display Settings//
+ var numberGetStories = 20; //number of request made
+ var lastStoryDisplayed = 0; //starting number
+
+//Buttons//
+ var $navLoginBtn = $('#loginSignUpBtn');
+ var $mainLoginForm = $('#loginSignUpForm');
+ var $dataDisplay = $('ol');
+ var $navBtns = $('.navbar-nav');
+ var $signOutBtn = $('#signOutBtn');
+ var $loggedInBtn = $('#loginSignUpBtn');
+
+ //Login Sign Up Form Buttons
+ var $loginSignUpTabs = $('.nav-tabs');
+ var $formLogin = $('#formLogin');
+ var $formSignUp = $('#formSignUp');
+
+//Stored Items//
+ var favoritesList;
+ var favoriteStoryIds;
+ var auth_key = localStorage.getItem("auth_key");
+ var currentStory = localStorage.getItem("current_story") || 'top';
+
+ //Hide Show Toggle logged in content
+ var $loggedIn = $('.loggedIn');
diff --git a/ajax_with_jquery_exercise/script_methods.js b/ajax_with_jquery_exercise/script_methods.js
new file mode 100644
index 00000000..6a7d45b9
--- /dev/null
+++ b/ajax_with_jquery_exercise/script_methods.js
@@ -0,0 +1,100 @@
+"use strict";
+
+function getFavoriteStoryIds(stories){
+ //save favorites
+ favoritesList = stories;
+
+ //object with key as Hacker News Story ID and value as Favorite ID
+ //key to look up gliphicons (stars)
+ //value to delete favorites
+ favoriteStoryIds = stories.reduce((acc, story) => {
+ acc[story.story_id] = story.id;
+ return acc
+ },{});
+}
+
+
+function checkIfLoggedIn(){
+ if(auth_key === 'undefined' || !auth_key){
+ auth_key = false
+ displayStories()
+ return
+ }
+
+ getData('favorites', 'stories', function(result){
+ if(result.status > 299){
+ auth_key = false
+ if($loggedInBtn.hasClass('display-hide')){
+ $loggedIn.toggleClass('display-hide')
+ }
+ displayStories()
+ } else {
+ getFavoriteStoryIds(result)
+ if($signOutBtn.hasClass('display-hide')){
+ $loggedIn.toggleClass('display-hide')
+ }
+ displayStories()
+ }
+ })
+}
+
+
+function displayStories(){
+ getData(currentStory, 'stories', function(stories){
+ var selectStoryIds = stories.slice(lastStoryDisplayed, lastStoryDisplayed+numberGetStories)
+
+ selectStoryIds.map(story =>
+ getData('item', 'stories', function(storyDetail){
+ newData(storyDetail.title, storyDetail.url || 'http://rithmschool.com', storyDetail.time, storyDetail.by, storyDetail.id)
+ }, story)
+ )
+ })
+}
+
+
+
+function newData(title, url, time, author, id){
+ $dataDisplay.append(
+ `
+ ${displayGliphicon(id)}
+ ${title} ${createUrl(url)}
+ submitted ${time} by ${author}
+
+ `)
+}
+
+function createUrl(url){
+ url = url || 'http://rithmschool.com' //default URL when URL is not provided
+
+ //short URL
+ // Example - Full URL 'http://google.com' - Short URL - 'google.com'
+ var rmHttp= url.indexOf('//')+2;
+ var urlShort = url.slice(rmHttp,url.indexOf('/', rmHttp) === -1 ? url.length: url.indexOf('/', rmHttp));
+
+ return `
(${urlShort}) `
+}
+
+function displayGliphicon(input){
+ if(input === 'justLogged'){
+ $('ol li').each(function(){
+ var location = $(this).children().eq(0)
+ if(!jQuery.isEmptyObject(favoriteStoryIds) && favoriteStoryIds[$(this).attr('id')]){
+ location.addClass('glyphicon-star')
+ } else {
+ location.addClass('glyphicon-star-empty')
+ }
+ })
+ return
+ }
+
+ if(auth_key){
+ if(favoriteStoryIds[input]){
+ return'
'
+ } else {
+ return'
'
+ }
+ }
+
+ return `
`;
+
+}
\ 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..5b77ec13
--- /dev/null
+++ b/ajax_with_jquery_exercise/style.css
@@ -0,0 +1,33 @@
+ol > li > p{
+ color: gray;
+ font-size: 10px;
+}
+.error{
+ color: red;
+}
+
+.display-hide{
+ display: none !important;
+}
+
+.pad-left{
+ padding-left: 20px;
+}
+.header{
+ background: orange;
+ border-radius: .2em;
+ margin-top: 2em;
+}
+a {
+ text-decoration: none !important;
+ color: black;
+}
+li > a {
+ color: gray;
+}
+.margin-bottom{
+ margin-bottom: 1em;
+}
+.main{
+ background: #fff7ea;
+}
\ No newline at end of file
diff --git a/call_apply_bind_exercise/callApplyBind.js b/call_apply_bind_exercise/callApplyBind.js
index e69de29b..fbb6fdb7 100644
--- a/call_apply_bind_exercise/callApplyBind.js
+++ b/call_apply_bind_exercise/callApplyBind.js
@@ -0,0 +1,71 @@
+var obj = {
+ fullName: "Harry Potter",
+ person: {
+ sayHi: function(){
+ return "This person's name is " + this.fullName;
+ }.apply(obj)
+ }
+}
+
+console.log(
+obj.person.sayHi
+)
+
+var obj = {
+ fullName: "Harry Potter",
+ sayHi(){
+ return "This person's name is " + this.fullName
+ }
+}
+
+
+function sumEvenArguments(){
+ var args = [].slice.call(arguments);
+
+ return args.reduce((acc, num)=>{
+ if(num % 2 === 0) acc += num
+ return acc;
+ },0)
+}
+
+function arrayFrom(args){
+ return [].slice.call(args);;
+}
+
+function invokeMax(fn, num){
+ var count = num;
+ return function add(a,b){
+ if(count <= 0) return 'Maxed Out!'
+ count--;
+ return fn.apply(this,arguments);
+ }
+}
+
+var game = guessingGame(5)
+
+function guessingGame (numTries){
+ var answer = Math.floor(Math.random()*11);
+ var guesses = 0;
+
+ return function guess(num){
+ guesses++
+ if(numTries <= guesses) return "You are all done playing!"
+ if(num === answer) return "You got it!"
+ if(num < answer) return "You're too low!"
+ return "You're too high!"
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/canvas_exercise/Demo/index.html b/canvas_exercise/Demo/index.html
new file mode 100644
index 00000000..e9f02b4a
--- /dev/null
+++ b/canvas_exercise/Demo/index.html
@@ -0,0 +1,12 @@
+
+
+
+
Canvas Intro
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/canvas_exercise/Demo/index.js b/canvas_exercise/Demo/index.js
new file mode 100644
index 00000000..ff9dbb0a
--- /dev/null
+++ b/canvas_exercise/Demo/index.js
@@ -0,0 +1,39 @@
+// document.addEventListener("DOMContentLoaded", function(){
+ var canvas = document.getElementById("my-canvas");
+ canvas.width = canvas.scrollWidth;
+ canvas.height = canvas.scrollHeight;
+
+
+ var x = 0;
+ var y = 0;
+ // var addX = 2;
+ // var addY = 3;
+
+ // var ctx = canvas.getContext('2d');
+ // ctx.fillStyle = "pink";
+ // ctx.fillRect(x,y,100,100);
+ // ctx.clearRect(0,0,canvas.width,canvas.height);
+
+
+ canvas.font = '48px serif';
+ canvas.strokeText('Hello world', 10, 50);
+
+ // function update(){
+ // ctx.clearRect(0, 0, canvas.width, canvas.height);
+ // x+= 1;
+ // y+= 1;
+ // ctx.fillRect(x,y,100,100);
+ // }
+
+ // function update() {
+ // ctx.clearRect(0, 0, canvas.width, canvas.height);
+ // if (x > canvas.width || x < 0) { addX *= -1; }
+ // if (y > canvas.height || y < 0) { addY *= -1; }
+ // x += addX;
+ // y += addY;
+ // ctx.fillRect(x, y, 100, 100);
+ // } 4
+
+ // setInterval(update, 10)
+
+// });
\ No newline at end of file
diff --git a/canvas_exercise/Demo/style.css b/canvas_exercise/Demo/style.css
new file mode 100644
index 00000000..088ca938
--- /dev/null
+++ b/canvas_exercise/Demo/style.css
@@ -0,0 +1,5 @@
+#my-canvas {
+ background-color: blue;
+ height: 400px;
+ width: 400px;
+}
\ No newline at end of file
diff --git a/canvas_exercise/shapes_game/index.html b/canvas_exercise/shapes_game/index.html
index 97529df5..57ab4c24 100644
--- a/canvas_exercise/shapes_game/index.html
+++ b/canvas_exercise/shapes_game/index.html
@@ -6,7 +6,7 @@
-
+
@@ -39,4 +39,5 @@
Down
+