mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
354 lines
9.7 KiB
Markdown
354 lines
9.7 KiB
Markdown
---
|
|
id: 669e2f60e83c011754f711f9
|
|
title: Build a Travel Agency Page
|
|
challengeType: 25
|
|
dashedName: build-a-travel-agency-page
|
|
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 a `DOCTYPE` declaration.
|
|
1. You should have an `html` element with `lang` set to `en`.
|
|
1. You should have a `head` element containing a `meta` void element with `charset` set to `utf-8` and a `title` with the text `Travel Agency Page`.
|
|
1. You should have a `meta` tag in your `head` element that contains a short description of your website for SEO.
|
|
1. You should have an `h1` element to present your travel destinations.
|
|
1. You should have a paragraph below the `h1` element introducing the travel opportunities.
|
|
1. You should have an `h2` element with the text `Packages`.
|
|
1. You should have a `p` element introducing briefly the various packages.
|
|
1. You should have an unordered list element with two list items. The two list items should have the text `Group Travels` and `Private Tours`, respectively. The text of each list item should be enclosed by an anchor element.
|
|
1. You should have an `h2` element with the text `Top Itineraries`.
|
|
1. You should have at least three `figure` elements, each containing an anchor element and a `figcaption` element.
|
|
1. The three anchor elements should have an `img` element with an appropriate `alt` attribute and a `src` attribute set to a valid image as their content. You can use `https://cdn.freecodecamp.org/curriculum/labs/colosseo.jpg`, `https://cdn.freecodecamp.org/curriculum/labs/alps.jpg`, and `https://cdn.freecodecamp.org/curriculum/labs/sea.jpg` if you would like.
|
|
1. All your five anchor elements should have an `href` attribute with the value of `https://www.freecodecamp.org/learn` and a `target` attribute with the value of `_blank`.
|
|
|
|
# --hints--
|
|
|
|
Your travel agency page should have a `!DOCTYPE html` declaration.
|
|
|
|
```js
|
|
assert.match(code, /<!DOCTYPE\s+html>/i);
|
|
```
|
|
|
|
You should have an `html` element with `lang` set to `en`.
|
|
|
|
```js
|
|
assert.match(code, /<html\s+lang\s*=\s*('|")en\1\s*>[\s\S]*<\/\s*html\s*>/i);
|
|
```
|
|
|
|
You should have a `head` element within the `html` element.
|
|
|
|
```js
|
|
assert.match(
|
|
code,
|
|
/<html[\s\S]*>[\s\S]*<\s*head\s*>[\s\S]*<\/\s*head\s*>[\s\S]*<\/\s*html\s*>/i
|
|
);
|
|
```
|
|
|
|
You should have two `meta` elements within your `head` element.
|
|
|
|
```js
|
|
assert.match(code, /<\s*head\s*>[\s\S]*(<\s*meta[\s\S]*>[\s\S]*){2,}<\/\s*head\s*>/i);
|
|
```
|
|
|
|
One `meta` element should have a `name` attribute with value of `description` and a non-empty `content` attribute.
|
|
|
|
```js
|
|
assert.match(code,
|
|
/<\s*meta\s+[^>]*name\s*=\s*["']description["'][^>]*content\s*=\s*["'][^"']+?["'][^>]*>/i,
|
|
);
|
|
```
|
|
|
|
One `meta` element should have its `charset` attribute set to `UTF-8`.
|
|
|
|
```js
|
|
assert.match(code, /<\s*meta[\s\S]+?charset\s*=\s*('|")UTF-8\1/i);
|
|
```
|
|
|
|
You should have `title` element within your `head` element.
|
|
|
|
```js
|
|
assert.match(
|
|
code,
|
|
/<\s*head\s*>[\s\S]*<\s*title\s*>[\s\S]*<\/\s*title\s*>[\s\S]*<\/\s*head\s*>/i
|
|
);
|
|
```
|
|
|
|
Your `title` element should have your travel agency name.
|
|
|
|
```js
|
|
assert.isAbove(document.querySelector('title')?.innerText.trim().length, 0);
|
|
```
|
|
|
|
You should have a `body` element within your `html` element.
|
|
|
|
```js
|
|
assert.match(
|
|
code,
|
|
/<\s*html[\s\S]*>[\s\S]*<\s*head\s*>[\s\S]*<\/\s*head\s*>[\s\S]*<\s*body\s*>[\s\S]*<\/\s*body\s*>[\s\S]*<\/\s*html\s*>/i
|
|
);
|
|
```
|
|
|
|
You should have an `h1` element to present your travel destinations.
|
|
|
|
```js
|
|
assert.isAbove(document.querySelector('h1')?.innerText.length, 0);
|
|
```
|
|
|
|
You should only have one `h1` element.
|
|
|
|
```js
|
|
assert.lengthOf(document.querySelectorAll('h1'), 1);
|
|
```
|
|
|
|
You should have a `p` element below the `h1` element.
|
|
|
|
```js
|
|
assert.strictEqual(
|
|
document.querySelector('h1')?.nextElementSibling.tagName, 'P'
|
|
);
|
|
```
|
|
|
|
Your first `p` element should introduce the travel opportunities.
|
|
|
|
```js
|
|
assert.isNotEmpty(document.querySelector('p')?.textContent?.trim());
|
|
```
|
|
|
|
Your first `h2` element should have the text `Packages`.
|
|
|
|
```js
|
|
assert.equal(document.querySelectorAll('h2')[0]?.innerText.trim(), 'Packages');
|
|
```
|
|
|
|
You should have a `p` element below your first `h2` element.
|
|
|
|
```js
|
|
assert.strictEqual(
|
|
document.querySelector('h2')?.nextElementSibling.tagName, 'P'
|
|
);
|
|
```
|
|
|
|
Your second `p` element should introduce briefly the various packages.
|
|
|
|
```js
|
|
assert.isNotEmpty(document.querySelectorAll('p')?.[1]?.textContent?.trim());
|
|
```
|
|
|
|
You should have an unordered list element below your second `p` element.
|
|
|
|
```js
|
|
assert.strictEqual(
|
|
document.querySelectorAll('p')?.[1]?.nextElementSibling?.tagName,
|
|
'UL'
|
|
);
|
|
```
|
|
|
|
You should have two items in your unordered list.
|
|
|
|
```js
|
|
assert.lengthOf(document.querySelectorAll('p + ul li'), 2);
|
|
```
|
|
|
|
Both your list items should contain an anchor element.
|
|
|
|
```js
|
|
const listItems = document.querySelectorAll('p + ul li');
|
|
assert.isNotEmpty(listItems);
|
|
for (let e of listItems) {
|
|
assert.strictEqual(e.children[0].tagName, 'A');
|
|
assert.lengthOf(e.children, 1);
|
|
}
|
|
```
|
|
|
|
The anchor element of your first list item should wrap the text `Group Travels`.
|
|
|
|
```js
|
|
assert.equal(document.querySelectorAll('li > a')[0]?.innerText.trim(), 'Group Travels');
|
|
```
|
|
|
|
The anchor element of your second list item should wrap the text `Private Tours`.
|
|
|
|
```js
|
|
assert.equal(document.querySelectorAll('li > a')[1]?.innerText.trim(), 'Private Tours');
|
|
```
|
|
|
|
You should have an `h2` element after your unordered list.
|
|
|
|
```js
|
|
assert.strictEqual(
|
|
document.querySelectorAll('h2')[1]?.previousElementSibling.tagName,
|
|
'UL'
|
|
);
|
|
```
|
|
|
|
Your second `h2` element should have the text `Top Itineraries`.
|
|
|
|
```js
|
|
assert.equal(document.querySelectorAll('h2')[1]?.innerText.trim(), 'Top Itineraries');
|
|
```
|
|
|
|
You should have at least three `figure` elements.
|
|
|
|
```js
|
|
assert.isAtLeast(document.querySelectorAll('figure').length, 3);
|
|
```
|
|
|
|
Each `figure` element should contain an anchor element as its first nested element.
|
|
|
|
```js
|
|
const figures = document.querySelectorAll('figure');
|
|
assert.isNotEmpty(figures);
|
|
for (let figure of figures) {
|
|
assert.equal(figure.children[0].tagName, 'A');
|
|
}
|
|
```
|
|
|
|
Each `figure` element should contain a `figcaption` element as its second nested element.
|
|
|
|
```js
|
|
const figures = document.querySelectorAll('figure');
|
|
assert.isNotEmpty(figures);
|
|
for (let figure of figures) {
|
|
assert.equal(figure.children[1]?.tagName, 'FIGCAPTION');
|
|
}
|
|
```
|
|
|
|
Each `figcaption` should contain some text.
|
|
|
|
```js
|
|
const figcaptionEls = document.querySelectorAll('figcaption');
|
|
assert.isNotEmpty(figcaptionEls);
|
|
figcaptionEls.forEach((figcaption => assert.isNotEmpty(figcaption.innerText)));
|
|
```
|
|
|
|
Each of the `a` elements nested in your `figure` elements should contain an image.
|
|
|
|
```js
|
|
const anchors = document.querySelectorAll('figure > a');
|
|
assert.isNotEmpty(anchors);
|
|
for (let anchor of anchors) {
|
|
assert.equal(anchor.children[0]?.tagName, 'IMG');
|
|
}
|
|
```
|
|
|
|
Each `img` element should have a valid `src` attribute.
|
|
|
|
```js
|
|
const images = document.querySelectorAll('img');
|
|
assert.isNotEmpty(images);
|
|
for (let image of images) {
|
|
assert.isAbove(image.src.trim().length, 0);
|
|
}
|
|
```
|
|
|
|
Each `img` element should have an `alt` attribute with an appropriate value.
|
|
|
|
```js
|
|
const images = document.querySelectorAll('img');
|
|
assert.isNotEmpty(images);
|
|
for (let image of images) {
|
|
assert.isAbove(image.alt.trim().length, 0);
|
|
}
|
|
```
|
|
|
|
Each `a` element should have an `href` attribute with the value of `https://www.freecodecamp.org/learn`. Don't forget the links in the list items.
|
|
|
|
```js
|
|
const anchors = document.querySelectorAll('a');
|
|
assert.isNotEmpty(anchors);
|
|
for (let anchor of anchors) {
|
|
assert.equal(anchor.href, 'https://www.freecodecamp.org/learn');
|
|
}
|
|
```
|
|
|
|
Each `a` element should have a `target` attribute with the value of `_blank`. Don't forget the links in the list items.
|
|
|
|
```js
|
|
const anchors = document.querySelectorAll('a');
|
|
assert.isNotEmpty(anchors);
|
|
for (let anchor of anchors) {
|
|
assert.equal(anchor.target, '_blank');
|
|
}
|
|
```
|
|
|
|
# --seed--
|
|
|
|
## --seed-contents--
|
|
|
|
```html
|
|
|
|
```
|
|
|
|
# --solutions--
|
|
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<title>Travel Agency Page</title>
|
|
<meta name="description" content="This is an example website."/>
|
|
</head>
|
|
<body>
|
|
<h1>Discover Italy</h1>
|
|
<p>
|
|
Art, folklore, food, nature, and more. Choose among our wide selection of
|
|
guided tours and excursions, and live an unforgettable experience
|
|
exploring Italy.
|
|
</p>
|
|
<h2>Packages</h2>
|
|
<p>
|
|
We offer an extensive range of holiday solutions to accommodate the needs
|
|
of all our clients. From daily excursions in the most beautiful cities, to
|
|
thorough tours of hidden villages and medieval towns to discover Italy's
|
|
lesser-known sides.
|
|
</p>
|
|
<ul>
|
|
<li>
|
|
<a href="https://www.freecodecamp.org/learn" target="_blank"
|
|
>Group Travels</a
|
|
>
|
|
</li>
|
|
<li>
|
|
<a href="https://www.freecodecamp.org/learn" target="_blank"
|
|
>Private Tours</a
|
|
>
|
|
</li>
|
|
</ul>
|
|
<h2>Top Itineraries</h2>
|
|
<figure>
|
|
<a href="https://www.freecodecamp.org/learn" target="_blank">
|
|
<img
|
|
src="https://cdn.freecodecamp.org/curriculum/labs/colosseo.jpg"
|
|
alt="colosseum view"
|
|
/>
|
|
</a>
|
|
<figcaption>Rome and Center Italy</figcaption>
|
|
</figure>
|
|
<figure>
|
|
<a href="https://www.freecodecamp.org/learn" target="_blank">
|
|
<img
|
|
src="https://cdn.freecodecamp.org/curriculum/labs/alps.jpg"
|
|
alt="dolomites mountain view"
|
|
/>
|
|
</a>
|
|
<figcaption>Nature and National Parks</figcaption>
|
|
</figure>
|
|
<figure>
|
|
<a href="https://www.freecodecamp.org/learn" target="_blank">
|
|
<img
|
|
src="https://cdn.freecodecamp.org/curriculum/labs/sea.jpg"
|
|
alt="sea view"
|
|
/>
|
|
</a>
|
|
<figcaption>South Italy and Islands</figcaption>
|
|
</figure>
|
|
</body>
|
|
</html>
|
|
```
|