diff --git a/4-typing-game/typing-game/README.md b/4-typing-game/typing-game/README.md index 12e96c5d..3985d622 100644 --- a/4-typing-game/typing-game/README.md +++ b/4-typing-game/typing-game/README.md @@ -1,47 +1,94 @@ # Creating a game using events +Event-driven programming is the foundation of interactive web applications, and there's no better way to understand it than by building something fun and engaging. In this lesson, you'll create a typing speed game that responds to user interactions in real-time, teaching you how to handle events, manage application state, and create dynamic user experiences. + +By building this typing game, you'll discover how web browsers communicate with your JavaScript code through events, and how to write code that responds intelligently to user actions. You'll also learn essential programming patterns that form the backbone of modern web development, from simple button clicks to complex user interfaces. + +By the end of this lesson, you'll have created a fully functional typing game and gained the skills to build any interactive web application. Let's dive into the exciting world of event-driven programming and bring your web pages to life! + ## Pre-Lecture Quiz [Pre-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/21) ## Event driven programming +User interaction is what makes web applications come alive, transforming static pages into dynamic, responsive experiences. Understanding how to capture and respond to user actions is fundamental to creating engaging web applications that feel intuitive and professional. + +The challenge we face as developers is that we can't predict when users will click buttons, type in text fields, or interact with our interface. This uncertainty requires a different programming approach than the sequential, step-by-step code you might be familiar with. + When creating a browser based application, we provide a graphical user interface (GUI) for the user to use when interacting with what we've built. The most common way to interact with the browser is through clicking and typing in various elements. The challenge we face as a developer is we don't know when they're going to perform these operations! [Event-driven programming](https://en.wikipedia.org/wiki/Event-driven_programming) is the name for the type of programming we need to do to create our GUI. If we break this phrase down a little bit, we see the core word here is **event**. [Event](https://www.merriam-webster.com/dictionary/event), according to Merriam-Webster, is defined as "something which happens". This describes our situation perfectly. We know something is going to happen for which we want to execute some code in response, but we don't know when it will take place. The way we mark a section of code we want to execute is by creating a function. When we think about [procedural programming](https://en.wikipedia.org/wiki/Procedural_programming), functions are called in a specific order. This same thing is going to be true with event driven programming. The difference is **how** the functions will be called. -To handle events (button clicking, typing, etc.), we register **event listeners**. An event listener is a function which listens for an event to occur and executes in response. Event listeners can update the UI, make calls to the server, or whatever else needs to be done in response to the user's action. We add an event listener by using [addEventListener](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener), and providing a function to execute. +To handle events (button clicking, typing, etc.), we register **event listeners**. An event listener is a function which listens for an event to occur and executes in response. Event listeners can update the UI, make calls to the server, or whatever else needs to be done in response to the user's action. We add an event listener by using `addEventListener()`, and providing a function to execute. + +**Here's how event listeners work:** +- **Listens** for specific user actions like clicks, keystrokes, or mouse movements +- **Executes** your custom code when the specified event occurs +- **Responds** immediately to user interactions, creating a seamless experience +- **Handles** multiple events on the same element using different listeners -> **NOTE:** It's worth highlighting there are numerous ways to create event listeners. You can use anonymous functions, or create named ones. You can use various shortcuts, like setting the `click` property, or using `addEventListener`. In our exercise we are going to focus on `addEventListener` and anonymous functions, as it's probably the most common technique web developers use. It's also the most flexible, as `addEventListener` works for all events, and the event name can be provided as a parameter. +> **NOTE:** It's worth highlighting there are numerous ways to create event listeners. You can use anonymous functions, or create named ones. You can use various shortcuts, like setting the `click` property, or using `addEventListener()`. In our exercise we are going to focus on `addEventListener()` and anonymous functions, as it's probably the most common technique web developers use. It's also the most flexible, as `addEventListener()` works for all events, and the event name can be provided as a parameter. ### Common events +While web browsers offer dozens of different events you can listen for, most interactive applications rely on just a handful of essential events. Understanding these core events will give you the foundation to build sophisticated user interactions. + There are [dozens of events](https://developer.mozilla.org/docs/Web/Events) available for you to listen to when creating an application. Basically anything a user does on a page raises an event, which gives you a lot of power to ensure they get the experience you desire. Fortunately, you'll normally only need a small handful of events. Here's a few common ones (including the two we'll use when creating our game): -- [click](https://developer.mozilla.org/docs/Web/API/Element/click_event): The user clicked on something, typically a button or hyperlink -- [contextmenu](https://developer.mozilla.org/docs/Web/API/Element/contextmenu_event): The user clicked the right mouse button -- [select](https://developer.mozilla.org/docs/Web/API/Element/select_event): The user highlighted some text -- [input](https://developer.mozilla.org/docs/Web/API/Element/input_event): The user input some text +| Event | Description | Common Use Cases | +|-------|-------------|------------------| +| `click` | The user clicked on something | Buttons, links, interactive elements | +| `contextmenu` | The user clicked the right mouse button | Custom right-click menus | +| `select` | The user highlighted some text | Text editing, copy operations | +| `input` | The user input some text | Form validation, real-time search | + +**Understanding these event types:** +- **Triggers** when users interact with specific elements on your page +- **Provides** detailed information about the user's action through event objects +- **Enables** you to create responsive, interactive web applications +- **Works** consistently across different browsers and devices ## Creating the game +Now that you understand how events work, let's put that knowledge into practice by building something engaging and useful. We'll create a typing speed game that demonstrates event handling while helping you develop a crucial developer skill. + We are going to create a game to explore how events work in JavaScript. Our game is going to test a player's typing skill, which is one of the most underrated skills all developers should have. We should all be practicing our typing! The general flow of the game will look like this: -- Player clicks on start button and is presented with a quote to type -- Player types the quote as quickly as they can in a textbox - - As each word is completed, the next one is highlighted - - If the player has a typo, the textbox is updated to red - - When the player completes the quote, a success message is displayed with the elapsed time +```mermaid +flowchart TD + A[Player clicks Start] --> B[Random quote displays] + B --> C[Player types in textbox] + C --> D{Word complete?} + D -->|Yes| E[Highlight next word] + D -->|No| F{Correct so far?} + F -->|Yes| G[Keep normal styling] + F -->|No| H[Show error styling] + E --> I{Quote complete?} + I -->|No| C + I -->|Yes| J[Show success message with time] + G --> C + H --> C +``` + +**Here's how our game will work:** +- **Starts** when the player clicks the start button and displays a random quote +- **Tracks** the player's typing progress word by word in real-time +- **Highlights** the current word to guide the player's focus +- **Provides** immediate visual feedback for typing errors +- **Calculates** and displays the total time when the quote is completed Let's build our game, and learn about events! ### File structure -We're going to need three total files: **index.html**, **script.js** and **style.css**. Let's start by setting those up to make life a little easier for us. +Organizing your project files properly from the start makes development smoother and helps you maintain clean, professional code. Our typing game will follow the standard web development structure that separates content, styling, and behavior. + +We're going to need three total files: `index.html`, `script.js` and `style.css`. Let's start by setting those up to make life a little easier for us. -- Create a new folder for your work by opening a console or terminal window and issuing the following command: +**Create a new folder for your work by opening a console or terminal window and issuing the following command:** ```bash # Linux or macOS @@ -51,29 +98,49 @@ mkdir typing-game && cd typing-game md typing-game && cd typing-game ``` -- Open Visual Studio Code +**Here's what these commands do:** +- **Creates** a new directory called `typing-game` for your project files +- **Navigates** into the newly created directory automatically +- **Sets up** a clean workspace for your game development + +**Open Visual Studio Code:** ```bash code . ``` -- Add three files to the folder in Visual Studio Code with the following names: - - index.html - - script.js - - style.css +**This command:** +- **Launches** Visual Studio Code in the current directory +- **Opens** your project folder in the editor +- **Provides** access to all the development tools you'll need + +**Add three files to the folder in Visual Studio Code with the following names:** +- `index.html` - Contains the structure and content of your game +- `script.js` - Handles all the game logic and event listeners +- `style.css` - Defines the visual appearance and styling ## Create the user interface +Building a user interface is like creating a blueprint for how users will interact with your application. We need to think about what elements users need to see and interact with, then structure them in a logical, accessible way. + If we explore the requirements, we know we're going to need a handful of elements on our HTML page. This is sort of like a recipe, where we need some ingredients: -- Somewhere to display the quote for the user to type -- Somewhere to display any messages, like a success message -- A textbox for typing -- A start button +| UI Element | Purpose | HTML Element | +|------------|---------|-------------| +| Quote Display | Shows the text to type | `

