Skip to content

Commit

Permalink
Merge branch 'main' into events-inheritance
Browse files Browse the repository at this point in the history
  • Loading branch information
Elchi3 authored Dec 8, 2021
2 parents 8af8a86 + d205ffc commit 23a1d71
Show file tree
Hide file tree
Showing 211 changed files with 3,329 additions and 1,653 deletions.
2 changes: 1 addition & 1 deletion files/en-us/learn/forms/advanced_form_styling/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ As we've mentioned above a few times, if you want to gain full control over the
The following libraries aren't just about forms, but they have very interesting features for dealing with HTML forms:

- [jQuery UI](https://jqueryui.com/) offers customizable widgets such as date pickers (with special attention given to accessibility).
- [Twitter Bootstrap](https://twitter.github.com/bootstrap/base-css.html#forms) can help normalize your forms.
- [Bootstrap](https://getbootstrap.com/docs/5.1/forms/overview/) can help normalize your forms.
- [WebShim](https://afarkas.github.io/webshim/demos/) is a huge tool that can help you deal with browser HTML5 support. The web forms part can be really helpful.

Remember that CSS and JavaScript can have side effects. So if you choose to use one of those libraries, you should always have robust fallback HTML in case the script fails. There are many reasons why scripts may fail, especially in the mobile world, and you need to design your Web site or app to handle these cases as well as possible.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ To begin with, let's put together a basic function.
const html = document.querySelector('html');

const panel = document.createElement('div');
panel.setAttribute('class', 'msgBox');
panel.setAttribute('class','msgBox');
html.appendChild(panel);

const msg = document.createElement('p');
Expand All @@ -91,9 +91,7 @@ To begin with, let's put together a basic function.
closeBtn.textContent = 'x';
panel.appendChild(closeBtn);

closeBtn.onclick = function() {
panel.parentNode.removeChild(panel);
}
closeBtn.addEventListener('click', () => panel.parentNode.removeChild(panel));
```

This is quite a lot of code to go through, so we'll walk you through it bit by bit.
Expand Down Expand Up @@ -128,14 +126,12 @@ closeBtn.textContent = 'x';
panel.appendChild(closeBtn);
```
Finally, we use an {{domxref("GlobalEventHandlers.onclick")}} event handler to make it so that when the button is clicked, some code is run to delete the whole panel from the page — to close the message box.
Finally, we call {{domxref("EventTarget/addEventListener", "addEventListener()")}} to add a function that will be called when the user clicks the "close" button. The code will delete the whole panel from the page — to close the message box.
Briefly, the `onclick` handler is a property available on the button (or in fact, any element on the page) that can be set to a function to specify what code to run when the button is clicked. You'll learn a lot more about these in our later [events article](/en-US/docs/Learn/JavaScript/Building_blocks/Events). We are making the `onclick` handler equal to an anonymous function, which contains the code to run when the button is clicked. The line inside the function uses the {{domxref("Node.removeChild()")}} DOM API function to specify that we want to remove a specific child element of the HTML element — in this case the panel `<div>`.
Briefly, the `addEventListener()` method is provided by the button (or in fact, any element on the page) that can be passed a function and the name of an event. In this case the name of the event is 'click', meaning that when the user clicks the button, the function will be run. You'll learn a lot more about events in our [events article](/en-US/docs/Learn/JavaScript/Building_blocks/Events). The line inside the function uses the {{domxref("Node.removeChild()")}} DOM API function to specify that we want to remove a specific child element of the HTML element — in this case the panel `<div>`.

```js
closeBtn.onclick = function() {
panel.parentNode.removeChild(panel);
}
closeBtn.addEventListener('click', () => panel.parentNode.removeChild(panel));
```

Basically, this whole block of code is generating a block of HTML that looks like so, and inserting it into the page:
Expand Down Expand Up @@ -177,10 +173,10 @@ You've now got your function definition written into your `<script>` element jus
5. Finally, add the following line below the previous one:

```js
btn.onclick = displayMessage;
btn.addEventListener('click', displayMessage);
```

In a similar way to our `closeBtn.onclick...` line inside the function, here we are calling some code in response to a button being clicked. But in this case, instead of calling an anonymous function containing some code, we are calling our function name directly.
In a similar way to our `closeBtn.addEventListener...` line inside the function, here we are calling some code in response to a button being clicked. But in this case, instead of calling an anonymous function containing some code, we are calling our `displayMessage()` function by name.

6. Try saving and refreshing the page — now you should see the message box appear when you click the button.

Expand Down Expand Up @@ -227,15 +223,13 @@ As it stands, the function is still not very useful — we don't want to just sh
3. Last but not least, you now need to update your function call to include some updated message text. Change the following line:
```js
btn.onclick = displayMessage;
btn.addEventListener('click', displayMessage);
```
to this block:
```js
btn.onclick = function() {
displayMessage('Woo, this is a different message!');
};
btn.addEventListener('click', () => displayMessage('Woo, this is a different message!'));
```
If we want to specify parameters inside parentheses for the function we are calling, then we can't call it directly — we need to put it inside an anonymous function so that it isn't in the immediate scope and therefore isn't called immediately. Now it will not be called until the button is clicked.
Expand Down
83 changes: 69 additions & 14 deletions files/en-us/learn/javascript/building_blocks/conditionals/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,9 @@ It is perfectly OK to put one `if...else` statement inside another one — to ne
```js
if (choice === 'sunny') {
if (temperature < 86) {
para.textContent = 'It is ' + temperature + ' degrees outside — nice and sunny. Let\'s go out to the beach, or the park, and get an ice cream.';
para.textContent = `It is ${temperature} degrees outside — nice and sunny. Let\'s go out to the beach, or the park, and get an ice cream.`;
} else if (temperature >= 86) {
para.textContent = 'It is ' + temperature + ' degrees outside — REALLY HOT! If you want to go outside, make sure to put some sunscreen on.';
para.textContent = `It is ${temperature} degrees outside — REALLY HOT! If you want to go outside, make sure to put some sunscreen on.`;
}
}
```
Expand All @@ -218,9 +218,9 @@ To give you an AND example, the previous example snippet can be rewritten to thi

```js
if (choice === 'sunny' && temperature < 86) {
para.textContent = 'It is ' + temperature + ' degrees outside — nice and sunny. Let\'s go out to the beach, or the park, and get an ice cream.';
para.textContent = `It is ${temperature} degrees outside — nice and sunny. Let\'s go out to the beach, or the park, and get an ice cream.`;
} else if (choice === 'sunny' && temperature >= 86) {
para.textContent = 'It is ' + temperature + ' degrees outside — REALLY HOT! If you want to go outside, make sure to put some sunscreen on.';
para.textContent = `It is ${temperature} degrees outside — REALLY HOT! If you want to go outside, make sure to put some sunscreen on.`;
}
```

Expand Down Expand Up @@ -392,9 +392,7 @@ function update(bgColor, textColor) {
html.style.color = textColor;
}

select.onchange = function() {
( select.value === 'black' ) ? update('black','white') : update('white','black');
}
select.addEventListener('change', () => ( select.value === 'black' ) ? update('black','white') : update('white','black'));
```

{{ EmbedLiveSample('Ternary_operator_example', '100%', 300, "", "") }}
Expand Down Expand Up @@ -457,13 +455,13 @@ const select = document.querySelector('select');
const list = document.querySelector('ul');
const h1 = document.querySelector('h1');

select.onchange = function() {
select.addEventListener('change', () => {
const choice = select.value;

// ADD CONDITIONAL HERE

createCalendar(days, choice);
}
});

function createCalendar(days, choice) {
list.innerHTML = '';
Expand Down Expand Up @@ -555,7 +553,35 @@ solution.addEventListener('click', function() {
updateCode();
});

const jsSolution = 'const select = document.querySelector(\'select\');\nconst list = document.querySelector(\'ul\');\nconst h1 = document.querySelector(\'h1\');\n\nselect.onchange = function() {\n const choice = select.value;\n let days = 31;\n if(choice === \'February\') {\n days = 28;\n } else if(choice === \'April\' || choice === \'June\' || choice === \'September\'|| choice === \'November\') {\n days = 30;\n }\n\n createCalendar(days, choice);\n}\n\nfunction createCalendar(days, choice) {\n list.innerHTML = \'\';\n h1.textContent = choice;\n for(let i = 1; i <= days; i++) {\n const listItem = document.createElement(\'li\');\n listItem.textContent = i;\n list.appendChild(listItem);\n }\n }\n\ncreateCalendar(31,\'January\');';
const jsSolution = `const select = document.querySelector('select');
const list = document.querySelector('ul');
const h1 = document.querySelector('h1');
select.addEventListener('change', () => {
const choice = select.value;
let days = 31;
if (choice === 'February') {
days = 28;
} else if (choice === 'April' || choice === 'June' || choice === 'September'|| choice === 'November') {
days = 30;
}
createCalendar(days, choice);
});
function createCalendar(days, choice) {
list.innerHTML = '';
h1.textContent = choice;
for (let i = 1; i <= days; i++) {
const listItem = document.createElement('li');
listItem.textContent = i;
list.appendChild(listItem);
}
}
createCalendar(31,'January');`

let solutionEntry = jsSolution;

textarea.addEventListener('input', updateCode);
Expand Down Expand Up @@ -638,11 +664,11 @@ If you make a mistake, you can always reset the example with the "Reset" button.
const select = document.querySelector('select');
const html = document.querySelector('.output');

select.onchange = function() {
select.addEventListener('change', () => {
const choice = select.value;

// ADD SWITCH STATEMENT
}
// ADD CONDITIONAL HERE
});

function update(bgColor, textColor) {
html.style.backgroundColor = bgColor;
Expand Down Expand Up @@ -707,7 +733,36 @@ solution.addEventListener('click', function() {
updateCode();
});

const jsSolution = 'const select = document.querySelector(\'select\');\nconst html = document.querySelector(\'.output\');\n\nselect.onchange = function() {\n const choice = select.value;\n\n switch(choice) {\n case \'black\':\n update(\'black\',\'white\');\n break;\n case \'white\':\n update(\'white\',\'black\');\n break;\n case \'purple\':\n update(\'purple\',\'white\');\n break;\n case \'yellow\':\n update(\'yellow\',\'darkgray\');\n break;\n case \'psychedelic\':\n update(\'lime\',\'purple\');\n break;\n }\n}\n\nfunction update(bgColor, textColor) {\n html.style.backgroundColor = bgColor;\n html.style.color = textColor;\n}';
const jsSolution = `const select = document.querySelector('select');
const html = document.querySelector('.output');
select.addEventListener('change', () => {
const choice = select.value;
switch(choice) {
case 'black':
update('black','white');
break;
case 'white':
update('white','black');
break;
case 'purple':
update('purple','white');
break;
case 'yellow':
update('yellow','darkgray');
break;
case 'psychedelic':
update('lime','purple');
break;
}
});
function update(bgColor, textColor) {
html.style.backgroundColor = bgColor;
html.style.color = textColor;
}`;

let solutionEntry = jsSolution;

textarea.addEventListener('input', updateCode);
Expand Down
8 changes: 4 additions & 4 deletions files/en-us/learn/javascript/building_blocks/events/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -429,18 +429,18 @@ const fname = document.getElementById('fname');
const lname = document.getElementById('lname');
const para = document.querySelector('p');

form.onsubmit = function(e) {
form.addEventListener('submit', e => {
if (fname.value === '' || lname.value === '') {
e.preventDefault();
para.textContent = 'You need to fill in both names!';
}
}
});
```

Obviously, this is pretty weak form validation — it wouldn't stop the user validating the form with spaces or numbers entered into the fields, for example — but it is OK for example purposes.
The output is as follows:

{{ EmbedLiveSample('Preventing_default_behavior', '100%', 140, "", "") }}
{{ EmbedLiveSample('Preventing_default_behavior', '100%', 180, "", "") }}

> **Note:** for the full source code, see [preventdefault-validation.html](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/preventdefault-validation.html) (also see it [running live](https://mdn.github.io/learning-area/javascript/building-blocks/events/preventdefault-validation.html) here.)
Expand Down Expand Up @@ -558,7 +558,7 @@ const btn = document.querySelector('button');
const videoBox = document.querySelector('div');

function displayVideo() {
if(videoBox.getAttribute('class') === 'hidden') {
if (videoBox.getAttribute('class') === 'hidden') {
videoBox.setAttribute('class','showing');
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,34 +73,39 @@ The most interesting parts of the example's CSS file:

Your JavaScript needs to:

- Loop through all the images, and for each one insert an `<img>` element inside the `thumb-bar <div>` that embeds that image in the page.
- Attach an `onclick` handler to each `<img>` inside the `thumb-bar <div>` so that when they are clicked, the corresponding image is displayed in the `displayed-img <img>` element.
- Attach an `onclick` handler to the `<button>` so that when it is clicked, a darken effect is applied to the full-size image. When it is clicked again, the darken effect is removed again.
- Declare a `const` array listing the filenames of each image, such as `'pic1.jpg'`.
- Loop through the array of filenames, and for each one insert an `<img>` element inside the `thumb-bar <div>` that embeds that image in the page.
- Add a click event listener to each `<img>` inside the `thumb-bar <div>` so that when they are clicked, the corresponding image is displayed in the `displayed-img <img>` element.
- Add a click event listener to the `<button>` so that when it is clicked, a darken effect is applied to the full-size image. When it is clicked again, the darken effect is removed again.

To give you more of an idea, have a look at the [finished example](https://mdn.github.io/learning-area/javascript/building-blocks/gallery/) (no peeking at the source code!)

## Steps to complete

The following sections describe what you need to do.

## Declare an array of image filenames

You need to create an array listing the filenames of all the image to include in the gallery. The array should be declared as a constant.

### Looping through the images

We've already provided you with lines that store a reference to the `thumb-bar <div>` inside a constant called `thumbBar`, create a new `<img>` element, set its `src` attribute to a placeholder value `xxx`, and append this new `<img>` element inside `thumbBar`.

You need to:

1. Put the section of code below the "Looping through images" comment inside a loop that loops through all 5 images — you just need to loop through five numbers, one representing each image.
1. Put the section of code below the "Looping through images" comment inside a loop that loops through all the filenames in the array.
2. In each loop iteration, replace the `xxx` placeholder value with a string that will equal the path to the image in each case. We are setting the value of the `src` attribute to this value in each case. Bear in mind that in each case, the image is inside the images directory and its name is `pic1.jpg`, `pic2.jpg`, etc.

### Adding an onclick handler to each thumbnail image
### Adding a click event listener to each thumbnail image

In each loop iteration, you need to add an `onclick` handler to the current `newImage` — this handler should find the value of the `src` attribute of the current image. Set the `src` attribute value of the `displayed-img <img>` to the `src` value passed in as a parameter.
In each loop iteration, you need to add a click event listener to the current `newImage` — this listener should find the value of the `src` attribute of the current image. Set the `src` attribute value of the `displayed-img <img>` to the `src` value passed in as a parameter.

Alternatively, you can add one event listener to the thumb bar.

### Writing a handler that runs the darken/lighten button

That just leaves our darken/lighten `<button>` — we've already provided a line that stores a reference to the `<button>` in a constant called `btn`. You need to add an `onclick` handler that:
That just leaves our darken/lighten `<button>` — we've already provided a line that stores a reference to the `<button>` in a constant called `btn`. You need to add a click event listener that:

1. Checks the current class name set on the `<button>` — you can again achieve this by using `getAttribute()`.
2. If the class name is `"dark"`, changes the `<button>` class to `"light"` (using [`setAttribute()`](/en-US/docs/Web/API/Element/setAttribute)), its text content to "Lighten", and the {{cssxref("background-color")}} of the overlay `<div>` to `"rgba(0,0,0,0.5)"`.
Expand Down
29 changes: 24 additions & 5 deletions files/en-us/learn/javascript/building_blocks/looping_code/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ const para = document.querySelector('p');
const input = document.querySelector('input');
const btn = document.querySelector('button');

btn.addEventListener('click', function() {
btn.addEventListener('click', () => {
const searchName = input.value.toLowerCase();
input.value = '';
input.focus();
Expand Down Expand Up @@ -455,17 +455,17 @@ const para = document.querySelector('p');
const input = document.querySelector('input');
const btn = document.querySelector('button');

btn.addEventListener('click', function() {
btn.addEventListener('click', () => {
para.textContent = 'Output: ';
let num = input.value;
const num = input.value;
input.value = '';
input.focus();
for (let i = 1; i <= num; i++) {
let sqRoot = Math.sqrt(i);
if (Math.floor(sqRoot) !== sqRoot) {
continue;
}
para.textContent += i + ' ';
para.textContent += `${i} `;
}
});
```
Expand Down Expand Up @@ -668,7 +668,26 @@ solution.addEventListener('click', function() {
updateCode();
});

let jsSolution = 'const output = document.querySelector(\'.output\');\noutput.innerHTML = \'\';\n\nlet i = 10;\n\nwhile(i >= 0) {\n let para = document.createElement(\'p\');\n if(i === 10) {\n para.textContent = \'Countdown \' + i;\n } else if(i === 0) {\n para.textContent = \'Blast off!\';\n } else {\n para.textContent = i;\n }\n\n output.appendChild(para);\n\n i--;\n}';
let jsSolution = `const output = document.querySelector('.output');
output.innerHTML = '';
let i = 10;
while (i >= 0) {
const para = document.createElement('p');
if (i === 10) {
para.textContent = \`Countdown \$\{i}\`;
} else if (i === 0) {
para.textContent = 'Blast off!';
} else {
para.textContent = i;
}
output.appendChild(para);
i--;
}`;

let solutionEntry = jsSolution;

textarea.addEventListener('input', updateCode);
Expand Down
Loading

0 comments on commit 23a1d71

Please sign in to comment.