Groups
You can work in groups of two on this assignment.
Pair Programming
It is strongly recommended that you use formal “pair programming”, where one person (the driver) types/creates and the other (the navigator) observes/assists. Moreover, you should alternate roles so each person takes on each role for a roughly equal amount of time. Remember that a spokesperson will be designated at checkout time, so both group members need to be comfortable presenting the work.
Repositories
Before configuring a repository, decide if you will be working in a group or not. If you will be working in a group, decide who will create the GitHub group and who will join it.
Follow the same basic process used in studios and previous assignments to create/join a group, download the resulting repository (with GitHub Desktop), and import it using the Particle Desktop IDE.
The GitHub Link is: https://classroom.github.com/g/2nCqLnh-
Files in your repository:
The repository currently contains several files:
GarageApp.html
is empty, but it should be updated to include the UI.
GarageApp.js
is empty, but it should be updated to include the “controller” that will control the UI and interact with the Garage.
GarageModel.js
is empty, but it should be updated to include an object that is a reasonably accurate model of the Garage Door Opener.
GarageModelTestStub.html
is an HTML file that just includes the contents of GarageModel.js
. It can be used to test the garage
model in the JavaScript console.
README.md
contains some questions you need to complete when you are done with the assignment.
You may merge in your work from Assignment 1 (copy/paste) and you’re allowed to add more files (images/resources used, a file containing all your CSS, etc.)
The Problem
DBI was happy with your work on the garage door UI prototype, but they’ve decided they’d like to test a working prototype to get a better sense of how it will behave with a real garage door. They already understand how user accounts will work, so they want you to focus on other functionality for now.
Your (Second) Assignment
DBI wants to see your user interface in-action. They expect to see:
- Navigation between the Status and Basic Controls screen and the Advanced Features screen,
- Demonstrations of the features of the Status and Basic Controls page, and
- Demonstrations of the features controlled by the Advanced Features page.
Implementation Requirements
- DBI has a preference for “Single Page Applications”. That means:
- You shouldn’t be using any
<form>
elements at all.
- The individual HTML files that you created for the first demo should be merged into a single HTML file, where each “screen” of visual content is contained within a
<div>
. The <div>
s can be hidden or shown to give the appearance of switching screens without actually loading a new page. (Hint: You can use the .hidden
property of the element, like document.getElementById("anId").hidden = true;
, to hide or show elements. It’s also possible to use CSS to animate transitions, which may give a much more satisfying look-and-feel.
- DBI plans to eventually support real hardware for the door. Consequently, they would like a clean separation between the UI and the elements that will eventually be handled by hardware. The hardware team has decided it may be best to create a
garage
object that will be an event-driven model of the Garage Door Opener. You should be able to develop and test this model independently.
- The
garage
should support the same types of features as the actual garage door remote control. It should be able to:
- request that the door start to open/close and
- request the light change between off/on.
- The door can be open, closed, in the process of opening, and in the process of closing. The object needs to model the door’s behavior. For the purposes of demoing the behavior of the door:
- If the user presses the button when the door is closed, the garage door will start opening and then be open 1s later.
- If the user presses the button when the door is open, the door will start closing and then be closed 1s later.
- Real garage doors can be stopped before being fully opened/closed and may encounter errors that may require additional states. You can ignore all those special cases for now.
- The garage door has a variety of elements of “state”. Things it will keep track of include:
- The current state of the door (closing, closed, opening, open).
- If the light is on or off.
- The current brightness setting for the light (i.e., how bright it will be when it is on).
- The current “auto-off time” for the light.
- Whether the auto-close feature is enabled/disabled.
- The “auto-close time”. (The time from when the door is open until it will start to automatically close if auto-close is enabled).
- The light should automatically turn on whenever the door is in the process of opening or closing.
- The light should also turn on if the user manually turns the light on.
- The advanced features (auto close and turning the light off after a designated time) should work correctly
- Whenever the light is turned on (in any way), it should turn off automatically after the previously mentioned “auto-off time” has passed. (Ex: if auto-off was 60s, the light should turn off 60s after it came on every time it comes on)
- You can assume that “times” are abbreviated to make demoing easier:
- Auto-close time should be able to be set from 5s to 60s.
- Light auto-off time should be able to be set from 1s to 60s.
- For now, you can ignore conflicts that could arise from multiple features interacting. For example, if the user sets the auto-close time to 20s, then opens and re-closes the door (which only takes ~4s), you can allow the auto-close to attempt to close the door again in ~16s later.
- The user should be able to “set” values of state as appropriate. In particular there should be “setters” for all the settings, but setters probably aren’t appropriate for moving the door itself. (The user requests that it open and the door goes through a process of opening that takes time. “Setters” are for directly setting values and it wouldn’t make sense for a user to “set” a closed door to be instantly open).
- The Object should follow the “observer pattern” for state updates (i.e., support having at least one “listener” function).
- To simulate the delays that may occur due to network delays, you should delay all responses from the
garage
object to an Observer by 1s.
- To ensure that you have proper separation of responsibilities:
- the
garage
object should not directly interact with elements of the DOM or UI in any way.
- the UI should not directly interact with any properties of the
garage
. All interaction should take place through methods.
- The
garage
object should be in a separate file from the logic that controls the UI (in GarageModel.js
). It should be possible to test it thoroughly independently of the UI.
- The UI logic should be handled in
GarageApp.js
.
- UI controls should not display until the values have been obtained from the
garage
object.
- The UI should always be in-sync with the
garage
object, even if outside forces cause changes in the object. For example direct interaction with the garage
object from the Console may cause the object to change and such changes should be reflected on the UI.
- As with previous work, you should not use any libraries or frameworks. For example, you can’t use jQuery or React. All submitted code should be yours and you should cite any sources that influenced your work. In the UI design, you can use artwork that is not your own, however: 1) DBI strongly prefers things with a license that allows for free commercial development and 2) you must both cite the source of any artwork as a comment in-line where the artwork occurs and indicate details about its licenses or copyrights.
Suggested Work Flow
You are allowed to work in any order you like, but here’s an approach that may be effective:
- Review and update your work from the previous assignment.
- Merge the HTML for screens of interest into a single HTML file.
- Nest each separate screen in its own
div
.
- Be sure that all HTML elements that your code will need to interact with have a valid
id
.
- Verify that your HTML is properly structured (test in validator and browser)
- Write the code that will handle transitions between the screens
- Create the
garage
object adding one feature at a time:
- Add all state properties with appropriate types and default values
- Add any setter functions needed for state properties
- Test your work
- Add a property and setter for an “observer” function
- Create a helper function that will call the observer (i.e., that will send the observer that current state of the
garage
object)
- Create a simple function to print the “state” and configure it to be the observer.
- Update the setter for the “observer” function. When an observer is provided, automatically call the observer to provide the current state of the object. (That is, when something “subscribes” for the first time, fill it in on the current state as soon as it subscribes. This would be a good place to call the helper function from the last step)
- Test your work
- Update the helper function so that it will always delay calling the observer until 1s after the helper function was called.
- Test your work
- Ensure that all changes to state will call the observer function
- Test your work
- Update your UI to interact via the
garage
object
- Ensure that controls call methods as needed
- Test your work
- Have it subscribe an observer function
- Test your work
- Have the observer update any displayed variables and state as needed
- Test your work
- Hide elements on page load / startup
- Ensure that the observer will reveal any screens the first time state information is available
- Test your work
Hints
- See Studio: JavaScript 2.
- Consider using
setTimeout
for all the time-based interactions.
- If you haven’t worked with
setTimeout
before, you should try some test cases of setTimeout
in the JavaScript console.
-
You can use an object literal’s name to access properties and methods of the objects. For example:
var anObject = {
aProperty: "This is some property",
...
aMethod: function() {
console.log(this.aProperty) // Access property via this
console.log(anObject.aProperty) // Access property via object literal's name
}
}
The second approach only works in special cases like this where this is a single object being used (singleton), but it avoids some of the limitations of this
that can occur when using anonymous functions in JavaScript.
- Auto-close and the light automatically turning off can cause some confusion when testing. You may want to have auto-close default to being disabled and the auto-off time for the light to be a high value.
- In addition to the Tentative Rubric below, the
README.md
concludes with a checklist that can help you ensure you have met the majority of the assignment requirements.
Artifacts that are Due
The only materials due will be the HTML, CSS, JavaScript, and supporting materials (like images, etc.).
Tentative Rubric
Navigation (8 points)
- ensure navigation between all screens functions properly
State Changes (37 points)
- when the garage door state is toggled by the user, if garage door is closed, it should start opening and be open 1s later
- if the garage is open, it should start closing and be closed 1s later
- garage light should be able to be toggled off if it is on and vice versa
- garage light should come on whenever the door begins opening or closing
UI Functionality (18 points)
- range for AutoClose (door) should be 5s to 60s
- range for AutoOff (light) should be 1s to 60s
- Garage Light AutoOff and Garage Door AutoClose should work correctly
Garage Object (15 points)
- the
garage
object should not be directly interacted with, but instead should only be accessed through methods
- controls should NOT be available/accessible on the screen until the initial state of the light and door have been fetched
Best Practices (22 points)
- all HTML should be kept in one file
- no use of Delay (use setTimeout instead) NON-BLOCKING
- proper organization of HTML and JavaScript code
- comment your code!
- completion of
README.md
Demos
Testing Garage Object in Console
The video below show the basic steps needed to test your garage
object using a browser’s JavaScript Console. Note that part of the video is intentionally blurred to hide implmentation details. There are a variety of acceptable implementations and no need to exactly mimic the one shown in the video.
A Working App
This demo shows one of the simplest possible UI implementations and the basic behavior of the app. (You are encouraged to have a better UI, but the behavior should have the same basic characteristics)
Submission & Checkout
As outlined in the course policies, you must commit work to GitHub and demo it by class time on the due date for full credit.
You need to be prepared to demo and explain your work during your checkout as well as answer the questions in the README.md
. (The final checklist may help verify that you are ready to demo)
Checkout and review will be done on a first-come-first-serve basis. If you aren’t done before class you risk not being able to check out during class time. Work demoed after class time is considered late and will either not count as a grade or will consume late day coupons.