So, while I was finishing up with Homework 6, one additional bit of functionality that would be nice to add came to mind
Not only will it serve to jazz the page up a tiny bit more, it will also allow us to look at our JavaScript from a slightly different perspective
OK!
CSCI 1720
Intermediate Web
Homework 7 - More CSS & JavaScript
One little thing I'd like to add is for the play/pause buttons to remain highlighted when each is active
Create a new folder named hw7_js-3 on your external drive
Copy your files and folders from the hw6_js-2 folder to the hw7_js-3 folder. This, again, will be our starting point
Couple of things to address, here
Make sure all references to '(H/h)omework 6' are updated to read '(H/h)omework 7'
If the 'controls' attribute is still present in your <audio> element, remove it
All of the meta-information in your <head> element should be updated to reflect this new assignment
Add at least four <meta name='' content=''> elements, one each for author, date, keywords, and description. You may think of additional meta-elements that would be appropriate here (like, maybe, 'last revised')
CSS
So we need to add a CSS class that will tell the browser how the button should be displayed when it is active. We'll call this class, appropriately enough, .active
Open main.scss in Brackets. Oops! I almost forgot - Launch the Command Line Interface (cmd.exe) and run Sass in your working_directory/homework/hw7_js-3 directory. I'm assuming that by now you have enough practice with Sass that you can handle this without detailed instructions
Add the following and save your file
Fig 2- .active class
Interesting thing to note here: the color is defined using hexidecimal notation with alpha channel information. The last pair defines how transparent the color will be
That will do it for our CSS, for now
JavaScript
We're going to change the onclick attributes' properties to function calls; then define the functions
Modify the buttons' onclick properties as shown below (adding class='audioControl' to each as well)
Fig 3- Changing the controls
As you can see, we've changed the method call to a function call for a custom function in each control. You may be wondering why we didn't add an audioControl class to our CSS -- we shall see
Now that we have the function call is in place, best to define their respective functions, I guess. Scroll down to the bottom of index.html, where your JavaScript is
Typically, when developing these things, I'll get one bit working; then apply it to the rest. So let's add (after hide())
Fig 4- Setting up the first function
Think for a minute about what we want the page to do. When the user clicks the 'play' button, we want the audio control to start playing the .mp3 and for the button to remain highlighted, providing visual feedback. But what about when the user presses the 'pause' button? Well, we want it highlighted, but what else? That's right - the 'play' button has to be 'un-highlighted'. So we know we're going to need a function to do that
Add the following
Fig 5- Function to clear highlighting
Ok, back to the play() function. Here's a trick with the developer tools that will help you with selecting an element if it doesn't have an ID (ordinarily, you'd just assign an ID to it and use that, but work with me here). With the page displayed in your browser and the developer tools open, use the element selector tool to select the element you want to identify (in this case, the 'play' button)
This will highlight the element in the developer tool. Right-click on the highlighted part, hover over 'Copy', and select 'Copy JS path'
Fig 6- Select an element for identification
This will copy the JavaScript query to the clipboard for you
In your index.html, add a variable assignment and paste in the JavaScript from the clipboard
Fig 7- Pasting JS selector into code
This may look confusing, but it makes sense, if you remember your contextual selectors. It starts with the body element, then progresses down through the DOM until it reaches the desired element. This trick can be real useful when you're developing and don't want to have to refactor all of your code
You can also see how assigning that monstrosity to a shorter variable ('el' is an arbitrary name - short for 'element') will make it easier to refer to it in your code
Now we'll put in a call to 'un-toggle' the active element, whatever it may be (we haven't written it yet, but we know what we want it to do)
Fig 8- Clear active
Now, here's our "meat 'n taters"
Fig 9- Active class and play
Notice here that each time we click the play button, we're resetting the volume to 0.3. There are other ways we could handle this if we wanted the user to be able to pause and resume without resetting the volume, but that's good enough for now
Using the same steps, now, you can complete the pause() function:
Fig 10- pause() function
Volume up and volume down don't need to be highlighted, so the functions for them are pretty straightforward
Fig 11- Volume up/down
Now all that's left to do is create the clearActive() function. This requires a different JS query - querying the class
Fig 12- Query by class
The important distinction here is that imgs is an collection of values, not a single value. The collection is called an HTMLCollection, which is similar to an array, but not quite the same. So we'll want to convert it to an array in order to be able to use the forEach() loop control. Then imgs[0] corresponds to the 'play' button, imgs[1] to the 'pause' button, and so on - but with forEach(), as you'll see, we don't have to worry about the array indeces this time
The function will iterate through all of the objects in the array and remove the active class from each (if it's not there in the first place, nothing happens). We'll use a forEach loop to iterate through the four (see what I did there?) objects - in this case - and remove the class from each
Fig 13- Clearing the active class
Granted, there are only two of the objects ('play' and 'pause') that will ever have the active class added to them, so we could have just explicitly removed the class from each with two lines of code.
But what if we were to add more controls, say 'reverse' and 'fast forward' sometime in the future? Matter of preference, I guess
Fig 14- Order of execution when user clicks play or pause
So now it's time to test our code
Save your work and refresh the page in your browser. Click the 'play' button. Check that the 'play' button remains highlighted; then click the pause button. The playback should pause and the button should now be highlighted. Click 'play' again and check the volume controls to make sure they work
If there are any errors or anything that doesn't work like it should, it's time to check the console for error messages. Troubleshooting is an essential part of programming (remember - Right-click→Inspect or F12). The error messages will at the very least, give you a line number to start looking
If you have errors you can't resolve, upload your work to the server and send me an email so I can help troubleshoot
Finally (no, seriously)
Remember a while back when I said that drop-caps are nice but easily can be overdone? Looking are our work, I think we kind of did that. So let's go back to our main.scss file and look at the code for the drop-caps
Fig 15- Pseudo element
What we'd like to do is modify the code so that the browser only modifies the first letter of the first paragraph. Ultimately, we'll end up with this
Fig 16- Pseudo element
To understand how we're going to do this, we need to revisit the notion of the parent-child relationship that exists between HTML elements
Fig 17- Parent-child relationship
So we can see that the first paragraph in this construct is the fourth child element of the container-inner element. There is a CSS pseudo class, :nth-child() that allows us to select a specific child or children of a parent element. We can combine these two bits of information to solve our conundrum
Modify the pseudo element like this
Fig 18- Chaining selectors
Update the page's header from 'Homework 6' to 'Homework 7,' if you haven't already. Save your work and refresh the page in the browser. Use the 'developer tools' trick to modify the first letter so it spans three lines of text as shown in Fig. 16 and copy/save the properties/values back in to your code like we did in Homework 6, Steps 13-14
Finally, if all went well, we should have this
Fig 19- HW5 Final (final!) result
Once everything is working, log in to the class server with FileZilla
Navigate to your homework folder
Create a new subfolder named hw7_js-3 (alternatively, you can just upload your local hw7_js-3 folder to the homework folder on the server)
Upload all of your files/folders to the new subfolder
Display your page in the browser and Ctrl+click the validation links to check for errors in your HTML and CSS
Correct any errors that may have crept in, save, and re-upload your revised files to the server
Copy/paste the URL into a text file. Name the file hw7_js-3.txt and upload it to the D2L HW5 folder