mirror of
https://github.com/maxogden/geojson-js-utils.git
synced 2025-12-08 18:19:11 +00:00
convert to commonjs, add point in polygon + line intersection functions
This commit is contained in:
parent
665458841e
commit
77201deba9
@ -1,41 +1,57 @@
|
||||
h1. GeoJSON Utilities for JavaScript
|
||||
|
||||
Here you will find some simple utility functions to help you manipulate and work with GeoJSON objects.
|
||||
Here you will find some simple utility functions to help you manipulate and work with GeoJSON objects.
|
||||
|
||||
h2. Feature Collection Wrapping
|
||||
Some algorithms ported from https://github.com/bjwbell/canvas-geolib
|
||||
|
||||
This was written because I wanted to display arbitrary GeoJSON objects using OpenLayers, but an OpenLayers Strategy will only accept a FeatureCollection. I use these functions to turn my basic geometries (Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon) into valid FeatureCollections.
|
||||
h2. Line intersections
|
||||
|
||||
Here's an array of two GeoJSON Point objects:
|
||||
<pre>
|
||||
<code>
|
||||
var g = require('geojson-utils.js').init()
|
||||
|
||||
<pre><code>
|
||||
[{"coordinates" : [-122.672727,45.521561],"type" : "Point"},
|
||||
{"coordinates" : [-122.675647,45.523729],"type" : "Point"}]
|
||||
</code></pre>
|
||||
g.linesIntersect([[0,6],[6,6]], [[0,3],[6,3]])
|
||||
=> false
|
||||
|
||||
If you feed that through the @GeoJSON.feature_collection_for(geometry)@ function you will receive:
|
||||
g.linesIntersect([[0,6],[6,6]], [[3,0],[3,9]])
|
||||
=> [3,6]
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<pre><code>
|
||||
{ "type" : "FeatureCollection",
|
||||
"features" : [{"geometry" :
|
||||
{ "type" : "GeometryCollection",
|
||||
"geometries" : [
|
||||
{ "coordinates" : [-122.672727,45.521561], "type" : "Point" },
|
||||
{ "coordinates" : [-122.675647,45.523729], "type" : "Point" }
|
||||
]
|
||||
}}
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
h2. Point in polygon
|
||||
|
||||
h2. Polygon Intersections
|
||||
<pre>
|
||||
<code>
|
||||
g.pointInPolygon([3,3], [[0,0],[0,6],[6,6],[6,0]])
|
||||
=> true
|
||||
|
||||
g.pointInPolygon([-1,-1], [[0,0],[0,6],[6,6],[6,0]])
|
||||
=> false
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
Given some GeoJSON polygon objects:
|
||||
h2. and much much more! read the codez
|
||||
|
||||
<pre><code>
|
||||
var intersects_1 = { "type" :"Polygon","coordinates": [[0, 5], [5, 5], [3, 9]]};
|
||||
var intersects_2 = { "type" :"Polygon","coordinates": [[9, 0], [3, 3], [9, 9]]};
|
||||
</code></pre>
|
||||
h4. License
|
||||
|
||||
If you feed these through @GeoJSON.polygonsIntersect(intersects_1, intersects_2)@ function you will receive @true@. If your polygons don't intercept, you will receive @false@.
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2010 Max Ogden
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
88
geojson-utils.js
Normal file
88
geojson-utils.js
Normal file
@ -0,0 +1,88 @@
|
||||
exports.init = function() {
|
||||
var g = {};
|
||||
|
||||
g.scalarMultiply = function(xy, scalar) {
|
||||
return [xy[0] * scalar, xy[1] * scalar];
|
||||
}
|
||||
|
||||
g.subtractVector = function(xy, vector) {
|
||||
return g.add(xy, g.scalarMultiply(vector, -1));
|
||||
}
|
||||
|
||||
g.addVector = function(xy, vector) {
|
||||
return [xy[0] + vector[0], xy[1] + vector[1]];
|
||||
}
|
||||
|
||||
g.crossProduct = function(v1, v2) {
|
||||
return v1[0] * v2[1] - v2[0] * v1[1];
|
||||
}
|
||||
|
||||
g.linesIntersect = function(seg1, seg2) {
|
||||
var p = seg1[0],
|
||||
r = g.subtractVector(seg1[1], p),
|
||||
q = seg2[0],
|
||||
s = g.subtractVector(seg2[1], q);
|
||||
var rCrossS = g.crossProduct(r, s);
|
||||
var t = g.cross(g.subtractVector(q,p), s) / rCrossS;
|
||||
var u = g.cross(g.subtractVector(q,p), r) / rCrossS;
|
||||
if (0 <= u && u <= 1 && 0 <= t && t <= 1) {
|
||||
var intersectionPoint = g.addVector(p, g.scalarMultiply(r, t));
|
||||
return intersectionPoint;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
g.pointInPolygon = function(pt, poly) {
|
||||
for (var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
|
||||
((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1] < poly[i][1]))
|
||||
&& (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0])
|
||||
&& (c = !c);
|
||||
return c;
|
||||
}
|
||||
|
||||
g.numberToRadius = function(number) {
|
||||
return number * Math.PI / 180;
|
||||
}
|
||||
|
||||
g.numberToDegree = function(number) {
|
||||
return number * 180 / Math.PI;
|
||||
}
|
||||
|
||||
g.drawCircle = function(radius, center) {
|
||||
// convert degree/km to radiant
|
||||
var dist = radius / 6371;
|
||||
var radCenter = [g.numberToRadius(center[0]), g.numberToRadius(center[1])];
|
||||
// 15 sided circle; the larger the radius the more inaccurate it will be
|
||||
var steps = 15;
|
||||
var poly = [[center[0], center[1]]];
|
||||
for (var i = 0; i < steps; i++) {
|
||||
var brng = 2 * Math.PI * i / steps;
|
||||
var lat = Math.asin(Math.sin(radCenter[0]) * Math.cos(dist) +
|
||||
Math.cos(radCenter[0]) * Math.sin(dist) * Math.cos(brng));
|
||||
var lng = radCenter[1] + Math.atan2(Math.sin(brng) * Math.sin(dist) *
|
||||
Math.cos(radCenter[0]),
|
||||
Math.cos(dist) - Math.sin(radCenter[0]) *
|
||||
Math.sin(lat));
|
||||
|
||||
poly[i] = [];
|
||||
poly[i][0] = g.numberToDegree(lat);
|
||||
poly[i][1] = g.numberToDegree(lng);
|
||||
}
|
||||
return poly;
|
||||
}
|
||||
|
||||
g.rectangleCentroid = function(bbox) {
|
||||
var xmin = bbox[0], ymin = bbox[1], xmax = bbox[2], ymax = bbox[3];
|
||||
var xwidth = xmax - xmin;
|
||||
var ywidth = ymax - ymin;
|
||||
return [xmin + xwidth/2, ymin + ywidth/2];
|
||||
}
|
||||
|
||||
g.metersToDegrees = function(meters) {
|
||||
//non spherical; the larger the area the more innaccurate it will be
|
||||
return meters/111319.9;
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
30
helpers.js
30
helpers.js
@ -1,30 +0,0 @@
|
||||
var GeoJSON = function() {
|
||||
return {
|
||||
// map borrowed from http://github.com/janl/mustache.js/blob/master/mustache.js
|
||||
map : function(array, fn) {
|
||||
if (typeof array.map == "function") {
|
||||
return array.map(fn);
|
||||
} else {
|
||||
var r = [];
|
||||
var l = array.length;
|
||||
for(var i = 0; i < l; i++) {
|
||||
r.push(fn(array[i]));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
},
|
||||
collect_geometries : function(geometries) {
|
||||
if (geometries.type == 'GeometryCollection')
|
||||
return geometries;
|
||||
return [{"type" : "GeometryCollection", "geometries" : geometries }]
|
||||
},
|
||||
collect_features : function(features){
|
||||
if (features.type == 'FeatureCollection')
|
||||
return features;
|
||||
return { "type" : "FeatureCollection", "features" : GeoJSON.map(features, function(feature){return {"geometry" : feature}})}
|
||||
},
|
||||
feature_collection_for : function(geojson) {
|
||||
return this.collect_features(this.collect_geometries(geojson));
|
||||
}
|
||||
};
|
||||
}();
|
||||
114
intersections.js
114
intersections.js
@ -1,114 +0,0 @@
|
||||
var GeoJSON = function() {
|
||||
return {
|
||||
Vector: function(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
this.scalarMult = function(scalar) {
|
||||
return new GeoJSON.Vector(this.x * scalar, this.y * scalar);
|
||||
}
|
||||
this.dot = function(v2) {
|
||||
return this.x * v2.x + this.y * v2.y;
|
||||
};
|
||||
this.perp = function() {
|
||||
return new GeoJSON.Vector(-1 * this.y, this.x);
|
||||
};
|
||||
this.subtract = function(v2) {
|
||||
return this.add(v2.scalarMult(-1));
|
||||
};
|
||||
this.add = function(v2) {
|
||||
return new GeoJSON.Vector(this.x + v2.x, this.y + v2.y);
|
||||
}
|
||||
},
|
||||
|
||||
Segment: function(p1, p2) {
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
},
|
||||
|
||||
cross: function(v1, v2) {
|
||||
return v1.x * v2.y - v2.x * v1.y;
|
||||
},
|
||||
|
||||
epsilon: 10e-6,
|
||||
doesnt_intersect: 0,
|
||||
parallel_doesnt_intersect: 1,
|
||||
colinear_doesnt_intersect: 2,
|
||||
intersect: 3,
|
||||
colinear_intersect: 4,
|
||||
|
||||
linesIntersect: function(seg1, seg2, intersectionPoint) {
|
||||
p = seg1.p1;
|
||||
r = seg1.p2.subtract(seg1.p1);
|
||||
q = seg2.p1;
|
||||
s = seg2.p2.subtract(seg2.p1);
|
||||
rCrossS = GeoJSON.cross(r, s);
|
||||
if(rCrossS <= GeoJSON.epsilon && rCrossS >= -1 * GeoJSON.epsilon){
|
||||
return GeoJSON.parallel_doesnt_intersect;
|
||||
}
|
||||
t = GeoJSON.cross(q.subtract(p), s)/rCrossS;
|
||||
u = GeoJSON.cross(q.subtract(p), r)/rCrossS;
|
||||
if(0 <= u && u <= 1 && 0 <= t && t <= 1){
|
||||
intPoint = p.add(r.scalarMult(t));
|
||||
intersectionPoint.x = intPoint.x;
|
||||
intersectionPoint.y = intPoint.y;
|
||||
return GeoJSON.intersect;
|
||||
}else{
|
||||
return GeoJSON.doesnt_intersect;
|
||||
}
|
||||
},
|
||||
|
||||
polygonsIntersect: function(pol1, pol2) {
|
||||
//todo: check for large distances
|
||||
//todo: make this not suck, written after not sleeping for 24 hours
|
||||
for(var x = 0; x < pol1.coordinates.length; x++) {
|
||||
for(var y = 0; y < pol2.coordinates.length; y++) {
|
||||
if (y === pol2.coordinates.length-1 && x !== pol1.coordinates.length-1) {
|
||||
var xa1 = pol1.coordinates[x][0];
|
||||
var ya1 = pol1.coordinates[x][1];
|
||||
var xa2 = pol1.coordinates[x+1][0];
|
||||
var ya2 = pol1.coordinates[x+1][1];
|
||||
var xb1 = pol2.coordinates[y][0];
|
||||
var yb1 = pol2.coordinates[y][1];
|
||||
var xb2 = pol2.coordinates[0][0];
|
||||
var yb2 = pol2.coordinates[0][1];
|
||||
} else if (x === pol1.coordinates.length-1 && y !== pol2.coordinates.length-1){
|
||||
var xa1 = pol1.coordinates[x][0];
|
||||
var ya1 = pol1.coordinates[x][1];
|
||||
var xa2 = pol1.coordinates[0][0];
|
||||
var ya2 = pol1.coordinates[0][1];
|
||||
var xb1 = pol2.coordinates[y][0];
|
||||
var yb1 = pol2.coordinates[y][1];
|
||||
var xb2 = pol2.coordinates[y+1][0];
|
||||
var yb2 = pol2.coordinates[y+1][1];
|
||||
} else if (x === pol1.coordinates.length-1 && y === pol2.coordinates.length-1){
|
||||
var xa1 = pol1.coordinates[x][0];
|
||||
var ya1 = pol1.coordinates[x][1];
|
||||
var xa2 = pol1.coordinates[0][0];
|
||||
var ya2 = pol1.coordinates[0][1];
|
||||
var xb1 = pol2.coordinates[y][0];
|
||||
var yb1 = pol2.coordinates[y][1];
|
||||
var xb2 = pol2.coordinates[0][0];
|
||||
var yb2 = pol2.coordinates[0][1];
|
||||
} else {
|
||||
var xa1 = pol1.coordinates[x][0];
|
||||
var ya1 = pol1.coordinates[x][1];
|
||||
var xa2 = pol1.coordinates[x+1][0];
|
||||
var ya2 = pol1.coordinates[x+1][1];
|
||||
var xb1 = pol2.coordinates[y][0];
|
||||
var yb1 = pol2.coordinates[y][1];
|
||||
var xb2 = pol2.coordinates[y+1][0];
|
||||
var yb2 = pol2.coordinates[y+1][1];
|
||||
}
|
||||
var seg1 = new GeoJSON.Segment(new GeoJSON.Vector(xa1, ya1), new GeoJSON.Vector(xa2, ya2));
|
||||
var seg2 = new GeoJSON.Segment(new GeoJSON.Vector(xb1, yb1), new GeoJSON.Vector(xb2, yb2));
|
||||
var intersectionPoint = new GeoJSON.Vector(0, 0);
|
||||
if(GeoJSON.linesIntersect(seg1, seg2, intersectionPoint) == GeoJSON.intersect) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}();
|
||||
@ -1,26 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Jasmine Test Runner</title>
|
||||
<link rel="stylesheet" type="text/css" href="jasmine-0.11.1/jasmine.css">
|
||||
<script type="text/javascript" src="jasmine-0.11.1/jasmine.js"></script>
|
||||
<script type="text/javascript" src="jasmine-0.11.1/jasmine-html.js"></script>
|
||||
|
||||
<!-- include source files here... -->
|
||||
<script type="text/javascript" src="../intersections.js"></script>
|
||||
<script type="text/javascript" src="../helpers.js"></script>
|
||||
|
||||
<!-- include spec files here... -->
|
||||
<script type="text/javascript" src="geojson_utilities_spec.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
|
||||
jasmine.getEnv().execute();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -1,87 +0,0 @@
|
||||
describe("GeoJSON intersection functions", function() {
|
||||
describe("#polygonsIntersect", function() {
|
||||
it("should detect polygons that intersect", function() {
|
||||
var intersecting1 = {"type":"Polygon","coordinates":[[-122.34100341796875,47.739446498637776],[-122.5030517578125,47.60258275608435],[-122.39593505859375,47.492276537740416],[-122.1844482421875,47.51732435953473],[-122.23663330078125,47.72097237165927],[-122.34100341796875,47.739446498637776]]};
|
||||
var intersecting2 = {"type":"Polygon","coordinates":[[-122.23388671875,47.80036462595262],[-122.3162841796875,47.688626879942966],[-122.14187622070312,47.576649235558236],[-122.04437255859375,47.75422108200102],[-122.091064453125,47.782834903292276],[-122.23388671875,47.80036462595262]]};
|
||||
var not_intersecting = {"type":"Polygon","coordinates":[[-122.48931884765625,47.86950316614039],[-122.80517578125,47.655336290758285],[-122.63763427734375,47.60258275608435],[-122.35061645507812,47.86766066723359],[-122.48931884765625,47.86950316614039]]};
|
||||
|
||||
expect(GeoJSON.polygonsIntersect(intersecting1, intersecting2)).toBeTruthy();
|
||||
expect(GeoJSON.polygonsIntersect(intersecting1, not_intersecting)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("GeoJSON helper functions", function() {
|
||||
describe("#collect_geometries", function() {
|
||||
it("should wrap geometries in a geometry collection", function() {
|
||||
var points = [{"coordinates" : [-122.672727,45.521561], "type" : "Point"},
|
||||
{"coordinates" : [-122.675647,45.523729], "type" : "Point"}];
|
||||
var geometry_collection = [{"type" : "GeometryCollection", "geometries" : points }];
|
||||
expect(GeoJSON.collect_geometries(points)).toEqual(geometry_collection);
|
||||
});
|
||||
|
||||
it("shouldn't alter existing geometry collections", function() {
|
||||
var geometry_collection = { "type" : "GeometryCollection",
|
||||
"geometries" : [
|
||||
{ "coordinates" : [-122.672727,45.521561], "type" : "Point" },
|
||||
{ "coordinates" : [-122.675647,45.523729], "type" : "Point" }
|
||||
]
|
||||
}
|
||||
expect(GeoJSON.collect_geometries(geometry_collection)).toEqual(geometry_collection);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#collect_features", function() {
|
||||
it("should wrap geometry collections in a feature collection", function() {
|
||||
var geometry_collections = [{"type" : "GeometryCollection",
|
||||
"geometries" :
|
||||
[{"type":"LineString",
|
||||
"coordinates" : [[-122.593225, 45.563783], [-122.592189, 45.563325]]
|
||||
}]
|
||||
},
|
||||
{"type" : "GeometryCollection",
|
||||
"geometries" :
|
||||
[{"type":"LineString",
|
||||
"coordinates" : [[-122.593225, 45.563783], [-122.592189, 45.563325]]
|
||||
}]
|
||||
}]
|
||||
var feature_collection = {"type" : "FeatureCollection",
|
||||
"features" : [{"geometry" : geometry_collections[0]}, {"geometry" : geometry_collections[1]}]
|
||||
}
|
||||
expect(GeoJSON.collect_features(geometry_collections)).toEqual(feature_collection);
|
||||
});
|
||||
|
||||
it("shouldn't alter existing feature collections", function() {
|
||||
feature = { "type" : "FeatureCollection",
|
||||
"features" : [{"geometry" :
|
||||
{ "type" : "GeometryCollection",
|
||||
"geometries" : [
|
||||
{ "coordinates" : [-122.672727,45.521561], "type" : "Point" },
|
||||
{ "coordinates" : [-122.675647,45.523729], "type" : "Point" }
|
||||
]
|
||||
}}
|
||||
]
|
||||
}
|
||||
expect(GeoJSON.collect_features(feature)).toEqual(feature);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#feature_collection_for", function() {
|
||||
it("should convert arbitrary arrays of individual GeoJSON objects into a feature collection", function() {
|
||||
var points = [{"coordinates" : [-122.672727,45.521561],"type" : "Point"},
|
||||
{"coordinates" : [-122.675647,45.523729],"type" : "Point"}]
|
||||
expect(GeoJSON.feature_collection_for(points)).toEqual(
|
||||
{ "type" : "FeatureCollection",
|
||||
"features" : [{"geometry" :
|
||||
{ "type" : "GeometryCollection",
|
||||
"geometries" : [
|
||||
{ "coordinates" : [-122.672727,45.521561], "type" : "Point" },
|
||||
{ "coordinates" : [-122.675647,45.523729], "type" : "Point" }
|
||||
]
|
||||
}}
|
||||
]
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,182 +0,0 @@
|
||||
jasmine.TrivialReporter = function(doc) {
|
||||
this.document = doc || document;
|
||||
this.suiteDivs = {};
|
||||
this.logRunningSpecs = false;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
|
||||
var el = document.createElement(type);
|
||||
|
||||
for (var i = 2; i < arguments.length; i++) {
|
||||
var child = arguments[i];
|
||||
|
||||
if (typeof child === 'string') {
|
||||
el.appendChild(document.createTextNode(child));
|
||||
} else {
|
||||
if (child) { el.appendChild(child); }
|
||||
}
|
||||
}
|
||||
|
||||
for (var attr in attrs) {
|
||||
if (attr == "className") {
|
||||
el[attr] = attrs[attr];
|
||||
} else {
|
||||
el.setAttribute(attr, attrs[attr]);
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
|
||||
var showPassed, showSkipped;
|
||||
|
||||
this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
|
||||
this.createDom('div', { className: 'banner' },
|
||||
this.createDom('div', { className: 'logo' },
|
||||
"Jasmine",
|
||||
this.createDom('span', { className: 'version' }, runner.env.versionString())),
|
||||
this.createDom('div', { className: 'options' },
|
||||
"Show ",
|
||||
showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
|
||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
|
||||
showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
|
||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
|
||||
)
|
||||
),
|
||||
|
||||
this.runnerDiv = this.createDom('div', { className: 'runner running' },
|
||||
this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
|
||||
this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
|
||||
this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
|
||||
);
|
||||
|
||||
this.document.body.appendChild(this.outerDiv);
|
||||
|
||||
var suites = runner.suites();
|
||||
for (var i = 0; i < suites.length; i++) {
|
||||
var suite = suites[i];
|
||||
var suiteDiv = this.createDom('div', { className: 'suite' },
|
||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
|
||||
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
|
||||
this.suiteDivs[suite.id] = suiteDiv;
|
||||
var parentDiv = this.outerDiv;
|
||||
if (suite.parentSuite) {
|
||||
parentDiv = this.suiteDivs[suite.parentSuite.id];
|
||||
}
|
||||
parentDiv.appendChild(suiteDiv);
|
||||
}
|
||||
|
||||
this.startedAt = new Date();
|
||||
|
||||
var self = this;
|
||||
showPassed.onchange = function(evt) {
|
||||
if (evt.target.checked) {
|
||||
self.outerDiv.className += ' show-passed';
|
||||
} else {
|
||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
|
||||
}
|
||||
};
|
||||
|
||||
showSkipped.onchange = function(evt) {
|
||||
if (evt.target.checked) {
|
||||
self.outerDiv.className += ' show-skipped';
|
||||
} else {
|
||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
|
||||
var results = runner.results();
|
||||
var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
|
||||
this.runnerDiv.setAttribute("class", className);
|
||||
//do it twice for IE
|
||||
this.runnerDiv.setAttribute("className", className);
|
||||
var specs = runner.specs();
|
||||
var specCount = 0;
|
||||
for (var i = 0; i < specs.length; i++) {
|
||||
if (this.specFilter(specs[i])) {
|
||||
specCount++;
|
||||
}
|
||||
}
|
||||
var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
|
||||
message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
|
||||
this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
|
||||
|
||||
this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
|
||||
var results = suite.results();
|
||||
var status = results.passed() ? 'passed' : 'failed';
|
||||
if (results.totalCount == 0) { // todo: change this to check results.skipped
|
||||
status = 'skipped';
|
||||
}
|
||||
this.suiteDivs[suite.id].className += " " + status;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
|
||||
if (this.logRunningSpecs) {
|
||||
this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
|
||||
var results = spec.results();
|
||||
var status = results.passed() ? 'passed' : 'failed';
|
||||
if (results.skipped) {
|
||||
status = 'skipped';
|
||||
}
|
||||
var specDiv = this.createDom('div', { className: 'spec ' + status },
|
||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
|
||||
this.createDom('a', {
|
||||
className: 'description',
|
||||
href: '?spec=' + encodeURIComponent(spec.getFullName()),
|
||||
title: spec.getFullName()
|
||||
}, spec.description));
|
||||
|
||||
|
||||
var resultItems = results.getItems();
|
||||
var messagesDiv = this.createDom('div', { className: 'messages' });
|
||||
for (var i = 0; i < resultItems.length; i++) {
|
||||
var result = resultItems[i];
|
||||
|
||||
if (result.type == 'log') {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
|
||||
} else if (result.type == 'expect' && result.passed && !result.passed()) {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
|
||||
|
||||
if (result.trace.stack) {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (messagesDiv.childNodes.length > 0) {
|
||||
specDiv.appendChild(messagesDiv);
|
||||
}
|
||||
|
||||
this.suiteDivs[spec.suite.id].appendChild(specDiv);
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.log = function() {
|
||||
var console = jasmine.getGlobal().console;
|
||||
if (console && console.log) console.log.apply(console, arguments);
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.getLocation = function() {
|
||||
return this.document.location;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.specFilter = function(spec) {
|
||||
var paramMap = {};
|
||||
var params = this.getLocation().search.substring(1).split('&');
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var p = params[i].split('=');
|
||||
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
|
||||
}
|
||||
|
||||
if (!paramMap["spec"]) return true;
|
||||
return spec.getFullName().indexOf(paramMap["spec"]) == 0;
|
||||
};
|
||||
@ -1,166 +0,0 @@
|
||||
body {
|
||||
font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
|
||||
}
|
||||
|
||||
|
||||
.jasmine_reporter a:visited, .jasmine_reporter a {
|
||||
color: #303;
|
||||
}
|
||||
|
||||
.jasmine_reporter a:hover, .jasmine_reporter a:active {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.run_spec {
|
||||
float:right;
|
||||
padding-right: 5px;
|
||||
font-size: .8em;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.jasmine_reporter {
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.banner {
|
||||
color: #303;
|
||||
background-color: #fef;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
float: left;
|
||||
font-size: 1.1em;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.logo .version {
|
||||
font-size: .6em;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.runner.running {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
|
||||
.options {
|
||||
text-align: right;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.suite {
|
||||
border: 1px outset gray;
|
||||
margin: 5px 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.suite .suite {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.suite.passed {
|
||||
background-color: #dfd;
|
||||
}
|
||||
|
||||
.suite.failed {
|
||||
background-color: #fdd;
|
||||
}
|
||||
|
||||
.spec {
|
||||
margin: 5px;
|
||||
padding-left: 1em;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.spec.failed, .spec.passed, .spec.skipped {
|
||||
padding-bottom: 5px;
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
.spec.failed {
|
||||
background-color: #fbb;
|
||||
border-color: red;
|
||||
}
|
||||
|
||||
.spec.passed {
|
||||
background-color: #bfb;
|
||||
border-color: green;
|
||||
}
|
||||
|
||||
.spec.skipped {
|
||||
background-color: #bbb;
|
||||
}
|
||||
|
||||
.messages {
|
||||
border-left: 1px dashed gray;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
.passed {
|
||||
background-color: #cfc;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.failed {
|
||||
background-color: #fbb;
|
||||
}
|
||||
|
||||
.skipped {
|
||||
color: #777;
|
||||
background-color: #eee;
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/*.resultMessage {*/
|
||||
/*white-space: pre;*/
|
||||
/*}*/
|
||||
|
||||
.resultMessage span.result {
|
||||
display: block;
|
||||
line-height: 2em;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.resultMessage .mismatch {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.stackTrace {
|
||||
white-space: pre;
|
||||
font-size: .8em;
|
||||
margin-left: 10px;
|
||||
max-height: 5em;
|
||||
overflow: auto;
|
||||
border: 1px inset red;
|
||||
padding: 1em;
|
||||
background: #eef;
|
||||
}
|
||||
|
||||
.finished-at {
|
||||
padding-left: 1em;
|
||||
font-size: .6em;
|
||||
}
|
||||
|
||||
.show-passed .passed,
|
||||
.show-skipped .skipped {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
#jasmine_content {
|
||||
position:fixed;
|
||||
right: 100%;
|
||||
}
|
||||
|
||||
.runner {
|
||||
border: 1px solid gray;
|
||||
display: block;
|
||||
margin: 5px 0;
|
||||
padding: 2px 0 2px 10px;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user