This repository has been archived by the owner on Apr 1, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
1 parent
550b7c2
commit 026c40d
Showing
7 changed files
with
219 additions
and
82 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this file, | ||
* You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
|
||
"use strict"; | ||
|
||
(function(exports) { | ||
function Rectangle(x, y, w, h) { | ||
this.setRect(x, y, w, h); | ||
} | ||
|
||
Rectangle.prototype = { | ||
get width() { | ||
return this.right - this.left; | ||
}, | ||
get height() { | ||
return this.bottom - this.top; | ||
}, | ||
set width(v) { | ||
this.right = this.left + coerceToNumber(v); | ||
}, | ||
set height(v) { | ||
this.bottom = this.top + coerceToNumber(v); | ||
}, | ||
get isEmpty() { | ||
return this.left >= this.right || this.top >= this.bottom; | ||
}, | ||
|
||
clone() { | ||
return new Rectangle(this.left, this.top, this.width, this.height); | ||
}, | ||
|
||
intersect(other) { | ||
return this.clone().restrictTo(other); | ||
}, | ||
|
||
setRect(x, y, w, h) { | ||
this.left = coerceToNumber(x); | ||
this.top = coerceToNumber(y); | ||
this.right = this.left + coerceToNumber(w); | ||
this.bottom = this.top + coerceToNumber(h); | ||
return this; | ||
}, | ||
|
||
// Restrict area of this rectangle to the intersection of both rectangles. | ||
restrictTo(other) { | ||
if (this.isEmpty || other.isEmpty) { | ||
return this.setRect(0, 0, 0, 0); | ||
} | ||
|
||
const x1 = Math.max(this.left, other.left); | ||
const x2 = Math.min(this.right, other.right); | ||
const y1 = Math.max(this.top, other.top); | ||
const y2 = Math.min(this.bottom, other.bottom); | ||
|
||
// If width or height is 0, the intersection was empty. | ||
return this.setRect(x1, y1, Math.max(0, x2 - x1), Math.max(0, y2 - y1)); | ||
}, | ||
}; | ||
|
||
function coerceToNumber(v) { | ||
var num = Number.parseInt(v, 10); | ||
if (Number.isNaN(num)) { | ||
throw new TypeError("Expected number."); | ||
} | ||
return num; | ||
} | ||
exports.Rectangle = Rectangle; | ||
}(window)); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
/* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this file, | ||
* You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
/*global assert, expect*/ | ||
"use strict"; | ||
|
||
describe("Rect class", () => { | ||
|
||
describe("Exposed correctly", () => { | ||
it("should be present on window object", () => { | ||
assert.equal(!!(window.Rectangle), true); | ||
}); | ||
it("should be a function.", () => { | ||
assert.equal(typeof window.Rectangle === "function", true); | ||
}); | ||
it("should be constructible.", () => { | ||
var rect = new window.Rectangle(0, 0, 0, 0); | ||
expect(rect).to.be.an.instanceof(window.Rectangle); | ||
}); | ||
}); | ||
|
||
describe("Creating a rectangle", () => { | ||
it("should throw when constructor arguments result in NaN.", () => { | ||
var builder = function() { | ||
new window.Rectangle(...arguments); | ||
}; | ||
expect(() => { | ||
builder(); | ||
}).to.throw(TypeError); | ||
expect(() => { | ||
builder("one"); | ||
}).to.throw(TypeError); | ||
expect(() => { | ||
builder(1, "two", 3, 4); | ||
}).to.throw(TypeError); | ||
expect(() => { | ||
builder(1, 2, "three", 4); | ||
}).to.throw(TypeError); | ||
expect(() => { | ||
builder(1, 2, 3, "four"); | ||
}).to.throw(TypeError); | ||
}); | ||
it("should have attributes whose types are numbers.", () => { | ||
var rect = new window.Rectangle(1, 1, 10, 10); | ||
assert.typeOf(rect.left, "number"); | ||
assert.typeOf(rect.top, "number"); | ||
assert.typeOf(rect.bottom, "number"); | ||
assert.typeOf(rect.right, "number"); | ||
}); | ||
it("should have its properties set correctly.", () => { | ||
var rect = new window.Rectangle(5, 10, 10, 20); | ||
expect(rect.left).to.equal(5); | ||
expect(rect.top).to.equal(10); | ||
expect(rect.right).to.equal(15); | ||
expect(rect.bottom).to.equal(30); | ||
}); | ||
it("should parse strings correctly.", () => { | ||
var rect = new window.Rectangle(" 5 ", " \n 10 \t\t", "10", "\t20"); | ||
expect(rect.left).to.equal(5); | ||
expect(rect.left).to.be.a("number"); | ||
expect(rect.top).to.equal(10); | ||
expect(rect.top).to.be.a("number"); | ||
expect(rect.right).to.equal(15); | ||
expect(rect.right).to.be.a("number"); | ||
expect(rect.bottom).to.equal(30); | ||
expect(rect.bottom).to.be.a("number"); | ||
}); | ||
}); | ||
|
||
describe("Cloning", () => { | ||
var rect = new window.Rectangle(0, 0, 10, 10); | ||
var clone = rect.clone(); | ||
it("should result in different objects.", () => { | ||
expect(clone).to.not.be(rect); | ||
}); | ||
it("should have the same property values", () => { | ||
expect(clone).to.have.property("width", rect.width); | ||
expect(clone).to.have.property("height", rect.height); | ||
expect(clone).to.have.property("top", rect.top); | ||
expect(clone).to.have.property("bottom", rect.bottom); | ||
expect(clone).to.have.property("left", rect.left); | ||
expect(clone).to.have.property("right", rect.right); | ||
}); | ||
}); | ||
|
||
describe("Intersect and restrict", ()=> { | ||
it("should result in an empty rectangle after intersection.", ()=> { | ||
var emptyA = new window.Rectangle(0, 0, 0, 0); | ||
var b = new window.Rectangle(0, 0, 10, 10); | ||
expect(b.isEmpty).to.be(false); | ||
b.intersect(emptyA); | ||
expect(b.isEmpty).to.be(true); | ||
}); | ||
it("it should restrict a to b", ()=> { | ||
var a = new window.Rectangle(0, 0, 100, 100); | ||
var b = new window.Rectangle(10, 10, 50, 50); | ||
a.restrictTo(b); | ||
expect(a).to.have.property("left", 10); | ||
expect(a).to.have.property("top", 10); | ||
expect(a).to.have.property("right", 60); | ||
expect(a).to.have.property("bottom", 60); | ||
}); | ||
}); | ||
|
||
describe("Getters and setters", () => { | ||
var rect = new window.Rectangle(0, 0, 10, 20); | ||
it("should return the width.", () => { | ||
expect(rect.width).to.equal(10); | ||
}); | ||
it("should return the height.", () => { | ||
expect(rect.height).to.equal(20); | ||
}); | ||
it("should throw if setting the width to a NaN.", () => { | ||
expect(() => { | ||
rect.width = "not a number"; | ||
}).to.throw(TypeError); | ||
}); | ||
it("should throw if setting the height to a NaN.", () => { | ||
expect(() => { | ||
rect.height = "not a number"; | ||
}).to.throw(TypeError); | ||
}); | ||
it("should set the width.", () => { | ||
rect.width = 32; | ||
expect(rect.width).to.equal(32); | ||
}); | ||
it("should set the height.", () => { | ||
rect.height = 32; | ||
expect(rect.height).to.equal(32); | ||
}); | ||
it("should not be empty.", () => { | ||
assert.equal(rect.isEmpty, false); | ||
}); | ||
it("should become empty.", () => { | ||
rect.setRect(0, 0, 0, 0); | ||
assert.equal(rect.isEmpty, true); | ||
rect.setRect(0, 0, -10, -10); | ||
assert.equal(rect.isEmpty, true); | ||
}); | ||
}); | ||
}); |