# Homework 9: Javascript Javascript gives us the ability to perform computation and change the display to the user without requesting information from the backend. We will be using [JQuery](https://jquery.com/): a common Javascript library for modifying the DOM. Before we start, some general Javascript notes: * NEVER use the `var` keyword. When you want to declare a mutable variable, use `let`. One example of why is [here](https://hackernoon.com/why-you-shouldnt-use-var-anymore-f109a58b9b70). * There are several ways to write functions. Read [here](https://stackoverflow.com/questions/34361379/are-arrow-functions-and-functions-equivalent-exchangeable) for some context. Feel free to use either. The stencil uses arrow functions. * Use `const` for immutable values. * [This](https://htmlcheatsheet.com/js/) cheatsheet has a lot of useful examples. * When in doubt about syntax or how to do something, Google it! * Here's a couple more helpful sites: * [Javascript](http://javascript.info/) * [Mozilla's Javascript docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript) * [W3 Javascript tutorial](https://www.w3schools.com/js) * [REST](https://www.restapitutorial.com/lessons/restquicktips.html) * [JSFiddle](https://jsfiddle.net/) * [codepen](https://codepen.io/) For this homework you will be working in your local environment. The templates for this homework are [here](https://github.com/browncs6/Homework9.git). You will need to duplicate this repo (read: [duplicating](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/duplicating-a-repository)). When creating a new repo (to duplicate to) please name it cs0060-<_your-cs-login_>-hw9, then set it to be [private](https://help.github.com/en/github/administering-a-repository/setting-repository-visibility#making-a-repository-private). Then complete all your work/testing locally and push to your private repo. Then add the following github usernames as [contributors](https://help.github.com/en/github/setting-up-and-managing-your-github-user-account/inviting-collaborators-to-a-personal-repository) (so we can access your code). * jnrolfe * samstronghammer * leonhardfs * hershgupta404 * caoruiming * aninah __We will need to clone your repo and run your code for grading__. __NOTE__: If you do not have a Github Pro account you cannot add more than 3 collaborators to a private repo. You can get Github Pro for free by signing up for the [education pack](https://education.github.com/pack) using your Brown email address. __NOTE__: This homework consists of 3 problems. Problem 1 and Problem 2 are individual assignments, and each student should solve them on their own. Problem 3 is a problem on which you work with your team, you may also contact your team TA to help you on this if you're struggling as a team. Please hand it in like an individual assignment though. ## Problem 1 For this problem we have provided a webpage in the `p1` directory and you will be editing it on the fly using Javascript. The webpage currently looks like this: <img src="https://i.imgur.com/QzWPYaz.png" style="border-style:solid;border-width:5px;" /> You will be writing code to transform it into this: <img src="https://i.imgur.com/n7i4seQ.png" style="border-style:solid;border-width:5px;"/> You will do the following: * The following changes need to happen when the button is pressed: * Main header transitions from "Homework 9: Problem 1" to "HW9 P1 DONE :)". This is implemented for you. * The paragraph of text before the recipie should change to having a text size of 24px. (_hint:_ check [this](https://api.jquery.com/css/) out) * The recipe list should be filled in with the contents of the provided list `ingredients` using a `for` loop. (_hint:_ check [this](https://api.jquery.com/append/) out) * The graffiti on the bottom of the website should be changed from the text "SEALION WAZ HERE" to "PENGUINZ RULE". (_hint:_ check [this](https://api.jquery.com/text/) out) * The blue square should have a click handler bound to it that causes it to change color randomly whenever it is clicked. (_hint:_ check [this](https://api.jquery.com/css/) out and use the utility function in our stencil). To test your code, open the `index.html` file in your browser. Click the "Apply Changes" button to invoke the `apply_changes` function in `p1.js` (this is bound for you). Reload the page to try again. Sometimes you'll need to perform a hard refresh of the javascript files, because modern browsers typically cache them. <https://fabricdigital.co.nz/blog/how-to-hard-refresh-your-browser-and-clear-cache> lists all the key combination for various browsers/platforms to perform a hard refresh. ## Problem 2 Freddy the Fiordland penguin wants to be able to chat with all of his other penguin friends. He knows of a chat server, but doesn't have a front-end so they can interact with it. For this problem the back-end has been implemented and is live! You will be interacting with it to communicate with other users. Feel free to make several users and send messages between them. You'll also be able to send messages to the accounts other people are making. That being said, we expect two things: 1. Do not attempt halt, attack, or hack the server. This will be considered an academic code violation. 2. Do not send any inappropriate or mean messages to other users of this server. This will also be considered an academic code violation. We will be using two different ways of connecting with the server. One is a websocket. This allows the server to update the client quickly when changes occur. The other is the POST messages with callbacks that you are used to. We have handled the logic of setting up the websocket for you in the stencil. To see what you're working on, open the .html file in a web browser. The web development sidebar is also very helpful (right click on page, click inspect element). Keep an eye on the console to work on debugging. For each post request, you will be using following this format (it's JQuery): ``` $.post(<URL>, <data JSON>, <callback function>); ``` All post requests will be going to this address: `http://157.245.2.52:7000/chat`. That is where the server is running. Fun fact-- it's running on the test droplet we used for problem 5 for homework 3 :smile: Below is the API that you will be using. Read it carefully. Implement one piece at a time and see if it works. ### API All of the messages sent between the client and server (in either direction) will always have a ```type``` and usually have a ```payload```. All of your sent messages (excluding the `CONNECT` message) will also have a `token` to stay logged in. The types are listed in the ```MESSAGE_TYPE``` enum for you. The expected shape for each of these messages is defined below. You will be constructing messages to send to the server and deconstructing messages from the server. Don't forget that you can always test your requests with cURL! #### Client -> Server * ```CONNECT```, `POST`: This is used to "log in" to the server. When you successfully send this message the first time, the server will store your username and your salted, hashed, password pair. Then, if anyone tries to sign in with your username without the password, it will fail. So, don't forget your password! Additionally, it will prevent you from signing in to the same user in more than one place simultaneously (including multiple tabs). After sending this message, the response can be read in the callback. ``` { type: CONNECT payload: { username: "penguin37" password: "I<3BoardGames" } } ``` * ```MSG```, `POST`: This is used to send a message to another person. If they are currently online, they will be sent the message immediately. If not, it is recorded in the message history and will be accessible to the other user when they log in. If you send a message to yourself, it will fail and you will receive an error message. The callback will receive confirmation that the message sent *or* an error stating why it didn't work. ``` { type: MSG token: "askdlfnEOIB2askdlfnEOIB2" payload: { to: "penguin42" msg: "Hey, do you want to hang out later?" } } ``` * ```HISTORY```, `POST`: This is used to request your message history with another user. The payload should contain the username of the other user. This is how you sign back in and see old messages. ``` { type: HISTORY token: "askdlfnEOIB2askdlfnEOIB2" payload: { user: "penguin 42" } } ``` #### Server -> Client * ```CONNECT```, callback response: This is a response to a ```CONNECT``` message from the client. The backend returns a `token`. This is the token you will use to authenticate all future messages. ``` { type: CONNECT payload: { token: "askdlfnEOIB2askdlfnEOIB2" } } ``` * ```MSG```, websocket: This occurs when a user has sent you a message. ``` { type: MSG payload: { from: "penguin42" msg: "Hey, do you want to hang out later?" } } ``` * ```HISTORY```, callback response: This is sent in response to a ```HISTORY``` message from the client. It contains an ordered list of messages you have exchanged with the other user (oldest first, newest last). In this case the payload is a list. ``` { type: HISTORY payload: [ { from: "penguin42" to: "penguin37" msg: "Hey, do you want to hang out later?" }, { from: "penguin37" to: "penguin42" msg: "Sure!" }, { from: "penguin42" to: "penguin37" msg: "Fantastic. Is 8pm ok?" }, { from: "penguin37" to: "penguin42" msg: "Yup! I'll bring Settlers of Catan." } ] } ``` * ```LIST```, websocket: This is sent to all users when anyone logs in or closes the tab. It contains the list of online and offline users in the payload. ``` { type: LIST payload: { online: [ "penguin37", "penguin42" ] offline: [ "penguin 11", "penguin 23" ] } ``` * ```SENT```, callback response: This is used to confirm that a ```MSG``` message was valid and went through. There is no payload because the caller knows what message it pertains to through the callback. ``` { type: SENT } ``` * ```ERROR```, callback response: This message should only be sent by the server. It will contain an error type and message in the payload. This can be sent in place of the expected response if the user input was invalid or malformed. ``` { type: ERROR payload: { type: LOGIN_ERROR msg: "Incorrect password." } } ``` If you have any issues with the server (API isn't behaving as documented, requests aren't going through, etc.) please email Sam at samuel_oliphant@brown.edu. He wrote the server. ### Implementation You will be working under the `problem2` directory for this problem. We have provided you with a stencil that gives basic css/html, but the JavaScript that makes the application come to life is sorely lacking. You will notice a number of TODOs marked in the files. We will outline these TODOs here. #### login.js 1. Declare elements: this is a series of let statements where you declare the JQuery elements you plan to use across the file. 2. `login_attempt`: read the API so you know what the backend expects and what to expect in response. Make sure that when you set the `window.location` variable you include the token in the form `<url>?token=<token>`, or else `chat.js` won't work 3. Bind the let statements you made in 1. 4. Add a [click handler](https://api.jquery.com/click/) for the login button #### chat.js [Template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) will likely be very helpful for parts of this file. 1. Declare elements: this is a series of let statements where you declare the JQuery elements you plan to use across the file. 2. `handle_message`: handles three different types of messages. You may want to unpack them and hand the results to helper functions. The .LIST case is where you will likely want to use the template literals and `onclick` properties. 3. Helper functions: Up to you. It will clean up your code to factor these out. 4. `set_current_conversation`: This should be called every time a list element is clicked in the list of online or offline users with the username as an argument. When this function is called you will need to request your message history with that user and display the response. Exactly how it is displayed is up to you, but someone using your front end should be able to understand who sent what message and in what order. 5. `send_message`: Send a message to the user you are currently conversing with through a POST request. 6. Bind the let statements you made in 1. 7. Add a [click handler](https://api.jquery.com/click/) for the send button #### improvements To get full credit for this problem we'd like you to spend some open-ended time working on nothing but the look, feel, and behavior of the website. You may have to edit the css, html, or JS of the page to accomplish your changes. Try playing with the color of different elements. Perhaps add a mouse-over coloring or effect. Think about what would annoy you as a user (or what about the look isn't appealing) and fix it. Fix at least four things (or three bigger things) and write about what you fixed in your Gradescope handin. A few of possible changes: * Add a div or something so any errors that occur are displayed there instead of just in the console * Making chat history more pretty (think about other chat applications you've used and their looks) * Download a font and use it in your page, <https://fonts.google.com/> is a great resource for this. * Put the list of offline users in a box with a maximum height that can scroll so it doesn't stretch the page (the same can be done with message history). * Notify the user whenever they receive a message (even if they aren't currently conversing with the person who sent it). This could be done with highlighting or a box that contains notifications. * Make the webpage visual compelling by styling it using a color palette, inspiration can be found under <https://flatuicolors.com/> and <https://www.colourlovers.com/> ## Problem 3 The last problem, again, will be related to your final projects. While you still don't have databases, you can begin work on the look and feel of the front-end. You will submit two things: * A basic flow chart for your website. We do not expect here a full wireflow chart typically used in UI/UX design for a web application, a simple directed graph with the nodes and edges labeled is sufficient. It should help you plan out your website! * The nodes are parts of your website * The edges are ways of getting from site to site * At least *two* html/css pairs that are mockups of how you want your website to look. You can use placeholders and text stubs if necessary. * Make a shared GitHub repo for your team. Ensure that it is private and that you have added the five TAs as collaborators. This is where you'll be working on your final project. Make a folder in the root of the repo called "mocks". Put the html/css there. For example, if your website has a login page, a page for each user, a page for browsing users, and a page for each image that the users post (to see it bigger or something), the graph might look something like this: ![](https://i.imgur.com/8NYQ8id.jpg) This is just a quick sketch. Please spend some time making the graph thorough and look nice. This will be your blueprint for making the website so give naming careful consideration. To hand in, do both of these parts in a shared hackmd.io document with your teammates. Include an image of the graph and a screenshot of each rendered html page in the document along with any description of the page that you deem necessary (regarding functionality of different buttons on the page, etc). Put a link to this hackmd.io document in your Gradescope handin. Also include a link to your group's GitHub repo. ## Deliverables ### GitHub Repo: #### Problem 1 Implement as described in problem 1. #### Problem 2 Implement as described in problem 2. #### Problem 3 Provide the html/css used to generate the images in your Gradescope handin. ### Gradescope: Your CS login #### Problem 1 N/A #### Problem 2 Description of what you did for the Improvements section. #### Problem 3 A link to your group's repo and a link to your group's hackmd.io document.