` with `id="quote"` | +| Message Area | Displays status and success messages | `

` with `id="message"` | +| Text Input | Where players type the quote | `` with `id="typed-value"` | +| Start Button | Begins the game | ` - +

+

New? Add your Information

+
+
+ + +
+
+ + +
+ + ``` -This is the form where your saved information will be input and saved to local storage. -Next, create the results area; under the final form tag, add some divs: +**Here's what this form accomplishes:** +- **Creates** a semantic form structure with proper labels and input associations +- **Enables** browser autocomplete functionality for improved user experience +- **Requires** both fields to be filled before submission using the `required` attribute +- **Organizes** inputs with descriptive class names for easy styling and JavaScript targeting +- **Provides** clear instructions for users who are setting up the extension for the first time + +### Building the Results Display -```HTML +Next, create the results area that will show the carbon footprint data. Add this HTML below the form: + +```html
-
loading...
-
-
-
-

Region:

-

Carbon Usage:

-

Fossil Fuel Percentage:

-
- +
loading...
+
+
+
+

Region:

+

Carbon Usage:

+

Fossil Fuel Percentage:

+
+
``` -At this point, you can try a build. Make sure to install the package dependencies of this extension: -``` +**Breaking down what this structure provides:** +- **`loading`**: **Displays** a loading message while API data is being fetched +- **`errors`**: **Shows** error messages if API calls fail or data is invalid +- **`data`**: **Holds** raw data for debugging purposes during development +- **`result-container`**: **Presents** formatted carbon footprint information to users +- **`clear-btn`**: **Allows** users to change their region and reconfigure the extension + +### Setting Up the Build Process + +Now let's install the project dependencies and test the build process: + +```bash npm install ``` -This command will use npm, the Node Package Manager, to install webpack for your extension's build process. Webpack is a bundler that handles compiling code. You can see the output of this process by looking in `/dist/main.js` - you see the code has been bundled. +**What this installation process accomplishes:** +- **Downloads** Webpack and other development dependencies specified in `package.json` +- **Configures** the build toolchain for compiling modern JavaScript +- **Prepares** the development environment for extension building and testing +- **Enables** code bundling, optimization, and cross-browser compatibility features + +> 💡 **Build Process Insight**: Webpack bundles your source code from `/src/index.js` into `/dist/main.js`. This process optimizes your code for production and ensures browser compatibility. + +### Testing Your Progress + +At this point, you can test your extension: + +1. **Run** the build command to compile your code +2. **Load** the extension into your browser using the developer mode +3. **Verify** that the form displays correctly and looks professional +4. **Check** that all form elements are properly aligned and functional -For now, the extension should build and, if you deploy it into Edge as an extension, you'll see a form neatly displayed. +**You've successfully:** +- **Built** the foundational HTML structure for your extension +- **Created** both configuration and results interfaces +- **Set up** the development workflow with modern build tools +- **Prepared** your extension for the next phase of JavaScript functionality -Congratulations, you've taken the first steps towards building a browser extension. In subsequent lessons, you'll make it more functional and useful. +Congratulations! You've completed the first major milestone in browser extension development. In the upcoming lessons, you'll add JavaScript functionality to make your extension fully interactive and useful. ## GitHub Copilot Agent Challenge 🚀 diff --git a/5-browser-extension/1-about-browsers/assignment.md b/5-browser-extension/1-about-browsers/assignment.md index 62d1edff..c862d15c 100644 --- a/5-browser-extension/1-about-browsers/assignment.md +++ b/5-browser-extension/1-about-browsers/assignment.md @@ -1,11 +1,130 @@ -# Restyle your Extension +# Assignment: Restyle Your Browser Extension + +## Overview + +Now that you've built the HTML structure for your carbon footprint browser extension, it's time to make it visually appealing and user-friendly. Great design enhances the user experience and makes your extension more professional and engaging. + +Your extension comes with basic CSS styling, but this assignment challenges you to create a unique visual identity that reflects your personal style while maintaining excellent usability. ## Instructions -The codebase for this extension comes complete with styles, but you don't have to use them; make your extension your own by restyling it by editing its css file. +### Part 1: Analyze the Current Design + +Before making changes, examine the existing CSS structure: + +1. **Locate** the CSS files in your extension project +2. **Review** the current styling approach and color scheme +3. **Identify** areas for improvement in layout, typography, and visual hierarchy +4. **Consider** how the design supports user goals (easy form completion and clear data display) + +### Part 2: Design Your Custom Styling + +Create a cohesive visual design that includes: + +**Color Scheme:** +- Choose a primary color palette that reflects environmental themes +- Ensure sufficient contrast for accessibility (use tools like WebAIM's contrast checker) +- Consider how colors will look across different browser themes + +**Typography:** +- Select readable fonts that work well at small extension sizes +- Establish a clear hierarchy with appropriate font sizes and weights +- Ensure text remains legible in both light and dark browser themes + +**Layout and Spacing:** +- Improve the visual organization of form elements and data display +- Add appropriate padding and margins for better readability +- Consider responsive design principles for different screen sizes + +### Part 3: Implement Your Design + +Modify the CSS files to implement your design: + +```css +/* Example starting points for customization */ + +.form-data { + /* Style the configuration form */ + background: /* your choice */; + padding: /* your spacing */; + border-radius: /* your preference */; +} + +.result-container { + /* Style the data display area */ + background: /* complementary color */; + border: /* your border style */; + margin: /* your spacing */; +} + +/* Add your custom styles here */ +``` + +**Key areas to style:** +- **Form elements**: Input fields, labels, and submit button +- **Results display**: Data container, text styling, and loading states +- **Interactive elements**: Hover effects, button states, and transitions +- **Overall layout**: Container spacing, background colors, and visual hierarchy + +### Part 4: Test and Refine + +1. **Build** your extension with `npm run build` +2. **Load** the updated extension into your browser +3. **Test** all visual states (form entry, loading, results display, errors) +4. **Verify** accessibility with browser developer tools +5. **Refine** your styles based on actual usage + +## Creative Challenges + +### Basic Level +- Update colors and fonts to create a cohesive theme +- Improve spacing and alignment throughout the interface +- Add subtle hover effects to interactive elements + +### Intermediate Level +- Design custom icons or graphics for your extension +- Implement smooth transitions between different states +- Create a unique loading animation for API calls + +### Advanced Level +- Design multiple theme options (light/dark/high-contrast) +- Implement responsive design for different browser window sizes +- Add micro-interactions that enhance the user experience + +## Submission Guidelines + +Your completed assignment should include: + +- **Modified CSS files** with your custom styling +- **Screenshots** showing your extension in different states (form, loading, results) +- **Brief description** (2-3 sentences) explaining your design choices and how they improve the user experience + +## Assessment Rubric + +| Criteria | Exemplary (4) | Proficient (3) | Developing (2) | Beginning (1) | +|----------|---------------|----------------|----------------|----------------| +| **Visual Design** | Creative, cohesive design that enhances usability and reflects strong design principles | Good design choices with consistent styling and clear visual hierarchy | Basic design improvements with some consistency issues | Minimal styling changes or inconsistent design | +| **Functionality** | All styles work perfectly across different states and browser environments | Styles work well with minor issues in edge cases | Most styles functional with some display problems | Significant styling issues that impact usability | +| **Code Quality** | Clean, well-organized CSS with meaningful class names and efficient selectors | Good CSS structure with appropriate use of selectors and properties | Acceptable CSS with some organization issues | Poor CSS structure or overly complex styling | +| **Accessibility** | Excellent color contrast, readable fonts, and consideration for users with disabilities | Good accessibility practices with minor areas for improvement | Basic accessibility considerations with some issues | Limited attention to accessibility requirements | + +## Tips for Success + +> 💡 **Design Tip**: Start with subtle changes and build up to more dramatic styling. Small improvements in typography and spacing often have big impacts on perceived quality. + +**Best practices to follow:** +- **Test** your extension in both light and dark browser themes +- **Use** relative units (em, rem) for better scalability +- **Maintain** consistent spacing using CSS custom properties +- **Consider** how your design will look to users with different visual needs +- **Validate** your CSS to ensure it follows proper syntax + +> ⚠️ **Common Mistake**: Don't sacrifice usability for visual appeal. Your extension should be both beautiful and functional. -## Rubric +**Remember to:** +- **Keep** important information easily readable +- **Ensure** buttons and interactive elements are easy to click +- **Maintain** clear visual feedback for user actions +- **Test** your design with real data, not just placeholder text -| Criteria | Exemplary | Adequate | Needs Improvement | -| -------- | -------------------------------------------- | --------------------- | ----------------- | -| | Code is submitted with functional new styles | Styling is incomplete | Styles are buggy | \ No newline at end of file +Good luck creating a browser extension that's both functional and visually stunning! \ No newline at end of file diff --git a/5-browser-extension/2-forms-browsers-local-storage/README.md b/5-browser-extension/2-forms-browsers-local-storage/README.md index 9e94a089..12583868 100644 --- a/5-browser-extension/2-forms-browsers-local-storage/README.md +++ b/5-browser-extension/2-forms-browsers-local-storage/README.md @@ -4,19 +4,23 @@ [Pre-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/25) -### Introduction +## Introduction -In this lesson, you'll call an API by submitting your browser extension's form and displaying the results in your browser extension. In addition, you'll learn about how you can store data in your browser's local storage for future reference and use. +Now that you've built the foundation of your browser extension with HTML and CSS, it's time to bring it to life with dynamic functionality. In this lesson, you'll transform your static form into an interactive tool that communicates with external APIs and intelligently stores data for future use. + +API integration is a cornerstone skill in modern web development. Whether you're fetching weather data, user profiles, or carbon emission statistics like we'll do today, understanding how to work with APIs opens up endless possibilities for your applications. You'll also discover how browser storage works behind the scenes, allowing your extension to remember user preferences and data even after closing and reopening. + +By the end of this lesson, you'll have a fully functional browser extension that fetches real environmental data, stores user settings, and provides a polished user experience. Let's dive into the exciting world of API integration and data persistence! ✅ Follow the numbered segments in the appropriate files to know where to place your code -### Set up the elements to manipulate in the extension: +## Set up the elements to manipulate in the extension -By this time you have built the HTML for the form and results `
` for your browser extension. From now on, you'll need to work in the `/src/index.js` file and build your extension bit by bit. Refer to the [previous lesson](../1-about-browsers/README.md) on getting your project set up and on the build process. +Before we can make our extension interactive, we need to establish connections between our JavaScript code and the HTML elements we created earlier. Think of this step as creating a communication bridge between your code and the user interface. -Working in your `index.js` file, start by creating some `const` variables to hold the values associated with various fields: +Working in your `index.js` file, you'll start by creating `const` variables that reference each important element on your form. This approach keeps your code organized and makes it easy to update the interface later. -```JavaScript +```javascript // form fields const form = document.querySelector('.form-data'); const region = document.querySelector('.region-name'); @@ -32,120 +36,171 @@ const myregion = document.querySelector('.my-region'); const clearBtn = document.querySelector('.clear-btn'); ``` -All of these fields are referenced by their css class, as you set it up in the HTML in the previous lesson. +**Here's what this code does:** +- **Captures** form elements using `document.querySelector()` with CSS class selectors +- **Creates** references to input fields for the region name and API key +- **Establishes** connections to result display elements for carbon usage data +- **Sets up** access to UI elements like loading indicators and error messages +- **Stores** each element reference in a `const` variable for easy reuse throughout your code -### Add listeners +## Add event listeners -Next, add event listeners to the form and the clear button that resets the form, so that if a user submits the form or clicks that reset button, something will happen, and add the call to initialize the app at the bottom of the file: +Event listeners are like watchful assistants that wait for specific user actions and then execute your code in response. You'll add listeners for form submission and button clicks to make your extension interactive. -```JavaScript +```javascript form.addEventListener('submit', (e) => handleSubmit(e)); clearBtn.addEventListener('click', (e) => reset(e)); init(); ``` -✅ Notice the shorthand used to listen for a submit or click event, and how the event it is passed to the handleSubmit or reset functions. Can you write the equivalent of this shorthand in a longer format? Which do you prefer? +**Understanding these concepts:** +- **Attaches** a submit listener to the form that triggers when users press Enter or click submit +- **Connects** a click listener to the clear button for resetting the form +- **Passes** the event object `(e)` to handler functions for additional control +- **Calls** the `init()` function immediately to set up the initial state of your extension + +✅ Notice the shorthand arrow function syntax used here. This modern JavaScript approach is cleaner than traditional function expressions, but both work equally well! -### Build out the init() function and the reset() function: +## Build the initialization and reset functions -Now you are going to build the function that initializes the extension, which is called init(): +The `init()` function is like the startup routine for your extension - it checks what data is already stored and decides what to show the user. The `reset()` function provides a clean slate when users want to start over. -```JavaScript +```javascript function init() { - //if anything is in localStorage, pick it up + // Check if user has previously saved API credentials const storedApiKey = localStorage.getItem('apiKey'); const storedRegion = localStorage.getItem('regionName'); - //set icon to be generic green - //todo + // Set extension icon to generic green (placeholder for future lesson) + // TODO: Implement icon update in next lesson if (storedApiKey === null || storedRegion === null) { - //if we don't have the keys, show the form + // First-time user: show the setup form form.style.display = 'block'; results.style.display = 'none'; loading.style.display = 'none'; clearBtn.style.display = 'none'; errors.textContent = ''; } else { - //if we have saved keys/regions in localStorage, show results when they load - displayCarbonUsage(storedApiKey, storedRegion); + // Returning user: load their saved data automatically + displayCarbonUsage(storedApiKey, storedRegion); results.style.display = 'none'; form.style.display = 'none'; clearBtn.style.display = 'block'; } -}; +} function reset(e) { e.preventDefault(); - //clear local storage for region only + // Clear stored region to allow user to choose a new location localStorage.removeItem('regionName'); + // Restart the initialization process init(); } - ``` -In this function, there is some interesting logic. Reading through it, can you see what happens? -- two `const` are set up to check if the user has stored an APIKey and region code in local storage. -- if either of those is null, show the form by changing its style to display as 'block' -- hide the results, loading, and clearBtn and set any error text to an empty string -- if there exists a key and region, start a routine to: - - call the API to get carbon usage data - - hide the results area - - hide the form - - show the reset button +**Breaking down what happens here:** +- **Retrieves** stored API key and region from browser's local storage +- **Checks** if this is a first-time user (no stored credentials) or returning user +- **Shows** the setup form for new users and hides other interface elements +- **Loads** saved data automatically for returning users and displays the reset option +- **Manages** the user interface state based on available data -Before moving on, it's useful to learn about a very important concept available in browsers: [LocalStorage](https://developer.mozilla.org/docs/Web/API/Window/localStorage). LocalStorage is a useful way to store strings in the browser as a `key-value` pair. This type of web storage can be manipulated by JavaScript to manage data in the browser. LocalStorage does not expire, while SessionStorage, another kind of web storage, is cleared when the browser is closed. The various types of storage have pros and cons to their usage. +**Key concepts about Local Storage:** +- **Persists** data between browser sessions (unlike session storage) +- **Stores** data as key-value pairs using `getItem()` and `setItem()` +- **Returns** `null` when no data exists for a given key +- **Provides** a simple way to remember user preferences and settings -> Note - your browser extension has its own local storage; the main browser window is a different instance and behaves separately. +> 💡 **Understanding Browser Storage**: [LocalStorage](https://developer.mozilla.org/docs/Web/API/Window/localStorage) is one of several storage options available in web browsers. Think of it as a mini-database that lives in your user's browser. +> +> **What you need to know:** +> - **Stores** data as key-value pairs that persist between browser sessions +> - **Survives** browser restarts (unlike SessionStorage which expires when tabs close) +> - **Provides** up to 5-10MB of storage space per domain +> - **Works** synchronously, making it easy to use in your JavaScript code -You set your APIKey to have a string value, for example, and you can see that it is set on Edge by "inspecting" a web page (you can right-click a browser to inspect) and going to the Applications tab to see the storage. +> **Important Note**: Your browser extension has its own isolated local storage that's separate from regular web pages. This provides security and prevents conflicts with other websites. -![Local storage pane](images/localstorage.png) +You can view your stored data by opening browser Developer Tools (F12), navigating to the **Application** tab, and expanding the **Local Storage** section. -✅ Think about situations where you would NOT want to store some data in LocalStorage. In general, placing API Keys in LocalStorage is a bad idea! Can you see why? In our case, since our app is purely for learning and will not be deployed to an app store, we will use this method. +![Local storage pane](images/localstorage.png) -Notice that you use the Web API to manipulate LocalStorage, either by using `getItem()`, `setItem()`, or `removeItem()`. It's widely supported across browsers. +> ⚠️ **Security Consideration**: In production applications, storing API keys in LocalStorage poses security risks since JavaScript can access this data. For learning purposes, this approach works fine, but real applications should use secure server-side storage for sensitive credentials. -Before building the `displayCarbonUsage()` function that is called in `init()`, let's build the functionality to handle the initial form submission. +## Handle form submission -### Handle the form submission +When users submit your form, you need to intercept that action and process their input instead of letting the browser handle it normally. This is where form submission handling becomes crucial for single-page applications and extensions. -Create a function called `handleSubmit` that accepts an event argument `(e)`. Stop the event from propagating (in this case, we want to stop the browser from refreshing) and call a new function, `setUpUser`, passing in the arguments `apiKey.value` and `region.value`. In this way, you use the two values that are brought in via the initial form when the appropriate fields are populated. +Create a function that captures the form submission event and extracts the user's input: -```JavaScript +```javascript function handleSubmit(e) { e.preventDefault(); setUpUser(apiKey.value, region.value); } ``` -✅ Refresh your memory - the HTML you set up in the last lesson has two input fields whose `values` are captured via the `const` you set up at the top of the file, and they are both `required` so the browser stops users from inputting null values. -### Set up the user +**In the above, we've:** +- **Prevents** the default form submission behavior that would refresh the page +- **Extracts** user input values from the API key and region fields +- **Passes** the form data to the `setUpUser()` function for processing +- **Maintains** single-page application behavior by avoiding page reloads + +✅ Remember that your HTML form fields include the `required` attribute, so the browser automatically validates that users provide both the API key and region before this function runs. + +## Set up user preferences -Moving on to the `setUpUser` function, here is where you set local storage values for apiKey and regionName. Add a new function: +The `setUpUser` function is responsible for saving the user's credentials and initiating the first API call. This creates a smooth transition from setup to displaying results. -```JavaScript +```javascript function setUpUser(apiKey, regionName) { + // Save user credentials for future sessions localStorage.setItem('apiKey', apiKey); localStorage.setItem('regionName', regionName); + + // Update UI to show loading state loading.style.display = 'block'; errors.textContent = ''; clearBtn.style.display = 'block'; - //make initial call + + // Fetch carbon usage data with user's credentials displayCarbonUsage(apiKey, regionName); } ``` -This function sets a loading message to show while the API is called. At this point, you have arrived at creating the most important function of this browser extension! -### Display Carbon Usage +**Step by step, here's what's happening:** +- **Saves** the API key and region name to local storage for future use +- **Shows** a loading indicator to inform users that data is being fetched +- **Clears** any previous error messages from the display +- **Reveals** the clear button for users to reset their settings later +- **Initiates** the API call to fetch real carbon usage data + +This function creates a seamless user experience by managing both data persistence and user interface updates in one coordinated action. + +## Display carbon usage data -Finally, it's time to query the API! +Now comes the exciting part - fetching real environmental data from an external API! This is where your extension transforms from a simple form into a powerful tool that provides valuable information to users. -Before going further, we should discuss APIs. APIs, or [Application Programming Interfaces](https://www.webopedia.com/TERM/A/API.html), is a critical element of a web developer's toolbox. They provide standard ways for programs to interact and interface with each other. For example, if you are building a web site that needs to query a database, someone might have created an API for you to use. While there are many types of APIs, one of the most popular is a [REST API](https://www.smashingmagazine.com/2018/01/understanding-using-rest-api/). +**Understanding APIs in web development:** -✅ The term 'REST' stands for 'Representational State Transfer' and features using variously-configured URLs to fetch data. Do a little research on the various types of APIs available to developers. What format appeals to you? +[Application Programming Interfaces (APIs)](https://www.webopedia.com/TERM/A/API.html) are the bridges that connect different software systems. Think of them as specialized messengers that allow your application to request specific data from external services. When you check the weather on your phone, submit a payment online, or share content on social media, APIs are working behind the scenes. -There are important things to note about this function. First, notice the [`async` keyword](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function). Writing your functions so that they run asynchronously means that they wait for an action, such as data being returned, to be completed before continuing. +**Key concepts about REST APIs:** +- **REST** stands for 'Representational State Transfer' +- **Uses** standard HTTP methods (GET, POST, PUT, DELETE) to interact with data +- **Returns** data in predictable formats, typically JSON +- **Provides** consistent, URL-based endpoints for different types of requests + +✅ The [CO2 Signal API](https://www.co2signal.com/) we'll use provides real-time carbon intensity data from electrical grids worldwide. This helps users understand the environmental impact of their electricity usage! + +> 💡 **Understanding Asynchronous JavaScript**: The [`async` keyword](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function) is essential for modern web development. When you make API calls, you're requesting data from external servers, which takes time. +> +> **Here's why async/await matters:** +> - **Prevents** your application from freezing while waiting for API responses +> - **Allows** other code to continue running during network requests +> - **Provides** cleaner, more readable code compared to callback-based approaches +> - **Handles** errors gracefully when network requests fail Here's a quick video about `async`: @@ -153,56 +208,82 @@ Here's a quick video about `async`: > 🎥 Click the image above for a video about async/await. -Create a new function to query the C02Signal API: - -```JavaScript -import axios from '../node_modules/axios'; +Create the function to fetch and display carbon usage data: +```javascript +// Modern fetch API approach (no external dependencies needed) async function displayCarbonUsage(apiKey, region) { try { - await axios - .get('https://api.co2signal.com/v1/latest', { - params: { - countryCode: region, - }, - headers: { - 'auth-token': apiKey, - }, - }) - .then((response) => { - let CO2 = Math.floor(response.data.data.carbonIntensity); - - //calculateColor(CO2); - - loading.style.display = 'none'; - form.style.display = 'none'; - myregion.textContent = region; - usage.textContent = - Math.round(response.data.data.carbonIntensity) + ' grams (grams C02 emitted per kilowatt hour)'; - fossilfuel.textContent = - response.data.data.fossilFuelPercentage.toFixed(2) + - '% (percentage of fossil fuels used to generate electricity)'; - results.style.display = 'block'; - }); + // Fetch carbon intensity data from CO2 Signal API + const response = await fetch('https://api.co2signal.com/v1/latest', { + method: 'GET', + headers: { + 'auth-token': apiKey, + 'Content-Type': 'application/json' + }, + // Add query parameters for the specific region + ...new URLSearchParams({ countryCode: region }) && { + url: `https://api.co2signal.com/v1/latest?countryCode=${region}` + } + }); + + // Check if the API request was successful + if (!response.ok) { + throw new Error(`API request failed: ${response.status}`); + } + + const data = await response.json(); + const carbonData = data.data; + + // Calculate rounded carbon intensity value + const carbonIntensity = Math.round(carbonData.carbonIntensity); + + // Update the user interface with fetched data + loading.style.display = 'none'; + form.style.display = 'none'; + myregion.textContent = region.toUpperCase(); + usage.textContent = `${carbonIntensity} grams (grams CO₂ emitted per kilowatt hour)`; + fossilfuel.textContent = `${carbonData.fossilFuelPercentage.toFixed(2)}% (percentage of fossil fuels used to generate electricity)`; + results.style.display = 'block'; + + // TODO: calculateColor(carbonIntensity) - implement in next lesson + } catch (error) { - console.log(error); + console.error('Error fetching carbon data:', error); + + // Show user-friendly error message loading.style.display = 'none'; results.style.display = 'none'; - errors.textContent = 'Sorry, we have no data for the region you have requested.'; + errors.textContent = 'Sorry, we couldn\'t fetch data for that region. Please check your API key and region code.'; } } ``` -This is a big function. What's going on here? +**Breaking down what happens here:** +- **Uses** the modern `fetch()` API instead of external libraries like Axios for cleaner, dependency-free code +- **Implements** proper error checking with `response.ok` to catch API failures early +- **Handles** asynchronous operations with `async/await` for more readable code flow +- **Authenticates** with the CO2 Signal API using the `auth-token` header +- **Parses** JSON response data and extracts carbon intensity information +- **Updates** multiple UI elements with formatted environmental data +- **Provides** user-friendly error messages when API calls fail + +**Key modern JavaScript concepts demonstrated:** +- **Template literals** with `${}` syntax for clean string formatting +- **Error handling** with try/catch blocks for robust applications +- **Async/await** pattern for handling network requests gracefully +- **Object destructuring** to extract specific data from API responses +- **Method chaining** for multiple DOM manipulations -- following best practices, you use an `async` keyword to make this function behave asynchronously. The function contains a `try/catch` block as it will return a promise when the API returns data. Because you don't have control over the speed that the API will respond (it may not respond at all!), you need to handle this uncertainty by calling it asynchronously. -- you're querying the co2signal API to get your region's data, using your API Key. To use that key, you have to use a type of authentication in your header parameters. -- once the API responds, you assign various elements of its response data to the parts of your screen you set up to show this data. -- if there's an error, or if there is no result, you show an error message. +✅ This function showcases the complete lifecycle of API integration: authentication, request, data processing, UI updates, and error handling - all essential skills for modern web development! -✅ Using asynchronous programming patterns is another very useful tool in your toolbox. Read [about the various ways](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function) you can configure this type of code. +🎉 **Congratulations!** You've built a fully functional browser extension that: +- **Integrates** with external APIs to fetch real-world data +- **Stores** user preferences in local storage +- **Handles** errors gracefully with user-friendly messages +- **Provides** a smooth, interactive user experience -Congratulations! If you build your extension (`npm run build`) and refresh it in your extensions pane, you have a working extension! The only thing that isn't working is the icon, and you'll fix that in the next lesson. +To test your extension, run `npm run build` and refresh it in your browser's extensions panel. You now have a working carbon footprint tracker! The only feature left to implement is the dynamic icon, which you'll tackle in the next lesson. --- @@ -216,7 +297,21 @@ Use the Agent mode to complete the following challenge: ## 🚀 Challenge -We've discussed several types of API so far in these lessons. Choose a web API and research in depth what it offers. For example, take a look at APIs available within browsers such as the [HTML Drag and Drop API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API). What makes a great API in your opinion? +Expand your understanding of APIs by exploring the wealth of browser-based APIs available for web development. Choose one of these browser APIs and build a small demonstration: + +- [Geolocation API](https://developer.mozilla.org/docs/Web/API/Geolocation_API) - Get user's current location +- [Notification API](https://developer.mozilla.org/docs/Web/API/Notifications_API) - Send desktop notifications +- [HTML Drag and Drop API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API) - Create interactive drag interfaces +- [Web Storage API](https://developer.mozilla.org/docs/Web/API/Web_Storage_API) - Advanced local storage techniques +- [Fetch API](https://developer.mozilla.org/docs/Web/API/Fetch_API) - Modern alternative to XMLHttpRequest + +**Research questions to consider:** +- What real-world problems does this API solve? +- How does the API handle errors and edge cases? +- What security considerations exist when using this API? +- How widely supported is this API across different browsers? + +After your research, identify what characteristics make an API developer-friendly and reliable. ## Post-Lecture Quiz diff --git a/5-browser-extension/2-forms-browsers-local-storage/assignment.md b/5-browser-extension/2-forms-browsers-local-storage/assignment.md index b7f68bc4..ff7aab62 100644 --- a/5-browser-extension/2-forms-browsers-local-storage/assignment.md +++ b/5-browser-extension/2-forms-browsers-local-storage/assignment.md @@ -1,11 +1,93 @@ # Adopt an API +## Overview + +APIs open up endless possibilities for creative web development! In this assignment, you'll choose an external API and build a browser extension that solves a real problem or provides valuable functionality to users. + ## Instructions -APIs can be very fun to play with. Here is a [list of many free ones](https://github.com/public-apis/public-apis). Pick an API, and build a browser extension that solves a problem. It can be as small a problem of not having enough pet pictures (so, try the [dog CEO API](https://dog.ceo/dog-api/)) or something bigger - have fun! +### Step 1: Choose Your API +Select an API from this curated [list of free public APIs](https://github.com/public-apis/public-apis). Consider these categories: + +**Popular options for beginners:** +- **Entertainment**: [Dog CEO API](https://dog.ceo/dog-api/) for random dog pictures +- **Weather**: [OpenWeatherMap](https://openweathermap.org/api) for current weather data +- **Quotes**: [Quotable API](https://quotable.io/) for inspirational quotes +- **News**: [NewsAPI](https://newsapi.org/) for current headlines +- **Fun Facts**: [Numbers API](http://numbersapi.com/) for interesting number facts + +### Step 2: Plan Your Extension +Before coding, answer these planning questions: +- What problem does your extension solve? +- Who is your target user? +- What data will you store in local storage? +- How will you handle API failures or rate limits? + +### Step 3: Build Your Extension +Your extension should include: + +**Required Features:** +- Form inputs for any required API parameters +- API integration with proper error handling +- Local storage for user preferences or API keys +- Clean, responsive user interface +- Loading states and user feedback + +**Code Requirements:** +- Use modern JavaScript (ES6+) features +- Implement async/await for API calls +- Include proper error handling with try/catch blocks +- Add meaningful comments explaining your code +- Follow consistent code formatting + +### Step 4: Test and Polish +- Test your extension with various inputs +- Handle edge cases (no internet, invalid API responses) +- Ensure your extension works after browser restart +- Add user-friendly error messages + +## Bonus Challenges + +Take your extension to the next level: +- Add multiple API endpoints for richer functionality +- Implement data caching to reduce API calls +- Create keyboard shortcuts for common actions +- Add data export/import features +- Implement user customization options + +## Submission Requirements + +1. **Working browser extension** that successfully integrates with your chosen API +2. **README file** explaining: + - Which API you chose and why + - How to install and use your extension + - Any API keys or setup required + - Screenshots of your extension in action +3. **Clean, commented code** following modern JavaScript practices ## Rubric -| Criteria | Exemplary | Adequate | Needs Improvement | -| -------- | -------------------------------------------------------------------------- | ---------------------------------------- | ----------------------- | -| | A complete browser extension is submitted using an API from the above list | A partial browser extension is submitted | The submission has bugs | \ No newline at end of file +| Criteria | Exemplary (90-100%) | Proficient (80-89%) | Developing (70-79%) | Beginning (60-69%) | +|----------|---------------------|---------------------|---------------------|--------------------| +| **API Integration** | Flawless API integration with comprehensive error handling and edge case management | Successful API integration with basic error handling | API works but has limited error handling | API integration has significant issues | +| **Code Quality** | Clean, well-commented modern JavaScript following best practices | Good code structure with adequate comments | Code works but needs better organization | Poor code quality with minimal comments | +| **User Experience** | Polished interface with excellent loading states and user feedback | Good interface with basic user feedback | Basic interface that functions adequately | Poor user experience with confusing interface | +| **Local Storage** | Sophisticated use of local storage with data validation and management | Proper implementation of local storage for key features | Basic local storage implementation | Minimal or incorrect use of local storage | +| **Documentation** | Comprehensive README with setup instructions and screenshots | Good documentation covering most requirements | Basic documentation missing some details | Poor or missing documentation | + +## Getting Started Tips + +1. **Start simple**: Choose an API that doesn't require complex authentication +2. **Read the docs**: Thoroughly understand your chosen API's endpoints and responses +3. **Plan your UI**: Sketch your extension's interface before coding +4. **Test frequently**: Build incrementally and test each feature as you add it +5. **Handle errors**: Always assume API calls might fail and plan accordingly + +## Resources + +- [Browser Extension Documentation](https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions) +- [Fetch API Guide](https://developer.mozilla.org/docs/Web/API/Fetch_API/Using_Fetch) +- [Local Storage Tutorial](https://developer.mozilla.org/docs/Web/API/Window/localStorage) +- [JSON Parsing and Handling](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) + +Have fun building something useful and creative! 🚀 \ No newline at end of file diff --git a/5-browser-extension/3-background-tasks-and-performance/README.md b/5-browser-extension/3-background-tasks-and-performance/README.md index 55a041ae..4ce667c7 100644 --- a/5-browser-extension/3-background-tasks-and-performance/README.md +++ b/5-browser-extension/3-background-tasks-and-performance/README.md @@ -1,5 +1,11 @@ # Browser Extension Project Part 3: Learn about Background Tasks and Performance +Background tasks and performance optimization are the invisible engines that power exceptional web experiences. While users interact with your browser extension's interface, behind the scenes your code is managing data fetching, icon updates, and system resources. Understanding how to optimize these processes transforms a functional extension into a professional, efficient tool that users love. + +In this final lesson of the browser extension module, you'll complete your carbon footprint tracker by implementing dynamic icon updates and learning essential performance monitoring techniques. You'll discover how browsers manage background processes, explore the tools that help you identify performance bottlenecks, and apply optimization strategies that make your extension lightning-fast. + +By the end of this lesson, you'll have a fully functional browser extension and the knowledge to build performant web applications that scale beautifully. Let's dive into the world of browser performance and bring your extension to life! + ## Pre-Lecture Quiz [Pre-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/27) @@ -12,12 +18,22 @@ It remains to manage some background tasks, including refreshing the color of th ## Web Performance Basics +Web performance is the foundation of user experience on the modern web. When your code runs efficiently, users feel the difference in every interaction - from instant page loads to smooth animations and responsive interfaces. Understanding performance isn't just about making things faster; it's about creating web experiences that feel magical rather than frustrating. + +Let's explore the tools and techniques that help you measure and optimize your web applications. We'll start with browser-based profiling tools, then apply these concepts to optimize your browser extension. + > "Website performance is about two things: how fast the page loads, and how fast the code on it runs." -- [Zack Grossbart](https://www.smashingmagazine.com/2012/06/javascript-profiling-chrome-developer-tools/) The topic of how to make your websites blazingly fast on all kinds of devices, for all kinds of users, in all kinds of situations, is unsurprisingly vast. Here are some points to keep in mind as you build either a standard web project or a browser extension. The first thing you need to do to ensure that your site is running efficiently is to gather data about its performance. The first place to do this is in the developer tools of your web browser. In Edge, you can select the "Settings and more" button (the three dots icon on the top right of the browser), then navigate to More Tools > Developer Tools and open the Performance tab. You can also use the keyboard shortcuts `Ctrl` + `Shift` + `I` on Windows or `Option` + `Command` + `I` on Mac to open developer tools. +**Here's how to get started with performance profiling:** +- **Opens** the Developer Tools using the keyboard shortcut or menu option +- **Navigates** to the Performance tab to access profiling tools +- **Records** a performance session while your page loads or runs +- **Analyzes** the results to identify bottlenecks and optimization opportunities + The Performance tab contains a Profiling tool. Open a website (try, for example, [https://www.microsoft.com](https://www.microsoft.com/?WT.mc_id=academic-77807-sagibbon)) and click the 'Record' button, then refresh the site. Stop the recording at any time, and you will be able to see the routines that are generated to 'script', 'render', and 'paint' the site: ![Edge profiler](./images/profiler.png) @@ -40,102 +56,179 @@ Check the Event Log pane to see if any event took longer than 15 ms: ## Profiling checks +Effective performance profiling goes beyond just running the tools - it requires knowing what to look for and how to interpret the data. Experienced developers have learned to spot common performance patterns that can make or break user experience. + +Let's examine the key areas where performance issues typically emerge and how to identify them before they become problems in production. + In general, there are some "problem areas" that every web developer should watch for when building a site to avoid nasty surprises when it's time to deploy to production. **Asset sizes**: The web has gotten 'heavier', and thus slower, over the past few years. Some of this weight has to do with the use of images. ✅ Look through the [Internet Archive](https://httparchive.org/reports/page-weight) for a historical view of page weight and more. -A good practice is to ensure that your images are optimized and delivered at the right size and resolution for your users. +**Best practices for asset optimization:** +- **Compresses** images using modern formats like WebP or AVIF +- **Serves** appropriately sized images for different screen resolutions +- **Minifies** CSS and JavaScript files to reduce download size +- **Implements** lazy loading for images and content below the fold **DOM traversals**: The browser has to build its Document Object Model based on the code you write, so it's in the interest of good page performance to keep your tags minimal, only using and styling what the page needs. To this point, excess CSS associated with a page could be optimized; styles that need to be used only on one page don't need to be included in the main style sheet, for example. +**Key strategies for DOM optimization:** +- **Minimizes** the number of HTML elements and nesting levels +- **Removes** unused CSS rules and consolidates stylesheets efficiently +- **Organizes** CSS to load only what's needed for each page +- **Structures** HTML semantically for better browser parsing + **JavaScript**: Every JavaScript developer should watch for 'render-blocking' scripts that must be loaded before the rest of the DOM can be traversed and painted to the browser. Consider using `defer` with your inline scripts (as is done in the Terrarium module). +**Modern JavaScript optimization techniques:** +- **Uses** the `defer` attribute to load scripts after DOM parsing +- **Implements** code splitting to load only necessary JavaScript +- **Applies** lazy loading for non-critical functionality +- **Minimizes** the use of heavy libraries and frameworks when possible + ✅ Try some sites on a [Site Speed Test website](https://www.webpagetest.org/) to learn more about the common checks that are done to determine site performance. Now that you have an idea of how the browser renders the assets you send to it, let's look at the last few things you need to do to complete your extension: ### Create a function to calculate color +Now we'll implement the core logic that transforms CO2 data into a visual indicator. This function will take the carbon intensity value from our API and map it to an appropriate color that reflects the environmental impact. + Working in `/src/index.js`, add a function called `calculateColor()` after the series of `const` variables you set to gain access to the DOM: -```JavaScript +```javascript function calculateColor(value) { - let co2Scale = [0, 150, 600, 750, 800]; - let colors = ['#2AA364', '#F5EB4D', '#9E4229', '#381D02', '#381D02']; + // Define CO2 intensity scale (grams per kWh) + const co2Scale = [0, 150, 600, 750, 800]; + // Corresponding colors from green (clean) to dark brown (high carbon) + const colors = ['#2AA364', '#F5EB4D', '#9E4229', '#381D02', '#381D02']; - let closestNum = co2Scale.sort((a, b) => { + // Find the closest scale value to our input + const closestNum = co2Scale.sort((a, b) => { return Math.abs(a - value) - Math.abs(b - value); })[0]; - console.log(value + ' is closest to ' + closestNum); - let num = (element) => element > closestNum; - let scaleIndex = co2Scale.findIndex(num); - - let closestColor = colors[scaleIndex]; + + console.log(`${value} is closest to ${closestNum}`); + + // Find the index for color mapping + const num = (element) => element > closestNum; + const scaleIndex = co2Scale.findIndex(num); + + const closestColor = colors[scaleIndex]; console.log(scaleIndex, closestColor); + // Send color update message to background script chrome.runtime.sendMessage({ action: 'updateIcon', value: { color: closestColor } }); } ``` -What's going on here? You pass in a value (the carbon intensity) from the API call you completed in the last lesson, and then you calculate how close its value is to the index presented in colors array. Then you send that closest color value over to the chrome runtime. +**Breaking down what happens here:** +- **Defines** arrays for CO2 intensity scale and corresponding colors +- **Calculates** the closest scale value using array sorting and Math.abs() +- **Finds** the appropriate color index using findIndex() method +- **Sends** a message to the Chrome runtime with the selected color +- **Uses** template literals for cleaner string formatting +- **Applies** const declarations for values that don't change -The chrome.runtime has [an API](https://developer.chrome.com/extensions/runtime) that handles all kinds of background tasks, and your extension is leveraging that: +The `chrome.runtime` has [an API](https://developer.chrome.com/extensions/runtime) that handles all kinds of background tasks, and your extension is leveraging that: > "Use the chrome.runtime API to retrieve the background page, return details about the manifest, and listen for and respond to events in the app or extension lifecycle. You can also use this API to convert the relative path of URLs to fully-qualified URLs." +**Understanding Chrome Runtime API benefits:** +- **Manages** communication between different parts of your extension +- **Handles** background tasks without blocking the user interface +- **Provides** lifecycle management for extension events +- **Enables** message passing between content scripts and background scripts + ✅ If you're developing this browser extension for Edge, it might surprise you that you're using a chrome API. The newer Edge browser versions run on the Chromium browser engine, so you can leverage these tools. -> Note, if you want to profile a browser extension, launch the dev tools from within the extension itself, as it is its own separate browser instance. +> **Pro Tip**: If you want to profile a browser extension, launch the dev tools from within the extension itself, as it is its own separate browser instance. This gives you access to extension-specific performance metrics. ### Set a default icon color +Before we fetch real data, it's important to initialize our extension with a default state. This provides immediate visual feedback to users and ensures the extension appears functional from the moment it loads. + Now, in the `init()` function, set the icon to be generic green to start by again calling chrome's `updateIcon` action: -```JavaScript +```javascript chrome.runtime.sendMessage({ action: 'updateIcon', - value: { - color: 'green', - }, + value: { + color: 'green', + }, }); ``` + +**What this initialization accomplishes:** +- **Sets** a neutral green color as the default state +- **Provides** immediate visual feedback when the extension loads +- **Establishes** the communication pattern with the background script +- **Ensures** users see a functional extension before data loads ### Call the function, execute the call +Now we'll integrate our color calculation function with the API data flow. This connects the data retrieval process with the visual indicator system, creating a seamless user experience. + Next, call that function you just created by adding it to the promise returned by the C02Signal API: -```JavaScript -//let CO2... +```javascript +// After retrieving CO2 data from the API +// let CO2 = data.data[0].intensity.actual; calculateColor(CO2); ``` +**This integration accomplishes:** +- **Connects** the API data flow with the visual indicator system +- **Triggers** icon updates automatically when new data arrives +- **Ensures** real-time visual feedback based on current carbon intensity +- **Maintains** the separation of concerns between data fetching and display logic + And finally, in `/dist/background.js`, add the listener for these background action calls: -```JavaScript +```javascript +// Listen for messages from the content script chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) { if (msg.action === 'updateIcon') { chrome.action.setIcon({ imageData: drawIcon(msg.value) }); } }); -//borrowed from energy lollipop extension, nice feature! + +// Draw dynamic icon using Canvas API +// Borrowed from energy lollipop extension - nice feature! function drawIcon(value) { - let canvas = new OffscreenCanvas(200, 200); - let context = canvas.getContext('2d'); + // Create an offscreen canvas for better performance + const canvas = new OffscreenCanvas(200, 200); + const context = canvas.getContext('2d'); + // Draw a colored circle representing carbon intensity context.beginPath(); context.fillStyle = value.color; context.arc(100, 100, 50, 0, 2 * Math.PI); context.fill(); + // Return the image data for the browser icon return context.getImageData(50, 50, 100, 100); } ``` -In this code, you are adding a listener for any messages coming to the backend task manager. If it's called 'updateIcon', then the next code is run to draw an icon of the proper color using the Canvas API. + +**Understanding the background script functionality:** +- **Listens** for messages from content scripts using runtime.onMessage +- **Processes** 'updateIcon' actions to change the extension's toolbar icon +- **Creates** dynamic icons using the Canvas API and OffscreenCanvas +- **Draws** a colored circle that reflects current carbon intensity levels +- **Updates** the browser toolbar with the newly generated icon image +- **Uses** OffscreenCanvas for better performance in background contexts ✅ You'll learn more about the Canvas API in the [Space Game lessons](../../6-space-game/2-drawing-to-canvas/README.md). -Now, rebuild your extension (`npm run build`), refresh and launch your extension, and watch the color change. Is it a good time to run an errand or wash the dishes? Now you know! +**Testing your completed extension:** +- **Build** your extension using `npm run build` +- **Reload** the extension in your browser's extension management page +- **Launch** your extension and watch the color change based on current data +- **Monitor** how the icon updates reflect real-time carbon intensity + +Is it a good time to run an errand or wash the dishes? Now you know! Congratulations, you've built a useful browser extension and learned more about how the browser works and how to profile its performance. @@ -153,7 +246,13 @@ Use the Agent mode to complete the following challenge: ## 🚀 Challenge -Investigate some open source websites that have been around a long time ago, and, based on their GitHub history, see if you can determine how they were optimized over the years for performance, if at all. What is the most common pain point? +Investigate some open source websites that have been around a long time, and, based on their GitHub history, see if you can determine how they were optimized over the years for performance, if at all. What is the most common pain point? + +**Research approach:** +- **Examines** commit history for performance-related changes +- **Identifies** patterns in optimization strategies over time +- **Analyzes** common performance bottlenecks across different projects +- **Documents** your findings and shares insights with the community ## Post-Lecture Quiz diff --git a/5-browser-extension/3-background-tasks-and-performance/assignment.md b/5-browser-extension/3-background-tasks-and-performance/assignment.md index da68b50e..f3d8aa4f 100644 --- a/5-browser-extension/3-background-tasks-and-performance/assignment.md +++ b/5-browser-extension/3-background-tasks-and-performance/assignment.md @@ -1,9 +1,93 @@ # Analyze a site for performance -Provide a detailed report of a web site, showing areas where performance is problematic. Analyze why the site is slow and what you could do to speed it up. Don't rely only on the browser tools, but do some research on other tools that can help your report. +## Assignment Overview + +Performance analysis is a critical skill for modern web developers. In this assignment, you'll conduct a comprehensive performance audit of a real website, using both browser-based tools and third-party services to identify bottlenecks and propose optimization strategies. + +Your task is to provide a detailed performance report that demonstrates your understanding of web performance principles and your ability to use professional analysis tools effectively. + +## Assignment Instructions + +**Choose a website** for analysis - select one of the following options: +- A popular website you use frequently (news site, social media, e-commerce) +- An open-source project website (GitHub pages, documentation sites) +- A local business website or portfolio site +- Your own project or previous coursework + +**Conduct multi-tool analysis** using at least three different approaches: +- **Browser DevTools** - Use Chrome/Edge Performance tab for detailed profiling +- **Online auditing tools** - Try Lighthouse, GTmetrix, or WebPageTest +- **Network analysis** - Examine resource loading, file sizes, and request patterns + +**Document your findings** in a comprehensive report that includes: + +### Performance Metrics Analysis +- **Load time measurements** from multiple tools and perspectives +- **Core Web Vitals** scores (LCP, FID, CLS) and their implications +- **Resource breakdown** showing which assets contribute most to load time +- **Network waterfall analysis** identifying blocking resources + +### Problem Identification +- **Specific performance bottlenecks** with supporting data +- **Root cause analysis** explaining why each issue occurs +- **User impact assessment** describing how problems affect real users +- **Priority ranking** of issues based on severity and fixing difficulty + +### Optimization Recommendations +- **Specific, actionable improvements** with expected impact +- **Implementation strategies** for each recommended change +- **Modern best practices** that could be applied (lazy loading, compression, etc.) +- **Tools and techniques** for ongoing performance monitoring + +## Research Requirements + +**Don't rely only on browser tools** - expand your analysis using: + +**Third-party auditing services:** +- [Google Lighthouse](https://developers.google.com/web/tools/lighthouse) - Comprehensive audits +- [GTmetrix](https://gtmetrix.com/) - Performance and optimization insights +- [WebPageTest](https://www.webpagetest.org/) - Real-world testing conditions +- [Pingdom](https://tools.pingdom.com/) - Global performance monitoring + +**Specialized analysis tools:** +- [Bundle Analyzer](https://bundlephobia.com/) - JavaScript bundle size analysis +- [Image optimization tools](https://squoosh.app/) - Asset optimization opportunities +- [Security headers analysis](https://securityheaders.com/) - Security performance impact + +## Deliverables Format + +Create a professional report (2-3 pages) that includes: + +1. **Executive Summary** - Key findings and recommendations overview +2. **Methodology** - Tools used and testing approach +3. **Current Performance Assessment** - Baseline metrics and measurements +4. **Issues Identified** - Detailed problem analysis with supporting data +5. **Recommendations** - Prioritized improvement strategies +6. **Implementation Roadmap** - Step-by-step optimization plan + +**Include visual evidence:** +- Screenshots of performance tools and metrics +- Charts or graphs showing performance data +- Before/after comparisons where possible +- Network waterfall charts and resource breakdowns ## Rubric -| Criteria | Exemplary | Adequate | Needs Improvement | -| -------- | ---------------------------------------------------------------------------------------------------------- | --------------------------- | ----------------------------- | -| | A report is presented with details drawn not only from browser tools but from 3rd party tools if available | A basic report is presented | A minimal report is presented | +| Criteria | Exemplary (90-100%) | Adequate (70-89%) | Needs Improvement (50-69%) | +| -------- | ------------------- | ----------------- | -------------------------- | +| **Analysis Depth** | Comprehensive analysis using 4+ tools with detailed metrics, root cause analysis, and user impact assessment | Good analysis using 3 tools with clear metrics and basic problem identification | Basic analysis using 2 tools with limited depth and minimal problem identification | +| **Tool Diversity** | Uses browser tools + 3+ third-party services with comparative analysis and insights from each | Uses browser tools + 2 third-party services with some comparative analysis | Uses browser tools + 1 third-party service with limited comparison | +| **Problem Identification** | Identifies 5+ specific performance issues with detailed root cause analysis and quantified impact | Identifies 3-4 performance issues with good analysis and some impact measurement | Identifies 1-2 performance issues with basic analysis | +| **Recommendations** | Provides specific, actionable recommendations with implementation details, expected impact, and modern best practices | Provides good recommendations with some implementation guidance and expected outcomes | Provides basic recommendations with limited implementation details | +| **Professional Presentation** | Well-organized report with clear structure, visual evidence, executive summary, and professional formatting | Good organization with some visual evidence and clear structure | Basic organization with minimal visual evidence | + +## Learning Outcomes + +By completing this assignment, you will demonstrate your ability to: +- **Apply** professional performance analysis tools and methodologies +- **Identify** performance bottlenecks using data-driven analysis +- **Analyze** the relationship between code quality and user experience +- **Recommend** specific, actionable optimization strategies +- **Communicate** technical findings in a professional format + +This assignment reinforces the performance concepts learned in the lesson while building practical skills you'll use throughout your web development career.