2019-10-04 in class
This commit is contained in:
parent
6388526c01
commit
c72515f5ae
13 changed files with 28388 additions and 0 deletions
42
hw3/Claudio_Maggioni/index.html
Normal file
42
hw3/Claudio_Maggioni/index.html
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
<!-- DON'T MODIFY THIS FILE -->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>OO-JS Exercise - Web Atelier 2017</title>
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css">
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body onload="init()">
|
||||||
|
<h1>
|
||||||
|
OO-JS Exercise: Canvas
|
||||||
|
</h1>
|
||||||
|
<!-- <div id="clock">
|
||||||
|
<div id="progress-bar"></div>
|
||||||
|
<div id="clock-time"></div>
|
||||||
|
</div> -->
|
||||||
|
<div id="app">
|
||||||
|
<div id="left-toolbar" class="toolbar">
|
||||||
|
<button id="clear-btn">Clear</button>
|
||||||
|
<button id="undo-btn">Undo</button>
|
||||||
|
<button id="camera-btn"><i class="fa fa-camera" aria-hidden="true"></i></button>
|
||||||
|
</div>
|
||||||
|
<canvas id="canvas" width="600" height="400"></canvas>
|
||||||
|
<div id="brush-toolbar" class="toolbar">
|
||||||
|
<!-- Brushes buttons go here (programmatically). Each button should be a <button> element -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h2>Favourites</h2>
|
||||||
|
<div id="favourites">
|
||||||
|
<!-- Favourites will go here (programmatically). Each favourite should be an <img> element -->
|
||||||
|
</div>
|
||||||
|
<script src="scripts/brushes.js"></script>
|
||||||
|
<script src="scripts/undo.js"></script>
|
||||||
|
<!-- <script src="scripts/clock.js"></script> -->
|
||||||
|
<script src="scripts/app.js"></script>
|
||||||
|
<script src="main.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
15
hw3/Claudio_Maggioni/main.js
Normal file
15
hw3/Claudio_Maggioni/main.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// vim: set ts=2 sw=2 tw=80 et:
|
||||||
|
// Enter your initialization code here
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
// Create canvas app
|
||||||
|
const app = new App({
|
||||||
|
canvas: 'canvas',
|
||||||
|
buttons: {
|
||||||
|
clear: 'clear-btn',
|
||||||
|
camera: 'camera-btn',
|
||||||
|
undo: 'undo-btn'
|
||||||
|
},
|
||||||
|
brushToolbar: 'brush-toolbar'
|
||||||
|
});
|
||||||
|
}
|
5
hw3/Claudio_Maggioni/qunit-compat.js
Normal file
5
hw3/Claudio_Maggioni/qunit-compat.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
let test = QUnit.test;
|
||||||
|
let equal = QUnit.assert.equal.bind(QUnit.assert);
|
||||||
|
let notEqual = QUnit.assert.notEqual.bind(QUnit.assert);
|
||||||
|
let deepEqual = QUnit.assert.deepEqual.bind(QUnit.assert);
|
||||||
|
let notDeepEqual = QUnit.assert.notDeepEqual.bind(QUnit.assert);
|
5588
hw3/Claudio_Maggioni/resources/jsverify.standalone.js
Normal file
5588
hw3/Claudio_Maggioni/resources/jsverify.standalone.js
Normal file
File diff suppressed because it is too large
Load diff
17084
hw3/Claudio_Maggioni/resources/lodash.js
Normal file
17084
hw3/Claudio_Maggioni/resources/lodash.js
Normal file
File diff suppressed because it is too large
Load diff
5048
hw3/Claudio_Maggioni/resources/qunit-2.4.0.js
Normal file
5048
hw3/Claudio_Maggioni/resources/qunit-2.4.0.js
Normal file
File diff suppressed because it is too large
Load diff
235
hw3/Claudio_Maggioni/resources/qunit.css
Normal file
235
hw3/Claudio_Maggioni/resources/qunit.css
Normal file
|
@ -0,0 +1,235 @@
|
||||||
|
/**
|
||||||
|
* QUnit v1.10.0 - A JavaScript Unit Testing Framework
|
||||||
|
*
|
||||||
|
* http://qunitjs.com
|
||||||
|
*
|
||||||
|
* Copyright 2012 jQuery Foundation and other contributors
|
||||||
|
* Released under the MIT license.
|
||||||
|
* http://jquery.org/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Font Family and Sizes */
|
||||||
|
|
||||||
|
#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
|
||||||
|
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
|
||||||
|
#qunit-tests { font-size: smaller; }
|
||||||
|
|
||||||
|
|
||||||
|
/** Resets */
|
||||||
|
|
||||||
|
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Header */
|
||||||
|
|
||||||
|
#qunit-header {
|
||||||
|
padding: 0.5em 0 0.5em 1em;
|
||||||
|
|
||||||
|
color: #8699a4;
|
||||||
|
background-color: #0d3349;
|
||||||
|
|
||||||
|
font-size: 1.5em;
|
||||||
|
line-height: 1em;
|
||||||
|
font-weight: normal;
|
||||||
|
|
||||||
|
border-radius: 5px 5px 0 0;
|
||||||
|
-moz-border-radius: 5px 5px 0 0;
|
||||||
|
-webkit-border-top-right-radius: 5px;
|
||||||
|
-webkit-border-top-left-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-header a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #c2ccd1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-header a:hover,
|
||||||
|
#qunit-header a:focus {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-testrunner-toolbar label {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0 .5em 0 .1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-banner {
|
||||||
|
height: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-testrunner-toolbar {
|
||||||
|
padding: 0.5em 0 0.5em 2em;
|
||||||
|
color: #5E740B;
|
||||||
|
background-color: #eee;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-userAgent {
|
||||||
|
padding: 0.5em 0 0.5em 2.5em;
|
||||||
|
background-color: #2b81af;
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-modulefilter-container {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Tests: Pass/Fail */
|
||||||
|
|
||||||
|
#qunit-tests {
|
||||||
|
list-style-position: inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests li {
|
||||||
|
padding: 0.4em 0.5em 0.4em 2.5em;
|
||||||
|
border-bottom: 1px solid #fff;
|
||||||
|
list-style-position: inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests li strong {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests li a {
|
||||||
|
padding: 0.5em;
|
||||||
|
color: #c2ccd1;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
#qunit-tests li a:hover,
|
||||||
|
#qunit-tests li a:focus {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests ol {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
padding: 0.5em;
|
||||||
|
|
||||||
|
background-color: #fff;
|
||||||
|
|
||||||
|
border-radius: 5px;
|
||||||
|
-moz-border-radius: 5px;
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-top: .2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests th {
|
||||||
|
text-align: right;
|
||||||
|
vertical-align: top;
|
||||||
|
padding: 0 .5em 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests td {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests pre {
|
||||||
|
margin: 0;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests del {
|
||||||
|
background-color: #e0f2be;
|
||||||
|
color: #374e0c;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests ins {
|
||||||
|
background-color: #ffcaca;
|
||||||
|
color: #500;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Test Counts */
|
||||||
|
|
||||||
|
#qunit-tests b.counts { color: black; }
|
||||||
|
#qunit-tests b.passed { color: #5E740B; }
|
||||||
|
#qunit-tests b.failed { color: #710909; }
|
||||||
|
|
||||||
|
#qunit-tests li li {
|
||||||
|
padding: 5px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-bottom: none;
|
||||||
|
list-style-position: inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Passing Styles */
|
||||||
|
|
||||||
|
#qunit-tests li li.pass {
|
||||||
|
color: #3c510c;
|
||||||
|
background-color: #fff;
|
||||||
|
border-left: 10px solid #C6E746;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
|
||||||
|
#qunit-tests .pass .test-name { color: #366097; }
|
||||||
|
|
||||||
|
#qunit-tests .pass .test-actual,
|
||||||
|
#qunit-tests .pass .test-expected { color: #999999; }
|
||||||
|
|
||||||
|
#qunit-banner.qunit-pass { background-color: #C6E746; }
|
||||||
|
|
||||||
|
/*** Failing Styles */
|
||||||
|
|
||||||
|
#qunit-tests li li.fail {
|
||||||
|
color: #710909;
|
||||||
|
background-color: #fff;
|
||||||
|
border-left: 10px solid #EE5757;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests > li:last-child {
|
||||||
|
border-radius: 0 0 5px 5px;
|
||||||
|
-moz-border-radius: 0 0 5px 5px;
|
||||||
|
-webkit-border-bottom-right-radius: 5px;
|
||||||
|
-webkit-border-bottom-left-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
|
||||||
|
#qunit-tests .fail .test-name,
|
||||||
|
#qunit-tests .fail .module-name { color: #000000; }
|
||||||
|
|
||||||
|
#qunit-tests .fail .test-actual { color: #EE5757; }
|
||||||
|
#qunit-tests .fail .test-expected { color: green; }
|
||||||
|
|
||||||
|
#qunit-banner.qunit-fail { background-color: #EE5757; }
|
||||||
|
|
||||||
|
|
||||||
|
/** Result */
|
||||||
|
|
||||||
|
#qunit-testresult {
|
||||||
|
padding: 0.5em 0.5em 0.5em 2.5em;
|
||||||
|
|
||||||
|
color: #2b81af;
|
||||||
|
background-color: #D2E0E6;
|
||||||
|
|
||||||
|
border-bottom: 1px solid white;
|
||||||
|
}
|
||||||
|
#qunit-testresult .module-name {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fixture */
|
||||||
|
|
||||||
|
#qunit-fixture {
|
||||||
|
position: absolute;
|
||||||
|
top: -10000px;
|
||||||
|
left: -10000px;
|
||||||
|
width: 1000px;
|
||||||
|
height: 1000px;
|
||||||
|
}
|
83
hw3/Claudio_Maggioni/scripts/app.js
Normal file
83
hw3/Claudio_Maggioni/scripts/app.js
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
// vim: set ts=2 sw=2 et tw=80:
|
||||||
|
class App {
|
||||||
|
constructor(conf) {
|
||||||
|
if (!(typeof conf === 'object' && conf)) {
|
||||||
|
throw new Error('Argument conf different from specification');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.canvas = document.getElementById(conf.canvas);
|
||||||
|
if (!this.canvas || this.canvas.tagName !== 'CANVAS') {
|
||||||
|
throw new Error(`canvas is not a canvas`);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ctx = this.canvas.getContext('2d');
|
||||||
|
this.favourites = document.querySelector('div#favourites');
|
||||||
|
|
||||||
|
if (typeof conf.buttons === 'object' && conf.buttons) {
|
||||||
|
this.buttons = {}
|
||||||
|
for (const b of ['clear', 'button', 'camera'])
|
||||||
|
this.buttons[b] = document.getElementById(conf.buttons[b]);
|
||||||
|
|
||||||
|
if (this.buttons.clear)
|
||||||
|
this.buttons.clear.addEventListener('click', () =>
|
||||||
|
this.ctx.clearRect(0, 0, canvas.width, canvas.height));
|
||||||
|
|
||||||
|
if (this.buttons.camera)
|
||||||
|
this.buttons.camera.addEventListener('click', () => {
|
||||||
|
const base64 = this.canvas.toDataURL();
|
||||||
|
const img = document.createElement('img');
|
||||||
|
img.src = base64;
|
||||||
|
const span = document.createElement('span');
|
||||||
|
span.contentEditable = true;
|
||||||
|
this.favourites.appendChild(img);
|
||||||
|
this.favourites.appendChild(span);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.canvas.addEventListener('mousedown', (e) => {
|
||||||
|
this.ctx.save();
|
||||||
|
this.ctx.lineWidth = 1;
|
||||||
|
this.ctx.moveTo(e.offsetX, e.offsetY);
|
||||||
|
this.ctx.beginPath();
|
||||||
|
this.mousedown = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.canvas.addEventListener('mousemove', (e) => this.mousedown && this.draw(e));
|
||||||
|
|
||||||
|
const endPath = (e) => {
|
||||||
|
this.ctx.lineTo(e.offsetX, e.offsetY);
|
||||||
|
this.ctx.stroke();
|
||||||
|
this.ctx.restore();
|
||||||
|
this.mousedown = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.canvas.addEventListener('mouseup', endPath);
|
||||||
|
this.canvas.addEventListener('mouseout', endPath);
|
||||||
|
|
||||||
|
this.strokeStyle = this.constructor.defaultStrokeStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get defaultStrokeStyle() {
|
||||||
|
return 'black';
|
||||||
|
}
|
||||||
|
|
||||||
|
get strokeStyle() {
|
||||||
|
return this.ctx.strokeStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
set strokeStyle(style) {
|
||||||
|
if (typeof style !== 'string') {
|
||||||
|
throw new Error('style is not a string');
|
||||||
|
}
|
||||||
|
this.ctx.strokeStyle = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(e) {
|
||||||
|
console.log(e);
|
||||||
|
this.ctx.lineTo(e.offsetX, e.offsetY);
|
||||||
|
this.ctx.stroke();
|
||||||
|
this.ctx.beginPath();
|
||||||
|
this.ctx.moveTo(e.offsetX, e.offsetY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
19
hw3/Claudio_Maggioni/scripts/brushes.js
Normal file
19
hw3/Claudio_Maggioni/scripts/brushes.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
class PenBrush {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.opacity = 1;
|
||||||
|
this.name = "PenBrush";
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(ctx, strokeStyle, x, y) {
|
||||||
|
ctx.lineJoin = ctx.lineCap = 'round';
|
||||||
|
ctx.strokeStyle = strokeStyle;
|
||||||
|
ctx.lineTo(x, y);
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO DiscBrush
|
||||||
|
//TODO StarBrush
|
||||||
|
|
4
hw3/Claudio_Maggioni/scripts/undo.js
Normal file
4
hw3/Claudio_Maggioni/scripts/undo.js
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
const history = {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
136
hw3/Claudio_Maggioni/style.css
Normal file
136
hw3/Claudio_Maggioni/style.css
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
/* DO NOT MODIFY */
|
||||||
|
body{
|
||||||
|
font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#canvas{
|
||||||
|
border: 1px solid #bbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar {
|
||||||
|
width: 56px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar button {
|
||||||
|
height: 25px;
|
||||||
|
width: 52px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#brush-toolbar{
|
||||||
|
width: 84px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#brush-toolbar button{
|
||||||
|
height: 40px;
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#palette{
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-around;
|
||||||
|
width: 53px;
|
||||||
|
height: 204px;
|
||||||
|
background-color: buttonface;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar #camera-btn{
|
||||||
|
font-size: 1.5em;
|
||||||
|
line-height: 1.5em;
|
||||||
|
color: #444;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
border-radius: 3px;
|
||||||
|
height: 40px;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar #camera-btn:hover{
|
||||||
|
background: #70a0e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar #camera-btn:active{
|
||||||
|
background: #0e57c3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-color{
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.black {background-color:rgb(0, 0, 0);}
|
||||||
|
.dark-gray {background-color:rgb(87, 87, 87);}
|
||||||
|
.red {background-color:rgb(173, 35, 35);}
|
||||||
|
.blue {background-color:rgb(42, 75, 215);}
|
||||||
|
.green {background-color:rgb(29, 105, 20);}
|
||||||
|
.brown {background-color:rgb(129, 74, 25);}
|
||||||
|
.purple {background-color:rgb(129, 38, 192);}
|
||||||
|
.light-gray {background-color:rgb(160, 160, 160);}
|
||||||
|
.light-green {background-color:rgb(129, 197, 122);}
|
||||||
|
.light-blue {background-color:rgb(157, 175, 255);}
|
||||||
|
.cyan {background-color:rgb(41, 208, 208);}
|
||||||
|
.orange {background-color:rgb(255, 146, 51);}
|
||||||
|
.yellow {background-color:rgb(255, 238, 51);}
|
||||||
|
.tan {background-color:rgb(233, 222, 187);}
|
||||||
|
.pink {background-color:rgb(255, 205, 243);}
|
||||||
|
.white {background-color:rgb(255, 255, 255);}
|
||||||
|
|
||||||
|
#clock {
|
||||||
|
background-color: #ddd;
|
||||||
|
width: 360px;
|
||||||
|
height: 48px;
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
font-size: 2.5rem;
|
||||||
|
margin-top: -10px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#clock-time,
|
||||||
|
#progress-bar {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
#clock-time {
|
||||||
|
z-index: 10;
|
||||||
|
line-height: 48px; /* same height as #clock so that the time is vertically centered */
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress-bar {
|
||||||
|
width: 0%;
|
||||||
|
height: 48px;
|
||||||
|
background-color: #8DFF80;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 30px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#favourites div.gallery {
|
||||||
|
margin: 5px;
|
||||||
|
float: left;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#favourites div.gallery img {
|
||||||
|
width: 90%;
|
||||||
|
height: 100px;
|
||||||
|
box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.42);
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#favourites div.desc {
|
||||||
|
padding: 15px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
26
hw3/Claudio_Maggioni/test.html
Normal file
26
hw3/Claudio_Maggioni/test.html
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Exercise 3 - Object-oriented Javascript</title>
|
||||||
|
<link rel="stylesheet" href="resources/qunit.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<canvas id="test-canvas" width="600" height="400" style="display: none"></canvas>
|
||||||
|
|
||||||
|
<div id="qunit"></div>
|
||||||
|
<div id="qunit-fixture"></div>
|
||||||
|
<script src="scripts/brushes.js"></script>
|
||||||
|
<script src="scripts/undo.js"></script>
|
||||||
|
<script src="scripts/clock.js"></script>
|
||||||
|
<script src="scripts/app.js"></script>
|
||||||
|
<script src="resources/qunit-2.4.0.js"></script>
|
||||||
|
<script src="resources/lodash.js"></script>
|
||||||
|
<script src="resources/jsverify.standalone.js"></script>
|
||||||
|
<script src="qunit-compat.js"></script>
|
||||||
|
<script src="test.js"></script>
|
||||||
|
<script>
|
||||||
|
tests();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
103
hw3/Claudio_Maggioni/test.js
Normal file
103
hw3/Claudio_Maggioni/test.js
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
function tests() {
|
||||||
|
|
||||||
|
test("App class constructors and methods", function(assert) {
|
||||||
|
// The App class must be defined
|
||||||
|
equal(typeof App === 'function', true, "The App class must be defined");
|
||||||
|
equal(/^\s*class\s+/.test(App.toString()), true, "App is a function but it is not defined using the class keyword")
|
||||||
|
|
||||||
|
|
||||||
|
// The App class constructor should throw an error if its argument is undefined
|
||||||
|
assert.throws(function() {
|
||||||
|
new App(undefined)
|
||||||
|
}, "The App class constructor should throw an error if its argument is undefined")
|
||||||
|
// The App class constructor should throw an error if its argument is not a canvas
|
||||||
|
assert.throws(function() {
|
||||||
|
new App("");
|
||||||
|
}, "The App class constructor should throw an error if its argument is not an object")
|
||||||
|
assert.throws(function() {
|
||||||
|
new App(1);
|
||||||
|
}, "The App class constructor should throw an error if its argument is a number")
|
||||||
|
assert.throws(function() {
|
||||||
|
new App([]);
|
||||||
|
}, "The App class constructor should throw an error if its argument is an array")
|
||||||
|
assert.throws(function() {
|
||||||
|
new App(true);
|
||||||
|
}, "The App class constructor should throw an error if its argument is a boolean")
|
||||||
|
|
||||||
|
// The default Stroke Style should be accessible in a static way, and should be equal to "black"
|
||||||
|
equal(App.defaultStrokeStyle === 'black', true, 'The default Stroke Style should be accessible in a static way, and should be equal to "black"')
|
||||||
|
|
||||||
|
assert.throws(function() {
|
||||||
|
new App({});
|
||||||
|
}, "The App class constructor should throw an error if its argument options object is not pointing to a canvas element under the 'canvas' property")
|
||||||
|
|
||||||
|
const app = new App({canvas: 'test-canvas'})
|
||||||
|
equal(app.strokeStyle, "black", "Getter for strokeStyle is not defined")
|
||||||
|
|
||||||
|
// The draw method must be defined
|
||||||
|
equal(typeof app.draw === 'function', true, "The draw method must be defined")
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test("History and Stroke object literals fields and methods", function(assert) {
|
||||||
|
// The Stroke class must be defined
|
||||||
|
equal(typeof Stroke === 'function', true, "The Stroke class must be defined");
|
||||||
|
equal(/^\s*class\s+/.test(Stroke.toString()), true, "Stroke is a function but it is not defined using the class keyword")
|
||||||
|
|
||||||
|
equal(function(){
|
||||||
|
try {
|
||||||
|
const stroke = new Stroke('square')
|
||||||
|
} catch (err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}(), true, "Stroke can be instantiated")
|
||||||
|
|
||||||
|
const stroke = new Stroke('square');
|
||||||
|
const stroke1 = new Stroke('circle');
|
||||||
|
const stroke2 = new Stroke('triangle');
|
||||||
|
history.initializeNewPath()
|
||||||
|
|
||||||
|
assert.throws(function() {
|
||||||
|
history.push()
|
||||||
|
}, "Must pass a Stroke instance when you push in the history")
|
||||||
|
|
||||||
|
equal(function() {
|
||||||
|
try {
|
||||||
|
history.push(stroke);
|
||||||
|
} catch (err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}(), true, "History push accepts Stroke instances as a parameter");
|
||||||
|
|
||||||
|
equal(history.pop()[0] === stroke, true, "Pop returns an array containing the pushed Stroke instance")
|
||||||
|
|
||||||
|
history.initializeNewPath();
|
||||||
|
|
||||||
|
history.push(stroke);
|
||||||
|
history.push(stroke1);
|
||||||
|
history.push(stroke2);
|
||||||
|
|
||||||
|
equal(history.pop().length, 3, "Pop returns an array containing the pushed Stroke instances")
|
||||||
|
|
||||||
|
history.initializeNewPath();
|
||||||
|
|
||||||
|
equal(history.pop().length, 0, "Pop on an empty history should return an empty array")
|
||||||
|
|
||||||
|
history.initializeNewPath(); //simulate mouse down
|
||||||
|
|
||||||
|
history.push(stroke); //simulate mouse move
|
||||||
|
history.push(stroke1); //simulate mouse move
|
||||||
|
|
||||||
|
history.initializeNewPath(); //simulate mouse up and down again
|
||||||
|
|
||||||
|
history.push(stroke2); //simulate mouse move
|
||||||
|
|
||||||
|
equal(history.pop().length, 1, "Pop returns an array containing the most recent path (Expected path with 1 Stroke)")
|
||||||
|
|
||||||
|
equal(history.pop().length, 2, "Pop returns an array containing the most recent path (Expected path with 2 Strokes)")
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
Reference in a new issue