mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat(curriculum): add Build an HTML Audio and Video Player lab (#62460)
This commit is contained in:
@@ -2140,6 +2140,12 @@
|
||||
"In these lessons, you will learn how to work with the <code>audio</code> and <code>video</code> elements."
|
||||
]
|
||||
},
|
||||
"lab-html-audio-and-video-player": {
|
||||
"title": "Build an HTML Audio and Video Player",
|
||||
"intro": [
|
||||
"In this lab, you will build an HTML audio and video player using the <code>video</code> and <code>audio</code> elements with controls and source attributes."
|
||||
]
|
||||
},
|
||||
"lecture-working-with-images-and-svgs": {
|
||||
"title": "Working with Images and SVGs",
|
||||
"intro": [
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Introduction to the Build an HTML Audio and Video Player Lab
|
||||
block: lab-html-audio-and-video-player
|
||||
superBlock: full-stack-developer
|
||||
---
|
||||
|
||||
## Introduction to the Build an HTML Audio and Video Player Lab
|
||||
|
||||
In this lab, you will build an HTML audio and video player using the `video` and `audio` elements with controls and source attributes.
|
||||
+214
@@ -0,0 +1,214 @@
|
||||
---
|
||||
id: 68de40f53fcaf106f51cc20f
|
||||
title: Build an HTML Audio and Video Player
|
||||
challengeType: 25
|
||||
dashedName: build-an-html-audio-and-video-player
|
||||
demoType: onClick
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab.
|
||||
|
||||
**User Stories:**
|
||||
|
||||
1. You should have an `h1` element for the main title of the page.
|
||||
2. You should have two `section` elements.
|
||||
3. Inside the first `section` element, you should have an `h2` element for the title of the video playing.
|
||||
4. Below the `h2` element, you should have a `video` element with `controls` and `width` attributes. The `width` attribute should be set to `640`.
|
||||
5. Inside the `video` element, you should have a `source` element with a `src` attribute pointing to a video file and a `type` attribute.
|
||||
- You can use `https://cdn.freecodecamp.org/curriculum/labs/What is the map method and how does it work.mp4`.
|
||||
6. Inside the second `section` element, you should have an `h2` element for the title of the song playing.
|
||||
7. Below the `h2` element, you should have an `audio` element with the `controls` and `loop` attributes, and a `src` attribute that points to an audio file.
|
||||
- You can use `https://cdn.freecodecamp.org/curriculum/js-music-player/sailing-away.mp3`.
|
||||
- Or `https://cdn.freecodecamp.org/curriculum/js-music-player/we-are-going-to-make-it.mp3`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have an `h1` element for the main title of the page.
|
||||
|
||||
```js
|
||||
const h1 = document.querySelector('h1');
|
||||
assert.exists(h1);
|
||||
```
|
||||
|
||||
Your `h1` should not be empty.
|
||||
|
||||
```js
|
||||
const h1 = document.querySelector('h1');
|
||||
assert.isNotEmpty(h1.textContent.trim());
|
||||
```
|
||||
|
||||
You should have only one `h1` element
|
||||
|
||||
```js
|
||||
assert.lengthOf(document.querySelectorAll('h1'), 1);
|
||||
```
|
||||
|
||||
You should have two `section` elements.
|
||||
|
||||
```js
|
||||
assert.lengthOf(document.querySelectorAll('section'), 2);
|
||||
|
||||
```
|
||||
|
||||
Inside the first `section` element, you should have an `h2` element for the title of the video playing.
|
||||
|
||||
```js
|
||||
const section = document.querySelector('section');
|
||||
const h2 = section?.querySelector('h2');
|
||||
assert.exists(h2);
|
||||
```
|
||||
|
||||
Below the `h2` element, you should have a `video` element.
|
||||
|
||||
```js
|
||||
const section = document.querySelector('section');
|
||||
const video = section?.querySelector('h2 + video');
|
||||
assert.exists(video);
|
||||
```
|
||||
|
||||
The `video` element should have a `controls` attribute.
|
||||
|
||||
```js
|
||||
const section = document.querySelector('section');
|
||||
const video = section?.querySelector('h2 + video');
|
||||
const controlsAttr = video.controls;
|
||||
assert.isTrue(controlsAttr);
|
||||
```
|
||||
|
||||
The `video` element should have a `width` attribute set to `640`.
|
||||
|
||||
```js
|
||||
const section = document.querySelector('section');
|
||||
const video = section?.querySelector('h2 + video');
|
||||
const widthAttr = video.getAttribute('width');
|
||||
assert.equal(widthAttr, '640');
|
||||
```
|
||||
|
||||
Inside the `video` element, you should have a `source` element.
|
||||
|
||||
```js
|
||||
const section = document.querySelector('section');
|
||||
const source = section?.querySelector('h2 + video > source');
|
||||
assert.exists(source);
|
||||
```
|
||||
|
||||
The `source` element should have a `src` attribute pointing to a video file.
|
||||
|
||||
```js
|
||||
const section = document.querySelector('section');
|
||||
const source = section?.querySelector('h2 + video > source');
|
||||
const srcAttr = source.getAttribute('src');
|
||||
assert.match(srcAttr, /\.(mp4|webm|ogg|avi|mov)$/i);
|
||||
```
|
||||
|
||||
The `source` element should have a `type` attribute
|
||||
|
||||
```js
|
||||
const section = document.querySelector('section');
|
||||
const source = section?.querySelector('h2 + video > source');
|
||||
const typeAttr = source.getAttribute('type');
|
||||
assert.isNotEmpty(typeAttr);
|
||||
```
|
||||
|
||||
Inside the second `section` element, you should have an `h2` element for the title of the song playing.
|
||||
|
||||
```js
|
||||
const section = document.querySelector('section:nth-of-type(2)');
|
||||
const h2 = section?.querySelector('h2');
|
||||
assert.exists(h2);
|
||||
```
|
||||
|
||||
All your `h2` elements should contain some text.
|
||||
|
||||
```js
|
||||
const h2s = document.querySelectorAll('h2');
|
||||
assert.isNotEmpty(h2s);
|
||||
h2s.forEach((h2) => assert.isNotEmpty(h2.textContent.trim()));
|
||||
```
|
||||
|
||||
Below the `h2` element, you should have an `audio` element.
|
||||
|
||||
```js
|
||||
const section = document.querySelector('section:nth-of-type(2)');
|
||||
const audio = section?.querySelector('h2 + audio');
|
||||
assert.exists(audio);
|
||||
```
|
||||
|
||||
The `audio` element should have a `controls` attribute.
|
||||
|
||||
```js
|
||||
const section = document.querySelector('section:nth-of-type(2)');
|
||||
const audio = section?.querySelector('h2 + audio');
|
||||
const controlsAttr = audio.controls;
|
||||
assert.isTrue(controlsAttr);
|
||||
```
|
||||
|
||||
The `audio` element should have a `loop` attribute.
|
||||
|
||||
```js
|
||||
const section = document.querySelector('section:nth-of-type(2)');
|
||||
const audio = section?.querySelector('h2 + audio');
|
||||
const loopAttr = audio.loop;
|
||||
assert.isTrue(loopAttr);
|
||||
```
|
||||
|
||||
The `audio` element should have a `src` attribute pointing to an audio file.
|
||||
|
||||
```js
|
||||
const section = document.querySelector('section:nth-of-type(2)');
|
||||
const audio = section?.querySelector('h2 + audio');
|
||||
const srcAttr = audio.getAttribute('src');
|
||||
assert.match(srcAttr, /\.(mp3|wav|ogg|aac|flac)$/i);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>HTML Audio and Video Lab</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>HTML Audio and Video Lab</title>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<h1>HTML Audio and Video Lab</h1>
|
||||
|
||||
<section>
|
||||
<h2>What is the map method and how does it work</h2>
|
||||
<video controls width="640">
|
||||
<source src="https://cdn.freecodecamp.org/curriculum/labs/What is the map method and how does it work.mp4" type="video/mp4" />
|
||||
</video>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Sailing Away</h2>
|
||||
<audio src="https://cdn.freecodecamp.org/curriculum/js-music-player/sailing-away.mp3" controls loop>
|
||||
</audio>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "Build an HTML Audio and Video Player",
|
||||
"isUpcomingChange": false,
|
||||
"dashedName": "lab-html-audio-and-video-player",
|
||||
"helpCategory": "HTML-CSS",
|
||||
"blockLayout": "link",
|
||||
"challengeOrder": [
|
||||
{
|
||||
"id": "68de40f53fcaf106f51cc20f",
|
||||
"title": "Build an HTML Audio and Video Player"
|
||||
}
|
||||
],
|
||||
"blockType": "lab",
|
||||
"usesMultifileEditor": true
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
"lecture-understanding-how-html-affects-seo",
|
||||
"lab-travel-agency-page",
|
||||
"lecture-working-with-audio-and-video-elements",
|
||||
"lab-html-audio-and-video-player",
|
||||
"lecture-working-with-images-and-svgs",
|
||||
"workshop-build-a-heart-icon",
|
||||
"lecture-working-with-media",
|
||||
|
||||
Reference in New Issue
Block a user