Skip to content
Snippets Groups Projects
Commit 581d4ec7 authored by Lun's avatar Lun
Browse files

Edit the exercise descriptions based on Antti's suggestions

parent 65887f08
Branches
No related tags found
No related merge requests found
/* global module, require, console */ /* global module, require, console */
/* jshint globalstrict: true */ /* jshint globalstrict: true */
'use strict'; "use strict";
let Content = { let Content = {
click_for_points: { click_for_points: {
instructions: "This is an example of how automatically graded assignments appear in this course. Always <strong>carefully read assignment instructions</strong> before starting to do anything. At this time, there is no problem to solve. You are only expected to click the button on left to receive your first points.", instructions:
html: "<button class=\"green\">Click Me!</button>", "This is an example of how automatically graded assignments appear in this course. Always <strong>carefully read assignment instructions</strong> before starting to do anything. At this time, there is no problem to solve. You are only expected to click the button on left to receive your first points.",
html: '<button class="green">Click Me!</button>',
selector: ".exercise button", selector: ".exercise button",
events: "click", events: "click",
points: function ($element, config, event) { points: function ($element, config, event) {
return { return {
points: 10, points: 10,
feedback: 'Congratulations!' feedback: "Congratulations!",
}; };
}, },
maxPoints: 10, maxPoints: 10,
title: "Click for points", title: "Click for points",
description: "An example of how these assignments work.", description: "An example of how these assignments work.",
concepts: ["Automatic assessment"], concepts: ["Automatic assessment"],
order: 0 order: 0,
}, },
fix_typo: { fix_typo: {
instructions: "On the left, you see a message that unfortunately contains a typo. Your task is to open the browser inspector tool, find the paragraph element <strong>&lt;p&gt;</strong> containing the message and then edit the element body correctly to contain the intended message \"<strong>Hello World!</strong>\".", instructions:
html: "<div class=\"acos-webdev-poi\"><p>Hello Wordl!</p></div>", 'On the left, you see a message that unfortunately contains a typo. Your task is to open the browser inspector tool, find the paragraph element <strong>&lt;p&gt;</strong> containing the message and then edit the element body correctly to contain the intended message "<strong>Hello World!</strong>".',
html: '<div class="acos-webdev-poi"><p>Hello Wordl!</p></div>',
mutations: true, mutations: true,
points: function ($element, config, mutations) { points: function ($element, config, mutations) {
let $p = $element.find('.exercise p'); let $p = $element.find(".exercise p");
if ($p.length != 1) { if ($p.length != 1) {
return { return {
points: 0, points: 0,
feedback: 'The document is altered beyond repair. Avoid accidentally removing nodes. You should reset the assignment to start over.' feedback:
"The document is altered beyond repair. Avoid accidentally removing nodes. You should reset the assignment to start over.",
}; };
} else if ($p.eq(0).text() != 'Hello Wordl!') { } else if ($p.eq(0).text() != "Hello Wordl!") {
if ($p.eq(0).text() != 'Hello World!') { if ($p.eq(0).text() != "Hello World!") {
return { return {
points: 5, points: 5,
feedback: 'Almost there! You were able to change the node contents, but the message is not exactly as requested.' feedback:
"Almost there! You were able to change the node contents, but the message is not exactly as requested.",
}; };
} else { } else {
return { return {
points: 10, points: 10,
feedback: 'Great work! You were able to change the node contents as requested.' feedback:
"Great work! You were able to change the node contents as requested.",
}; };
} }
} }
...@@ -52,25 +56,30 @@ let Content = { ...@@ -52,25 +56,30 @@ let Content = {
title: "Fix typo", title: "Fix typo",
description: "Find and change element body", description: "Find and change element body",
concepts: ["Inspector", "DOM", "HTML"], concepts: ["Inspector", "DOM", "HTML"],
order: 1 order: 1,
}, },
change_color: { change_color: {
instructions: "The blue area on left contains barely visible text. Your task is to use the browser inspector tool and locate the paragraph element <strong>&lt;p&gt;</strong> containing the barely visible text and then add a CSS property to apply another <strong>color</strong>. <em>Note that editing existing CSS rules does not grade the exercise.</em>", instructions:
html: "<div class=\"acos-webdev-poi blue\" style=\"max-width: 280px;\"><p>The quick brown fox jumps over the lazy dog's back.</p></div>", "The blue area on left contains barely visible text. Your task is to use the browser inspector tool and locate the paragraph element <strong>&lt;p&gt;</strong> containing the barely visible text and then add a CSS property to apply another <strong>color</strong>. <em>Note that editing existing CSS rules does not grade the exercise.</em>",
html: '<div class="acos-webdev-poi blue" style="max-width: 280px;"><p>The quick brown fox jumps over the lazy dog\'s back.</p></div>',
mutations: true, mutations: true,
points: function ($element, config, mutations) { points: function ($element, config, mutations) {
let $p = $element.find('.exercise p'); let $p = $element.find(".exercise p");
if ($p.length != 1) { if ($p.length != 1) {
return { return {
points: 0, points: 0,
feedback: 'The document is altered beyond repair. Avoid accidentally removing nodes. You should reset the assignment to start over.' feedback:
"The document is altered beyond repair. Avoid accidentally removing nodes. You should reset the assignment to start over.",
}; };
} else if (!config.graded && $p.eq(0).css('color') != 'rgb(173, 216, 230)') { } else if (
!config.graded &&
$p.eq(0).css("color") != "rgb(173, 216, 230)"
) {
config.graded = true; config.graded = true;
return { return {
points: 10, points: 10,
feedback: 'Excellent! You changed the color of the text.' feedback: "Excellent! You changed the color of the text.",
}; };
} }
return undefined; return undefined;
...@@ -79,41 +88,43 @@ let Content = { ...@@ -79,41 +88,43 @@ let Content = {
title: "Change text color", title: "Change text color",
description: "Find and change text color using CSS", description: "Find and change text color using CSS",
concepts: ["Inspector", "DOM", "CSS"], concepts: ["Inspector", "DOM", "CSS"],
order: 2 order: 2,
}, },
disabled_button: { disabled_button: {
instructions: "You need to click the button on the left to receive your points from this assigment. Too bad that the button is disabled. Your task is to use the browser inspector tool to locate the <strong>button</strong>, remove the <strong>disabled</strong> attribute and finally click it.", instructions:
html: "<button class=\"green\" disabled>Click Me!</button>", "You need to click the button on the left to receive your points from this assigment. Too bad that the button is disabled. Your task is to use the browser inspector tool to locate the <strong>button</strong>, remove the <strong>disabled</strong> attribute and finally click it.",
html: '<button class="green" disabled>Click Me!</button>',
selector: ".exercise button", selector: ".exercise button",
events: "click", events: "click",
points: function ($element, config, event) { points: function ($element, config, event) {
return { return {
points: 10, points: 10,
feedback: 'Congratulations!' feedback: "Congratulations!",
}; };
}, },
maxPoints: 10, maxPoints: 10,
title: "Disabled button", title: "Disabled button",
description: "Find and enable button", description: "Find and enable button",
concepts: ["Inspector", "DOM", "HTML"], concepts: ["Inspector", "DOM", "HTML"],
order: 3 order: 3,
}, },
console_command: { console_command: {
instructions: "This time the area on the left does not have any visible content. However, this exercise defines a JavaScript function that can grant you points. Your task is to use the browser console to call the function like this: <code>giveMePoints();</code>", instructions:
html: "<div id=\"events\"><p>First, make sure that your browser <em>console</em> is open and it has the <em>top</em> JavaScript context selected (dropdown selection in Chrome). Then, type in the command given in instruction.</p></div>", "This time the area on the left does not have any visible content. However, this exercise defines a JavaScript function that can grant you points. Your task is to use the browser console to call the function like this: <code>giveMePoints();</code>",
html: '<div id="events"><p>First, make sure that your browser <em>console</em> is open and it has the <em>top</em> JavaScript context selected (dropdown selection in Chrome). Then, type in the command given in instruction.</p></div>',
script: function giveMePoints() { script: function giveMePoints() {
window.postMessage('grade'); window.postMessage("grade");
return 'Granting points my lord!'; return "Granting points my lord!";
}, },
selector: "$window", selector: "$window",
events: "message", events: "message",
points: function ($element, config, event) { points: function ($element, config, event) {
if (event.originalEvent.data == 'grade') { if (event.originalEvent.data == "grade") {
return { return {
points: 10, points: 10,
feedback: 'Congratulations!' feedback: "Congratulations!",
}; };
} }
return undefined; return undefined;
...@@ -122,14 +133,16 @@ let Content = { ...@@ -122,14 +133,16 @@ let Content = {
title: "Console command", title: "Console command",
description: "Call function in browser console", description: "Call function in browser console",
concepts: ["Console", "JavaScript"], concepts: ["Console", "JavaScript"],
order: 4 order: 4,
}, },
readonly_attribute: { readonly_attribute: {
instructions: "First try to fill the form on the left. One of the inputs does not allow you to enter anything in it. Using the browser developer tools, inspect the <em>&lt;input&gt;</em> element which has the <em>readonly</em> attribute set. Remove the attribute and try filling the <em>&lt;input&gt;</em>. You can also submit the form.", instructions:
"First try to fill the form on the left. One of the inputs does not allow you to enter anything in it. Using the browser developer tools, inspect the <em>&lt;input&gt;</em> element which has the <em>readonly</em> attribute set. Remove the attribute and try filling the <em>&lt;input&gt;</em>. You can also submit the form.",
script: function formSubmitted(e) { script: function formSubmitted(e) {
e.preventDefault(); e.preventDefault();
document.getElementById('form-submitted').innerHTML = "Thank you for submitting this form! :)"; document.getElementById("form-submitted").innerHTML =
"Thank you for submitting this form! :)";
}, },
selector: "$document", selector: "$document",
html: ` html: `
...@@ -162,18 +175,19 @@ let Content = { ...@@ -162,18 +175,19 @@ let Content = {
</div>`, </div>`,
mutations: true, mutations: true,
points: function ($element, config, event) { points: function ($element, config, event) {
let $email = $element.find('#form-age-field'); let $email = $element.find("#form-age-field");
let $inputs = $element.find('#readonly-attribute input') let $inputs = $element.find("#readonly-attribute input");
if ($email.length == 0 || $inputs.length < 3) { if ($email.length == 0 || $inputs.length < 3) {
return { return {
points: 0, points: 0,
feedback: 'The document is altered beyond repair. Avoid accidentally removing nodes or ids. You should reset the assignment to start over.' feedback:
"The document is altered beyond repair. Avoid accidentally removing nodes or ids. You should reset the assignment to start over.",
}; };
} else if(!config.graded && $email['0'].readOnly === false) { } else if (!config.graded && $email["0"].readOnly === false) {
config.graded = true; config.graded = true;
return { return {
points: 10, points: 10,
feedback: 'Congratulations!' feedback: "Congratulations!",
}; };
return undefined; return undefined;
} }
...@@ -182,11 +196,12 @@ let Content = { ...@@ -182,11 +196,12 @@ let Content = {
title: "Disable readonly attribute", title: "Disable readonly attribute",
description: "Find and disable the readonly attribute", description: "Find and disable the readonly attribute",
concepts: ["Inspector", "DOM", "CSS", "readonly"], concepts: ["Inspector", "DOM", "CSS", "readonly"],
order: 5 order: 5,
}, },
modify_list: { modify_list: {
instructions: "A malicious hacker has managed to break into our database and has modified our perfect pizza recipe, now the pizza does no long taste as before :'(. Please, help us find and remove (delete the element) the malicious ingredient.", instructions:
"A malicious hacker has managed to break into our database and has modified our perfect pizza recipe, now the pizza does no long taste as before :'(. Please, help us find and remove (delete the element) the malicious ingredient. Hint: right click on the element in the inspector and select the correct option.",
selector: "$document", selector: "$document",
html: ` html: `
<style> <style>
...@@ -217,46 +232,55 @@ let Content = { ...@@ -217,46 +232,55 @@ let Content = {
mutations: true, mutations: true,
script: function getToppingIds(ul) { script: function getToppingIds(ul) {
let toppingIds = []; let toppingIds = [];
Object.keys(ul).forEach(k => { Object.keys(ul).forEach((k) => {
if (!isNaN(k)) { if (!isNaN(k)) {
toppingIds.push(ul[k].id); toppingIds.push(ul[k].id);
}; }
}); });
return toppingIds; return toppingIds;
}, },
points: function ($element, config, event) { points: function ($element, config, event) {
let $ol = $element.find('#pizza-ol li'); let $ol = $element.find("#pizza-ol li");
let $ul = $element.find('#pizza-ul li'); let $ul = $element.find("#pizza-ul li");
let toppings = ["tomato", "mozzarella", "olive-oil", "pineapple", "basil"]; let toppings = [
"tomato",
"mozzarella",
"olive-oil",
"pineapple",
"basil",
];
if ($ol.length < 4) { if ($ol.length < 4) {
return { return {
points: 0, points: 0,
feedback: 'The dough should be fine as it is, we think that the problem might be in some nasty topping... Reset to try again' feedback:
"The dough should be fine as it is, we think that the problem might be in some nasty topping... Reset to try again",
}; };
} }
if ($ul.length < 4) { if ($ul.length < 4) {
return { return {
points: 0, points: 0,
feedback: "Yes you are right, a good pizza does not need many toppings, but we can't remove so many, otherwise we will be still hungry after dinner... Reset to try again" feedback:
"Yes you are right, a good pizza does not need many toppings, but we can't remove so many, otherwise we will be still hungry after dinner... Reset to try again",
}; };
} }
if ($ul.length === 4) { if ($ul.length === 4) {
let wrongTopping = false; let wrongTopping = false;
let toppingIds = getToppingIds($ul); let toppingIds = getToppingIds($ul);
toppings.forEach(topping => { toppings.forEach((topping) => {
let toppingMissing = !toppingIds.some(id => id === topping); let toppingMissing = !toppingIds.some((id) => id === topping);
let wrongMissing = (topping !== "pineapple" && toppingMissing); let wrongMissing = topping !== "pineapple" && toppingMissing;
wrongTopping = wrongMissing ? topping : wrongTopping; wrongTopping = wrongMissing ? topping : wrongTopping;
}); });
if (wrongTopping) { if (wrongTopping) {
return { return {
points: 0, points: 0,
feedback: `Are you sure? Please try again, we have used ${wrongTopping} for ages and it is a good topping... Reset to try again` feedback: `Are you sure? Please try again, we have used ${wrongTopping} for ages and it is a good topping... Reset to try again`,
}; };
} else { } else {
return { return {
points: 10, points: 10,
feedback: 'Thank you! Pineapple does not really belong on a pizza! What kind of evil hacker could do that to us?' feedback:
"Thank you! Pineapple does not really belong on a pizza! What kind of evil hacker could do that to us?",
}; };
} }
} }
...@@ -264,30 +288,32 @@ let Content = { ...@@ -264,30 +288,32 @@ let Content = {
}, },
maxPoints: 10, maxPoints: 10,
title: "Remove the right element from the list", title: "Remove the right element from the list",
description: "Find and remove the element which does not belong in the list", description:
"Find and remove the element which does not belong in the list",
concepts: ["Inspector", "DOM", "CSS", "list"], concepts: ["Inspector", "DOM", "CSS", "list"],
order: 6 order: 6,
}, },
radio_points: { radio_points: {
instructions: "Select the amount of points you would like to have and whether you will be awarded points. You might need to remove a <em>disabled</em> for the desired point amount.", instructions:
html: "<div id=\"radio-inputs\"><form method=\"post\" action=\"#\" id=\"award-points-form\">Award points?<br>No <input type=\"radio\" name=\"give-points\" value=\"no\"><br>Yes <input type=\"radio\" name=\"give-points\" value=\"yes\"><br><hr>How many points?<br>No Points <input type=\"radio\" name=\"point-amount\" value=\"0\" checked=\"\"><br>Half points <input type=\"radio\" name=\"point-amount\" value=\"5\"><br>Full Points <input type=\"radio\" name=\"point-amount\" value=\"10\" disabled=\"\"><br><input type=\"submit\" id=\"award-points\" value=\"Award Points\"></form></div>", "Select the amount of points you would like to have and whether you will be awarded points. You might need to remove a <em>disabled</em> for the desired point amount.",
html: '<div id="radio-inputs"><form method="post" action="#" id="award-points-form">Award points?<br>No <input type="radio" name="give-points" value="no"><br>Yes <input type="radio" name="give-points" value="yes"><br><hr>How many points?<br>No Points <input type="radio" name="point-amount" value="0" checked=""><br>Half points <input type="radio" name="point-amount" value="5"><br>Full Points <input type="radio" name="point-amount" value="10" disabled=""><br><input type="submit" id="award-points" value="Award Points"></form></div>',
selector: "#award-points-form", selector: "#award-points-form",
events: "submit", events: "submit",
points: function ($element, config, event) { points: function ($element, config, event) {
const form = document.getElementById('award-points-form'); const form = document.getElementById("award-points-form");
const givePoints = form.elements['give-points'].value; const givePoints = form.elements["give-points"].value;
const pointAmount = parseInt(form.elements['point-amount'].value); const pointAmount = parseInt(form.elements["point-amount"].value);
event.preventDefault(); event.preventDefault();
if(givePoints === 'yes') { if (givePoints === "yes") {
return { return {
points: pointAmount, points: pointAmount,
feedback: 'Congratulations! You got ' + pointAmount + ' points.' feedback: "Congratulations! You got " + pointAmount + " points.",
}; };
} else { } else {
return { return {
points: 0, points: 0,
feedback: 'You selected not to have points.' feedback: "You selected not to have points.",
}; };
} }
}, },
...@@ -295,10 +321,11 @@ let Content = { ...@@ -295,10 +321,11 @@ let Content = {
title: "Radio Points", title: "Radio Points",
description: "Points for selecting correct radio inputs", description: "Points for selecting correct radio inputs",
concepts: ["HTML", "Input", "radio", "disabled", "checked"], concepts: ["HTML", "Input", "radio", "disabled", "checked"],
order: 7 order: 7,
}, },
change_border_color: { change_border_color: {
instructions: "This looks quite horrible, please change the border color and the background color of the element on the left. You can use any value you prefer. In order to get the points you will have to use the developer tools console, and change the color in the <em>element</em> selector. Also remember that the values you use should be valid ones.", instructions:
"This looks quite horrible, please change the border color and the background color of the element on the left. You can use any value you prefer. In order to get the points you will have to use the developer tools console, and change the color in the <em>element</em> selector. Also remember that the values you use should be valid ones.",
html: ` html: `
<style> <style>
div#color-element { div#color-element {
...@@ -320,59 +347,66 @@ let Content = { ...@@ -320,59 +347,66 @@ let Content = {
selector: "#color-form", selector: "#color-form",
events: "submit", events: "submit",
points: function ($element, config, event) { points: function ($element, config, event) {
let borderColor = document.getElementById('color-element').style.borderColor; let borderColor =
let backgroundColor = document.getElementById('color-element').style.backgroundColor; document.getElementById("color-element").style.borderColor;
let backgroundColor =
document.getElementById("color-element").style.backgroundColor;
let pointAmount = 10; let pointAmount = 10;
event.preventDefault(); event.preventDefault();
let colorsChanged = (borderColor !== "rgb(47, 252, 252)" && backgroundColor !== "rgb(252, 47, 252)"); let colorsChanged =
let colorsDefined = (borderColor.length > 0 && backgroundColor.length > 0) borderColor !== "rgb(47, 252, 252)" &&
backgroundColor !== "rgb(252, 47, 252)";
let colorsDefined = borderColor.length > 0 && backgroundColor.length > 0;
if(colorsChanged && colorsDefined) { if (colorsChanged && colorsDefined) {
document.getElementById('color-element').innerHTML = "Thank you, that's much better!" document.getElementById("color-element").innerHTML =
"Thank you, that's much better!";
return { return {
points: pointAmount, points: pointAmount,
feedback: 'Congratulations, nice colors! You got ' + pointAmount + ' points.' feedback:
"Congratulations, nice colors! You got " + pointAmount + " points.",
}; };
} else { } else {
return { return {
points: 0, points: 0,
feedback: 'You have to change both the border color and background color with any valid value of your choice.' feedback:
"You have to change both the border color and background color with any valid value of your choice.",
}; };
} }
}, },
maxPoints: 10, maxPoints: 10,
title: "Change border color", title: "Change border color",
description: "Points for changing the border color to the right value", description: "Points for changing the border color to the right value",
concepts: ["HTML", "Input", "CSS", "color"], concepts: ["HTML", "Input", "CSS", "color"],
order: 8 order: 8,
}, },
css_checked_pseudo: { css_checked_pseudo: {
instructions: "You need to add a new style rule (little + icon in the developer tools). That adds a <code>text-decoration</code> property with a value of <code>line-through</code> to any label elements that are <em>adjacent siblings</em> to a checked input. Hint: you can use <code>:checked</code> pseudo-element to select only those inputs which have been checked. To add the new style with the developer tools, right click on the exercise window and choose \"Inspect\". If you go directly to the deveoper tools, the browser might not apply the style.", instructions:
html: "<form id=\"todo-list-form\"><input type=\"checkbox\" name=\"todo-list\" id=\"exercise\"><label for=\"excercise\">Exercise</label><br><input type=\"checkbox\" name=\"todo-list\" id=\"shopping\"><label for=\"shopping\">Shopping</label><br><input type=\"checkbox\" name=\"todo-list\" id=\"clean\"><label for=\"clean\">Clean</label></form>", 'You need to add a new style rule (little + icon in the developer tools). That adds a <code>text-decoration</code> property with a value of <code>line-through</code> to any label elements that are <em>adjacent siblings</em> to a checked input. Hint: you can use <code>:checked</code> pseudo-element to select only those inputs which have been checked. To add the new style with the developer tools, right click on the exercise window and choose "Inspect". If you go directly to the deveoper tools, the browser might not apply the style.',
html: '<form id="todo-list-form"><input type="checkbox" name="todo-list" id="exercise"><label for="excercise">Exercise</label><br><input type="checkbox" name="todo-list" id="shopping"><label for="shopping">Shopping</label><br><input type="checkbox" name="todo-list" id="clean"><label for="clean">Clean</label></form>',
selector: "#todo-list-form", selector: "#todo-list-form",
events: "change", events: "change",
points: function ($element, config, event) { points: function ($element, config, event) {
let givePoints = true; let givePoints = true;
let feedback = ""; let feedback = "";
const checkedLabels = $('#todo-list-form input:checked + label'); const checkedLabels = $("#todo-list-form input:checked + label");
const allLabels = $('#todo-list-form input + label'); const allLabels = $("#todo-list-form input + label");
const inputs = $('#todo-list-form input'); const inputs = $("#todo-list-form input");
let checkedSeen = false; let checkedSeen = false;
inputs.map((idx, input) => { inputs.map((idx, input) => {
let $label = $(input).next(); let $label = $(input).next();
if($(input).prop('checked')){ if ($(input).prop("checked")) {
if ($label.css('text-decoration').indexOf('line-through') > -1) { if ($label.css("text-decoration").indexOf("line-through") > -1) {
checkedSeen = true; checkedSeen = true;
} else { } else {
feedback = "Line-through NOT found for label for checked input." feedback = "Line-through NOT found for label for checked input.";
givePoints = false; givePoints = false;
} }
} else { } else {
if ($label.css('text-decoration').indexOf('line-through') > -1) { if ($label.css("text-decoration").indexOf("line-through") > -1) {
feedback = "Line-through found for label for NOT checked input." feedback = "Line-through found for label for NOT checked input.";
givePoints = false; givePoints = false;
checkedSeen = true; checkedSeen = true;
} else { } else {
...@@ -382,27 +416,28 @@ let Content = { ...@@ -382,27 +416,28 @@ let Content = {
if (checkedSeen == false) { if (checkedSeen == false) {
givePoints = false; givePoints = false;
feedback += " You need to have at least one input checked." feedback += " You need to have at least one input checked.";
} }
if(givePoints) { if (givePoints) {
return { return {
points: 10, points: 10,
feedback: feedback feedback: feedback,
}; };
} else { } else {
return { return {
points: 0, points: 0,
feedback: feedback feedback: feedback,
}; };
} }
}, },
maxPoints: 10, maxPoints: 10,
title: "CSS pseudo-element", title: "CSS pseudo-element",
description: "Add a new CSS rule that applies to adjacent siblings of a checked input", description:
"Add a new CSS rule that applies to adjacent siblings of a checked input",
concepts: ["HTML", "Input", "CSS", "checked", "pseudo-element"], concepts: ["HTML", "Input", "CSS", "checked", "pseudo-element"],
order: 9 order: 9,
}, },
}; };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment