From dd3f629d732e68069fdbc038bdb73c645be309fb Mon Sep 17 00:00:00 2001 From: Tom <20648924+moT01@users.noreply.github.com> Date: Mon, 23 Sep 2024 01:48:28 -0500 Subject: [PATCH] feat(curriculum): add technical documentation page lab (#56154) Co-authored-by: Dario-DC <105294544+Dario-DC@users.noreply.github.com> --- client/i18n/locales/english/intro.json | 7 +- .../lab-technical-documentation-page/index.md | 9 + .../meta.json | 16 + .../587d78b0367417b2b2512b05.md | 847 ++++++++++++++++++ 4 files changed, 878 insertions(+), 1 deletion(-) create mode 100644 client/src/pages/learn/front-end-development/lab-technical-documentation-page/index.md create mode 100644 curriculum/challenges/_meta/lab-technical-documentation-page/meta.json create mode 100644 curriculum/challenges/english/25-front-end-development/lab-technical-documentation-page/587d78b0367417b2b2512b05.md diff --git a/client/i18n/locales/english/intro.json b/client/i18n/locales/english/intro.json index a132c3a10dc..8c08fbe6d4d 100644 --- a/client/i18n/locales/english/intro.json +++ b/client/i18n/locales/english/intro.json @@ -1875,7 +1875,12 @@ "rbnd": { "title": "102", "intro": [] }, "xebj": { "title": "103", "intro": [] }, "jkdt": { "title": "104", "intro": [] }, - "cbbz": { "title": "105", "intro": [] }, + "lab-technical-documentation-page": { + "title": "Build a Technical Documentation Page", + "intro": [ + "For this lab, you will build a technical documentation page to serve as instruction or reference for a topic." + ] + }, "xcti": { "title": "106", "intro": [] }, "scec": { "title": "107", "intro": [] }, "mtbl": { "title": "108", "intro": [] }, diff --git a/client/src/pages/learn/front-end-development/lab-technical-documentation-page/index.md b/client/src/pages/learn/front-end-development/lab-technical-documentation-page/index.md new file mode 100644 index 00000000000..8fdd13968d7 --- /dev/null +++ b/client/src/pages/learn/front-end-development/lab-technical-documentation-page/index.md @@ -0,0 +1,9 @@ +--- +title: Introduction to the Technical Documentation Page +block: lab-technical-documentation-page +superBlock: front-end-development +--- + +## Introduction to the Technical Documentation Page + +For this project, you will build a technical documentation page to serve as instruction or reference for a topic. diff --git a/curriculum/challenges/_meta/lab-technical-documentation-page/meta.json b/curriculum/challenges/_meta/lab-technical-documentation-page/meta.json new file mode 100644 index 00000000000..d7e19a22482 --- /dev/null +++ b/curriculum/challenges/_meta/lab-technical-documentation-page/meta.json @@ -0,0 +1,16 @@ +{ + "name": "Build a Technical Documentation Page", + "blockType": "lab", + "isUpcomingChange": true, + "usesMultifileEditor": true, + "dashedName": "lab-technical-documentation-page", + "order": 105, + "superBlock": "front-end-development", + "challengeOrder": [ + { + "id": "587d78b0367417b2b2512b05", + "title": "Build a Technical Documentation Page" + } + ], + "helpCategory": "HTML-CSS" +} diff --git a/curriculum/challenges/english/25-front-end-development/lab-technical-documentation-page/587d78b0367417b2b2512b05.md b/curriculum/challenges/english/25-front-end-development/lab-technical-documentation-page/587d78b0367417b2b2512b05.md new file mode 100644 index 00000000000..2d2fda2a00d --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/lab-technical-documentation-page/587d78b0367417b2b2512b05.md @@ -0,0 +1,847 @@ +--- +id: 587d78b0367417b2b2512b05 +title: Build a Technical Documentation Page +challengeType: 14 +demoType: onClick +dashedName: build-a-technical-documentation-page +--- + +# --description-- + +**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab. + +**User Stories:** + +1. You can see a `main` element with a corresponding `id="main-doc"`, which contains the page's main content (technical documentation). +1. Within the `#main-doc` element, you can see several `section` elements, each with a class of `main-section`. There should be a minimum of five. +1. The first element within each `.main-section` should be a `header` element, which contains text that describes the topic of that section. +1. Each `section` element with the class of `main-section` should also have an `id` that corresponds with the text of each `header` contained within it. Any spaces should be replaced with underscores (e.g. The section that contains the header "JavaScript and Java" should have a corresponding `id="JavaScript_and_Java"`). +1. The `.main-section` elements should contain at least ten `p` elements total (not each). +1. The `.main-section` elements should contain at least five `code` elements total (not each). +1. The `.main-section` elements should contain at least five `li` items total (not each). +1. You can see a `nav` element with a corresponding `id="navbar"`. +1. The navbar element should contain one `header` element which contains text that describes the topic of the technical documentation. +1. Additionally, the navbar should contain link (`a`) elements with the class of `nav-link`. There should be one for every element with the class `main-section`. +1. The `header` element in the `#navbar` must come before any link (`a`) elements in the navbar. +1. Each element with the class of `nav-link` should contain text that corresponds to the `header` text within each `section` (e.g. if you have a "Hello world" section/header, your navbar should have an element which contains the text "Hello world"). +1. When you click on a navbar element, the page should navigate to the corresponding section of the `#main-doc` element (e.g. If you click on a `.nav-link` element that contains the text "Hello world", the page navigates to a `section` element with that id, and contains the corresponding header). +1. On regular sized devices (laptops, desktops), the element with `id="navbar"` should be shown on the left side of the screen and should always be visible to the user. +1. Your technical documentation should use at least one media query. + +**Note:** Be sure to link your stylesheet in your HTML and apply your CSS. + +# --hints-- + +You should have a `main` element with an `id` of `main-doc`. + +```js +const el = document.getElementById('main-doc') +assert(!!el) +``` + +You should have at least five `section` elements with a class of `main-section`. + +```js +const els = document.querySelectorAll('#main-doc section') +assert(els.length >= 5) +``` + +All of your `.main-section` elements should be `section` elements. + +```js +const els = document.querySelectorAll('.main-section') +els.forEach(el => { + if (el.tagName !== 'SECTION') assert(false) +}) +assert(els.length > 0) +``` + +You should have at least five `.main-section` elements that are descendants of `#main-doc`. + +```js +const els = document.querySelectorAll('#main-doc .main-section') +assert(els.length >= 5) +``` + +The first child of each `.main-section` should be a `header` element. + +```js +const els = document.querySelectorAll('.main-section') +els.forEach(el => { + if(el.firstElementChild?.tagName !== 'HEADER') assert(false) +}) +assert(els.length > 0) +``` + +None of your `header` elements should be empty. + +```js +const els = document.querySelectorAll('header') +els.forEach(el => { + if (el.innerText?.length <= 0) assert(false) +}) +assert(els.length > 0) +``` + +All of your `.main-section` elements should have an `id`. + +```js +const els = document.querySelectorAll('.main-section') +els.forEach(el => { + if (!el.id || el.id === '') assert(false) +}) +assert(els.length > 0) +``` + +Each `.main-section` should have an `id` that matches the text of its first child, having any spaces in the child's text replaced with underscores (`_`) for the id's. + +```js +const els = document.querySelectorAll('.main-section') +els.forEach(el => { + const text = el.firstElementChild?.innerText?.replaceAll(' ', '_') + if (el.id?.toUpperCase() !== text?.toUpperCase()) assert(false) +}) +assert(els.length > 0) +``` + +You should have at least 10 `p` elements (total) within your `.main-section` elements. + +```js +const els = document.querySelectorAll('.main-section p') +assert(els.length >= 10) +``` + +You should have at least five `code` elements that are descendants of `.main-section` elements. + +```js +const els = document.querySelectorAll('.main-section code') +assert(els.length >= 5) +``` + +You should have at least five `li` elements that are descendants of `.main-section` elements. + +```js +const els = document.querySelectorAll('.main-section li') +assert(els.length >= 5) +``` + +You should have a `nav` element with an `id` of `navbar`. + +```js +const el = document.getElementById('navbar') +assert(!!el && el.tagName === 'NAV') +``` + +Your `#navbar` should have exactly one `header` element within it. + +```js +const els = document.querySelectorAll('#navbar header') +assert(els.length === 1) +``` + +You should have at least one `a` element with a class of `nav-link`. + +```js +const els = document.querySelectorAll('a.nav-link') +assert(els.length >= 1) +``` + +All of your `.nav-link` elements should be anchor (`a`) elements. + +```js +const els = document.querySelectorAll('.nav-link') +els.forEach(el => { + if (el.tagName !== 'A') assert(false) +}) +assert(els.length > 0) +``` + +All of your `.nav-link` elements should be in the `#navbar`. + +```js +const els1 = document.querySelectorAll('.nav-link') +const els2 = document.querySelectorAll('#navbar .nav-link') +assert(els2.length > 0 && els1.length === els2.length) +``` + +You should have the same number of `.nav-link` and `.main-section` elements. + +```js +const els1 = document.querySelectorAll('.main-section') +const els2 = document.querySelectorAll('.nav-link') +assert(els1.length > 0 && els2.length > 0 && els1.length === els2.length) +``` + +The `header` element in the `#navbar` should come before any link (`a`) elements also in the `#navbar`. + +```js +const navLinks = document.querySelectorAll('#navbar a.nav-link'); +const header = document.querySelector('#navbar header'); +navLinks.forEach((navLink) => { + if ( + ( + header.compareDocumentPosition(navLink) & + Node.DOCUMENT_POSITION_PRECEDING + ) + ) assert(false) +}); +assert(!!header) +``` + +Each `.nav-link` should have text that corresponds to the `header` text of its related `section` (e.g. if you have a "Hello world" section/header, your `#navbar` should have a `.nav-link` which has the text "Hello world"). + +```js +const headerText = Array.from(document.querySelectorAll('.main-section')).map(el => + el.firstElementChild?.innerText?.trim().toUpperCase() +) +const linkText = Array.from(document.querySelectorAll('.nav-link')).map(el => + el.innerText?.trim().toUpperCase() +) +const remainder = headerText.filter(str => linkText.indexOf(str) === -1) +assert(headerText.length > 0 && linkText.length > 0 && remainder.length === 0) +``` + +Each `.nav-link` should have an `href` attribute that links to its corresponding `.main-section` (e.g. If you click on a `.nav-link` element that contains the text "Hello world", the page navigates to a `section` element with that id). + +```js +const hrefValues = Array.from(document.querySelectorAll('.nav-link')).map(el => el.getAttribute('href')) +const mainSectionIDs = Array.from(document.querySelectorAll('.main-section')).map(el => el.id) +const missingHrefValues = mainSectionIDs.filter(str => hrefValues.indexOf('#' + str) === -1) +assert(hrefValues.length > 0 && mainSectionIDs.length > 0 && missingHrefValues.length === 0) +``` + +Your `#navbar` should always be on the left edge of the window. + +```js +const el = document.getElementById('navbar') +const left1 = el?.offsetLeft +const left2 = el?.offsetLeft +assert(!!el && left1 >= -15 && left1 <= 15 && left2 >= -15 && left2 <= 15) +``` + +Your Technical Documentation project should use at least one media query. + +```js +const htmlSourceAttr = Array.from(document.querySelectorAll('source')).map(el => el.getAttribute('media')) +const cssCheck = new __helpers.CSSHelp(document).getCSSRules('media') +assert(cssCheck.length > 0 || htmlSourceAttr.length > 0); +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + + Technical Documentation Page + + + + + + + +``` + +```css + +``` + +# --solutions-- + +```html + + + + + + + +
+
+
Introduction
+
+

+ JavaScript is a cross-platform, object-oriented scripting language. + It is a small and lightweight language. Inside a host environment + (for example, a web browser), JavaScript can be connected to the + objects of its environment to provide programmatic control over + them. +

+ +

+ JavaScript contains a standard library of objects, such as Array, + Date, and Math, and a core set of language elements such as + operators, control structures, and statements. Core JavaScript can + be extended for a variety of purposes by supplementing it with + additional objects; for example: +

+
    +
  • + Client-side JavaScript extends the core language by supplying + objects to control a browser and its Document Object Model (DOM). + For example, client-side extensions allow an application to place + elements on an HTML form and respond to user events such as mouse + clicks, form input, and page navigation. +
  • +
  • + Server-side JavaScript extends the core language by supplying + objects relevant to running JavaScript on a server. For example, + server-side extensions allow an application to communicate with a + database, provide continuity of information from one invocation to + another of the application, or perform file manipulations on a + server. +
  • +
+
+
+
+
What you should already know
+
+

This guide assumes you have the following basic background:

+ +
    +
  • + A general understanding of the Internet and the World Wide Web + (WWW). +
  • +
  • Good working knowledge of HyperText Markup Language (HTML).
  • +
  • + Some programming experience. If you are new to programming, try + one of the tutorials linked on the main page about JavaScript. +
  • +
+
+
+
+
JavaScript and Java
+
+

+ JavaScript and Java are similar in some ways but fundamentally + different in some others. The JavaScript language resembles Java but + does not have Java's static typing and strong type checking. + JavaScript follows most Java expression syntax, naming conventions + and basic control-flow constructs which was the reason why it was + renamed from LiveScript to JavaScript. +

+ +

+ In contrast to Java's compile-time system of classes built by + declarations, JavaScript supports a runtime system based on a small + number of data types representing numeric, Boolean, and string + values. JavaScript has a prototype-based object model instead of the + more common class-based object model. The prototype-based model + provides dynamic inheritance; that is, what is inherited can vary + for individual objects. JavaScript also supports functions without + any special declarative requirements. Functions can be properties of + objects, executing as loosely typed methods. +

+

+ JavaScript is a very free-form language compared to Java. You do not + have to declare all variables, classes, and methods. You do not have + to be concerned with whether methods are public, private, or + protected, and you do not have to implement interfaces. Variables, + parameters, and function return types are not explicitly typed. +

+
+
+
+
Hello world
+
+ To get started with writing JavaScript, open the Scratchpad and write + your first "Hello world" JavaScript code: + function greetMe(yourName) { alert("Hello " + yourName); } + greetMe("World"); + + + Select the code in the pad and hit Ctrl+R to watch it unfold in your + browser! +
+
+
+
Variables
+

+ You use variables as symbolic names for values in your application. + The names of variables, called identifiers, conform to certain rules. +

+

+ A JavaScript identifier must start with a letter, underscore (_), or + dollar sign ($); subsequent characters can also be digits (0-9). + Because JavaScript is case sensitive, letters include the characters + "A" through "Z" (uppercase) and the characters "a" through "z" + (lowercase). +

+

+ You can use ISO 8859-1 or Unicode letters such as å and ü in + identifiers. You can also use the Unicode escape sequences as + characters in identifiers. Some examples of legal names are + Number_hits, temp99, and _name. +

+
+
+
Declaring variables
+
+ You can declare a variable in three ways: +

+ With the keyword var. For example, var x = 42. This + syntax can be used to declare both local and global variables. +

+

+ By simply assigning it a value. For example, + x = 42. This always declares a global variable. It + generates a strict JavaScript warning. You shouldn't use this + variant. +

+

+ With the keyword let. For example, let y = 13. This + syntax can be used to declare a block scope local variable. See + Variable scope below. +

+
+
+
+
Variable scope
+
+

+ When you declare a variable outside of any function, it is called a + global variable, because it is available to any other code in the + current document. When you declare a variable within a function, it + is called a local variable, because it is available only within that + function. +

+ +

+ JavaScript before ECMAScript 2015 does not have block statement + scope; rather, a variable declared within a block is local to the + function (or global scope) that the block resides within. For + example the following code will log 5, because the scope of x is the + function (or global context) within which x is declared, not the + block, which in this case is an if statement. +

+ if (true) { var x = 5; } console.log(x); // 5 +

+ This behavior changes, when using the let declaration introduced in + ECMAScript 2015. +

+ + if (true) { let y = 5; } console.log(y); // ReferenceError: y is + not defined +
+
+
+
Global variables
+
+

+ Global variables are in fact properties of the global object. In web + pages the global object is window, so you can set and access global + variables using the window.variable syntax. +

+ +

+ Consequently, you can access global variables declared in one window + or frame from another window or frame by specifying the window or + frame name. For example, if a variable called phoneNumber is + declared in a document, you can refer to this variable from an + iframe as parent.phoneNumber. +

+
+
+
+
Constants
+
+

+ You can create a read-only, named constant with the const keyword. + The syntax of a constant identifier is the same as for a variable + identifier: it must start with a letter, underscore or dollar sign + and can contain alphabetic, numeric, or underscore characters. +

+ + const PI = 3.14; +

+ A constant cannot change value through assignment or be re-declared + while the script is running. It has to be initialized to a value. +

+ +

+ The scope rules for constants are the same as those for let block + scope variables. If the const keyword is omitted, the identifier is + assumed to represent a variable. +

+ +

+ You cannot declare a constant with the same name as a function or + variable in the same scope. For example: +

+ + // THIS WILL CAUSE AN ERROR function f() {}; const f = 5; // THIS + WILL CAUSE AN ERROR ALSO function f() { const g = 5; var g; + //statements } + However, object attributes are not protected, so the following + statement is executed without problems. + const MY_OBJECT = {"key": "value"}; MY_OBJECT.key = + "otherValue"; +
+
+
+
Data types
+
+

The latest ECMAScript standard defines seven data types:

+
    +
  • +

    Six data types that are primitives:

    +
      +
    • Boolean. true and false.
    • +
    • + null. A special keyword denoting a null value. Because + JavaScript is case-sensitive, null is not the same as Null, + NULL, or any other variant. +
    • +
    • + undefined. A top-level property whose value is undefined. +
    • +
    • Number. 42 or 3.14159.
    • +
    • String. "Howdy"
    • +
    • + Symbol (new in ECMAScript 2015). A data type whose instances + are unique and immutable. +
    • +
    +
  • + +
  • and Object
  • +
+ Although these data types are a relatively small amount, they enable + you to perform useful functions with your applications. Objects and + functions are the other fundamental elements in the language. You can + think of objects as named containers for values, and functions as + procedures that your application can perform. +
+
+
+
if...else statement
+
+ Use the if statement to execute a statement if a logical condition is + true. Use the optional else clause to execute a statement if the + condition is false. An if statement looks as follows: + + if (condition) { statement_1; } else { statement_2; } + condition can be any expression that evaluates to true or false. See + Boolean for an explanation of what evaluates to true and false. If + condition evaluates to true, statement_1 is executed; otherwise, + statement_2 is executed. statement_1 and statement_2 can be any + statement, including further nested if statements. +

+ You may also compound the statements using else if to have multiple + conditions tested in sequence, as follows: +

+ if (condition_1) { statement_1; } else if (condition_2) { + statement_2; } else if (condition_n) { statement_n; } else { + statement_last; } + + In the case of multiple conditions only the first logical condition + which evaluates to true will be executed. To execute multiple + statements, group them within a block statement ({ ... }) . In + general, it's good practice to always use block statements, especially + when nesting if statements: + + if (condition) { statement_1_runs_if_condition_is_true; + statement_2_runs_if_condition_is_true; } else { + statement_3_runs_if_condition_is_false; + statement_4_runs_if_condition_is_false; } + It is advisable to not use simple assignments in a conditional + expression, because the assignment can be confused with equality when + glancing over the code. For example, do not use the following code: + if (x = y) { /* statements here */ } If you need to use + an assignment in a conditional expression, a common practice is to put + additional parentheses around the assignment. For example: + + if ((x = y)) { /* statements here */ } +
+
+
+
while statement
+
+ A while statement executes its statements as long as a specified + condition evaluates to true. A while statement looks as follows: + + while (condition) statement If the condition becomes + false, statement within the loop stops executing and control passes to + the statement following the loop. + +

+ The condition test occurs before statement in the loop is executed. + If the condition returns true, statement is executed and the + condition is tested again. If the condition returns false, execution + stops and control is passed to the statement following while. +

+ +

+ To execute multiple statements, use a block statement ({ ... }) to + group those statements. +

+ + Example: + +

+ The following while loop iterates as long as n is less than three: +

+ + var n = 0; var x = 0; while (n < 3) { n++; x += n; } +

+ With each iteration, the loop increments n and adds that value to x. + Therefore, x and n take on the following values: +

+ +
    +
  • After the first pass: n = 1 and x = 1
  • +
  • After the second pass: n = 2 and x = 3
  • +
  • After the third pass: n = 3 and x = 6
  • +
+

+ After completing the third pass, the condition n < 3 is no longer + true, so the loop terminates. +

+
+
+
+
Function declarations
+
+ A function definition (also called a function declaration, or function + statement) consists of the function keyword, followed by: + +
    +
  • The name of the function.
  • +
  • + A list of arguments to the function, enclosed in parentheses and + separated by commas. +
  • +
  • + The JavaScript statements that define the function, enclosed in + curly brackets, { }. +
  • +
+

+ For example, the following code defines a simple function named + square: +

+ + function square(number) { return number * number; } +

+ The function square takes one argument, called number. The function + consists of one statement that says to return the argument of the + function (that is, number) multiplied by itself. The return + statement specifies the value returned by the function. +

+ return number * number; +

+ Primitive parameters (such as a number) are passed to functions by + value; the value is passed to the function, but if the function + changes the value of the parameter, this change is not reflected + globally or in the calling function. +

+
+
+
+
Reference
+
+
    +
  • + All the documentation in this page is taken from + MDN +
  • +
+
+
+
+ + +``` + +```css +html, +body { + min-width: 290px; + color: #4d4e53; + background-color: #ffffff; + font-family: 'Open Sans', Arial, sans-serif; + line-height: 1.5; +} + +#navbar { + position: fixed; + min-width: 290px; + top: 0px; + left: 0px; + width: 300px; + height: 100%; + border-right: solid; + border-color: rgba(0, 22, 22, 0.4); +} + +header { + color: black; + margin: 10px; + text-align: center; + font-size: 1.8em; + font-weight: thin; +} + +#main-doc header { + text-align: left; + margin: 0px; +} + +#navbar ul { + height: 88%; + padding: 0; + overflow-y: auto; + overflow-x: hidden; +} + +#navbar li { + color: #4d4e53; + border-top: 1px solid; + list-style: none; + position: relative; + width: 100%; +} + +#navbar a { + display: block; + padding: 10px 30px; + color: #4d4e53; + text-decoration: none; + cursor: pointer; +} + +#main-doc { + position: absolute; + margin-left: 310px; + padding: 20px; + margin-bottom: 110px; +} + +section article { + color: #4d4e53; + margin: 15px; + font-size: 0.96em; +} + +section li { + margin: 15px 0px 0px 20px; +} + +code { + display: block; + text-align: left; + white-space: pre-line; + position: relative; + word-break: normal; + word-wrap: normal; + line-height: 2; + background-color: #f7f7f7; + padding: 15px; + margin: 10px; + border-radius: 5px; +} + +@media only screen and (max-width: 815px) { + /* For mobile phones: */ + #navbar ul { + border: 1px solid; + height: 207px; + } + + #navbar { + background-color: white; + position: absolute; + top: 0; + padding: 0; + margin: 0; + width: 100%; + max-height: 275px; + border: none; + z-index: 1; + border-bottom: 2px solid; + } + + #main-doc { + position: relative; + margin-left: 0px; + margin-top: 270px; + } +} + +@media only screen and (max-width: 400px) { + #main-doc { + margin-left: -10px; + } + + code { + margin-left: -20px; + width: 100%; + padding: 15px; + padding-left: 10px; + padding-right: 45px; + min-width: 233px; + } +} +```