Assignment 3: JavaScript CSC309: Programming on the Web Home handouts Assignment 3 Assignment 3: JavaScript Due date: Tue March 29, 2022 23:59:00 remaining Objectives In this assignment, you will write JavaScript scripts to make an HTML file interactive. The questions simulate some popular use cases of JavaScript that could be very well needed in implementing a website. Note that even though what was taught in the lectures is enough "knowledge" to cover this assignment, it is quite possible that some specific functions, queries, or tricks are not covered in the lectures. There are millions of features in web programming, and it is really impossible to teach them all in a lecture. Therefore, you are welcome to refer to the slides or online resources to lookup for specific things. However, please be mindful that you will not violate academic integrity, as explained later on. Notes This assignment will make up 15% of your final grade. The due date is Tuesday, March 29th at 23:59:00. Late submissions will incur a 15% penalty per day for a maximum of 3 days. If you have any questions or problems with the assignment, please post them on Piazza. Most of your submissions will be auto-graded. Therefore, your code must adhere to all details provided in the handout; otherwise, you might lose marks. It is absolutely recommended that you test your code on Google Chrome version 99. The auto tester will test your code through that browser. You still can use other browsers but at your own risk of different JS behavior/interpretation in different browsers. You will not receive any feedback from the auto grader before the deadline has passed. So it is your responsibility to double-check your code with the handout before submission. Even minor spelling mistakes can lead to loss of marks. No remark requests will be accepted on these matters. Submission You should submit your work to your git repository on Markus. That is, you cannot submit through its normal web interface. Instead, commit and push your codes to your repository for assignment 3. Find out your repo's URL by logging into Markus. Also, do not leave your commits to the very last minutes before the deadline. Academic Integrity Assignments are individual work which means that you will not be allowed to seek advice from other students or copy/paste someone else's code, even open-source codes from the internet. However, you are allowed to look at online resources, tutorials, and Q&A websites over the course of solving the problems. The entire code must be written by yourself. What to submit You can find the starter code here. You must only modify controller.js and put all of your JS logic there. This is the only file you should submit as well. Similar to previous assignments, push this file to your repo for assignment 3 on Markus. You must not attempt to add new files or modify other files. JavaScript Syntax You can use all the built-in tools and syntax that exist in JavaScript ES6 (ECMAScript 2015). Moreover, jQuery 3.6.0 is already included in the start code, and you could use that as well. In all questions, you can use either the plain JS functions or jQuery functions (or both of them). However, you are not allowed to import any other library or package. Can you validate me? You are given a signup form that inputs username, password (with its repeat), email, and phone. You are asked to provide the client-side validation for this form. That is, fields should be validated offline and in real time. Validation criteria and errors are as follows. Username must be at least six characters long and only consist of letters (lowercase or uppercase), digits, and underscore. If at least one of these conditions does not hold, display Username is invalid Password must be at least eight characters long, and it must include at least one digit, one lowercase letter, one uppercase letter, and one sign (i.e., a character from the set !@#$%^&* ). Otherwise, show Password is invalid Repeat password must be equal to password. Otherwise, display Passwords don't match Email must be a valid email address. If not, put the error message Email is invalid Phone must follow the following format: ???-???-????, where each ? is a digit. That is, three digits, followed by a dash, followed by three digits, another dash, and four more digits. Unsurprisingly, the error message for this field should be Phone is invalid Note that in a real-world application, these validation errors are often very bad choices because they give so little information to the user about what is wrong with their current input. However, to make things easier for you, we did not choose more detailed errors! Validation Each field must be validated every time its value changes (after the input box loses focus). Repeat password should also be validated if password changes. If there is an error with a field, you should turn the input background red and put the corresponding validation error inside the
element that directly follows the input in the HTML file. For example, username error should be displayed inside the element with ID username_notification, and so on. Once the error is resolved (after losing focus), the red background and the error message should disappear. The request When the button is clicked, you must validate all fields before sending a request. If there is an error, put At least one field is invalid. Please correct it before proceeding inside the
element with ID notification. Also, the problematic fields should become red, and their relevant error messages should be shown. If all fields are valid, send the following request: URL: https://mcsapps.utm.utoronto.ca/csc309s22/a3/register Method: POST Content type: application/json (Send a JSON string as the body of your request) Payload: username, password1, password2, email, phone Response codes: 200 OK: display User added 404 NOT FOUND: put Unknown error occurred 409 CONFLICT: print Username has already been taken inside the paragraph element mentioned above. Note 1: The request must be sent without a page reload. Moreover, make sure that the messages are exactly the same as quoted in this handout and are placed inside the right element. The auto tester will run a case-sensitive check and will deduct marks if there is a typo or any other difference. Note 2: If you implement everything correctly, you should never receive 404 NOT FOUND from the server. This error (and any other status code not listed above) means that there is something wrong with your request. A screenshot is shown below to help you with how the error handling should like. First day at Amazon It is early 1994, and you just found your first job. It is an unknown startup with the weird name "Amazon." Amazon is supposed to be an online shopping platform. Even though the idea sounds so stupid as only a few people have access to internet, your boss, Jeff, believes that someday it will be the greatest company in the world. Jeff has just fired the CTO as they did not believe in JavaScript and insisted that it would go obsolete in a year or two. Now, Jeff relies on you to complete his shopping cart page. If you do so correctly, you will become the new CTO of this startup and receive a salary of $0 per month, as well as 10% of the company's worthless shares. You must keep track of the user's shopping cart, which is a list of Item from model.js. When the user clicks on Add/Update item, you should add (or update if it already exists) an item inside its shopping cart and list the cart items in the bellow table (with ID cart-items). The
that encloses the row should have an ID equal to the name of the item. However, since an ID cannot contain whitespaces, you must replace them with underscores. You can assume that item names will not contain underscores. Each row must include the name, price, quantity, and total price (quantity times price) of an item. Also, there are three additional columns in which you should put a minus button (with class decrease), plus button (with class increase), and delete button (with class delete), respectively. The plus button increments the quantity of that item, while the minus button decrements it. The delete button removes the whole row from the table. Every time the cart updates, you should calculate the subtotal (sum of prices), taxes (a fixed 13% HST), and grand total (subtotal plus taxes). These values should be placed inside the tags with ID's subtotal, taxes, and grand_total, respectively. Notes The Add/Update Item button should be ignored unless all three fields are non-empty. Quantity must never become negative. That is, if the user keeps pressing the minus button, quantity must stop at zero. Moreover, an item whose quantity is zero should still remain on the list as the user might change their mind later on. You can assume that the user inputs a non-negative integer for quantity and a non-negative float with at most two decimal places for price. All displayed numbers should be rounded to two decimal places. Only put the numbers and refrain from adding the dollar sign ($) or commas (,). These make the auto tester mad. Pay attention to the details of the buttons and rows mentioned above. You must put the buttons in the exact mentioned order, and each must occupy one table cell. Also, you should make sure that your elements adhere to all specified classes and IDs. Failure to do so would cause a lot of confusion for the auto tester, and it will deduct your marks significantly. Add vs. update: Whenever the user clicks on Add/Update Item, if the item's name is not already present in the cart, you should create a new item and add a new row to the table. However, if there is already an item with the same name, you must update its price and quantity according to the new input. The below screenshot is an example of what the cart should look like. The HTML code for the first row should look like the following:
Kinder Chocolate Single Bars
0.54
36
19.44
Scroll to death Infinite scrolls brought about major changes in the way users interact with web/mobile applications. Previously, paginated contents, which are data lists too big to render in one fetch, used to be broken down into pages. Each page would be fetched separately, and the user could move to the next or previous page. However, this requires an active action from the user (Clicking or touching the next page button). The solution here was to make it seamless so that the user would not need to actively make a decision about staying on the app or leaving it. Therefore, infinite scrolls came about. In other words, once you are close enough to the end of the page, the new page will be fetched and rendered so that you preferably do not even realize that you moved to a new page. In this question, you are to implement such a scroll for pieces of text. When the page loads, you should fetch the first page (paragraphs 1 to 5), and every time the user reaches the bottom of the page, you should fetch and render the next page (basically the next five items). When there is no more content to show, you should tell the user that they have reached the end. Rendering instructions You should render all paragraphs inside the
with ID data. Each paragraph must be wrapped with a
with ID paragraph_. Paragraph's content should then follow as a child
element. At the end of the paragraph, print (Paragraph: ) in bold. After the paragraph, render a button with class like that shows the current number of likes for that paragraph. When that button is clicked, you must send a request to the server to add a new like. Upon the server's response, you should extract the new number of likes and replace the current number with that. You can refer to the screenshot at the end of the question as an example. If the response indicates that there is no more page to show, add a new paragraph whose content is the following text in bold (wrapped by the tag): You have reached the end. From that point on, you should not send any additional requests to the server for the next pages. APIs URL: https://mcsapps.utm.utoronto.ca/csc309s22/a3/text/data?paragraph= Method: GET Payload: paragraph, likes, content Example response:
{"data":[
{"paragraph": 1, "likes": 70, "content": "some long text...."},
{"paragraph": 2, "likes": 35, "content": "some very long text..."},
{"paragraph": 3, "likes": 0, "content": "another long text. come on you can imagine it."},
{"paragraph": 4, "likes": 0, "content": "please be patient until I show you some long text"},
{"paragraph": 5, "likes": 0, "content": "technical problems stop me from being successful"}
], "next": true
}
Note 1: The server returns the page that starts with the paragraph number sent in the query parameters. For example, if number is set to 6, the server returns paragraphs 6 to 10 (inclusive). The first paragraph is paragraph 1 (not paragraph 0). Note 2: The value associated with next indicates if there is more data to come. In this example, true means that at least paragraph number 6 exists. Therefore, you must fetch the next page when the user reaches the end of the page. URL: https://mcsapps.utm.utoronto.ca/csc309s22/a3/text/likes Description: Adds a new like for a paragraph and returns its up-to-date number of likes Method: POST Content type: application/json Payload: paragraph (the paragraph number) Example response:
{"data": {"likes": 77}}
Note: be careful that you precisely follow the rendering instructions above as the auto tester will look for the exact set of elements described. A screenshot of the list and the corresponding elements is shown below. Note that the picture is only meant to show you the structure of the elements and their respective classes and IDs. So the actual data you receive from the server might be different. Note 2: do not forget to set the proper ID for the