Liberate Connection, use jQuery for ajax

This commit is contained in:
Tom MacWright
2012-10-16 20:54:46 -04:00
parent 6cbbba9f8c
commit 2b8b30ad1e
11 changed files with 182 additions and 146 deletions
+10
View File
@@ -9,6 +9,7 @@
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojox/layout/resources/ResizeHandle.css">
<link rel="stylesheet" href="css/app.css">
<script src="js/lib/jshashtable.js"></script>
<script src="js/lib/jquery-1.8.2.min.js"></script>
<script src="js/lib/underscore-min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojo/dojo.js" data-dojo-config="async: true, parseOnLoad: true, baseUrl: 'js/iD/'"></script>
<style type="text/css">
@@ -21,6 +22,15 @@
<body class="claro">
<div id="appLayout" class="demoLayout">
<script type="text/javascript" src="js/lib/underscore-min.js"></script>
<script type="text/javascript" src="js/lib/jshashtable.js"></script>
<script type="text/javascript" src="js/lib/jquery-1.8.2.min.js"></script>
<script type="text/javascript" src="js/iD/Node.js"></script>
<script type="text/javascript" src="js/iD/Relation.js"></script>
<script type="text/javascript" src="js/iD/Entity.js"></script>
<script type="text/javascript" src="js/iD/Way.js"></script>
<script type="text/javascript" src="js/iD/Connection.js"></script>
<script>
require(["dojo/_base/lang","dojo/dom-geometry","dojo/dom-class","dojo/on","dojo/dom",
+69 -68
View File
@@ -1,37 +1,28 @@
define(["dojo/_base/xhr","dojo/_base/lang","dojox/xml/DomParser","dojo/_base/array",'dojo/_base/declare',
"iD/Entity","iD/Node","iD/Way","iD/Relation","iD/actions/CreateEntityAction"],
function(xhr,lang,DomParser,array,declare,Entity){
// define(["dojo/_base/xhr","dojo/_base/lang","dojox/xml/DomParser","dojo/_base/array",'dojo/_base/declare',
// "iD/Entity","iD/Node","iD/Way","iD/Relation","iD/actions/CreateEntityAction"],
// function(xhr,lang,DomParser,array,declare,Entity){
// ----------------------------------------------------------------------
// Connection base class
declare("iD.Connection", null, {
nodes: {}, // hash of node objects
ways: {}, // hash of way objects
relations: {}, // hash of relation objects
pois: null, // list of nodes which are POIs
maps: [], // list of Map objects listening to this
callback: null, // callback once .osm is parsed
modified: false, // data has been changed
nextNode: -1, // next negative ids
nextWay: -1, // |
nextRelation: -1, // |
apiBaseURL: '', // root API address
constructor:function(apiURL) {
// summary: The data store, including methods to fetch data from (and, eventually, save data to)
// an OSM API server.
this.nodes={};
this.ways={};
this.relations={};
this.pois=new Hashtable();
this.maps=[];
this.modified=false;
this.apiBaseURL=apiURL;
},
if (typeof iD === 'undefined') iD = {};
iD.Connection = function(apiURL) {
// summary: The data store, including methods to fetch data from (and, eventually, save data to)
// an OSM API server.
this.nextNode = -1; // next negative ids
this.nextWay = -1; // |
this.nextRelation = -1; // |
this.nodes={};
this.ways={};
this.relations={};
this.pois=new Hashtable();
this.maps=[];
this.modified=false;
this.apiBaseURL=apiURL;
this.callback = null;
};
iD.Connection.prototype = {
_assign:function(obj) {
// summary: Save an entity to the data store.
switch (obj.entityType) {
@@ -45,10 +36,12 @@ declare("iD.Connection", null, {
// summary: Return a node by id.
return this.nodes[id]; // iD.Node
},
getWay:function(id) {
// summary: Return a way by id.
return this.ways[id]; // iD.Way
},
getRelation:function(id) {
// summary: Return a relation by id.
return this.relations[id]; // iD.Relation
@@ -75,12 +68,14 @@ declare("iD.Connection", null, {
perform(new iD.actions.CreateEntityAction(node, lang.hitch(this,this._assign) ));
return node; // iD.Node
},
doCreateWay:function(tags, nodes, perform) {
// summary: Create a new way and save it in the data store, using an undo stack.
var way = new iD.Way(this, this.nextWay--, nodes.concat(), tags, true);
perform(new iD.actions.CreateEntityAction(way, lang.hitch(this,this._assign) ));
return way;
},
doCreateRelation:function(tags, members, perform) {
// summary: Create a new relation and save it in the data store, using an undo stack.
var relation = new iD.Relation(this, this.nextRelation--, members.concat(), tags, true);
@@ -88,23 +83,27 @@ declare("iD.Connection", null, {
return relation;
},
getObjectsByBbox:function(left,right,top,bottom) {
// summary: Find all drawable entities that are within a given bounding box.
// returns: Object An object with four properties: .poisInside, .poisOutside, .waysInside, .waysOutside.
// Each one is an array of entities.
var o={ poisInside: [], poisOutside: [],
waysInside: [], waysOutside: [] };
for (var id in this.ways) {
var way=this.ways[id];
if (way.within(left,right,top,bottom)) { o.waysInside.push(way); }
else { o.waysOutside.push(way); }
}
this.pois.each(function(node,v) {
if (node.within(left,right,top,bottom)) { o.poisInside.push(node); }
else { o.poisOutside.push(node); }
});
return o;
},
getObjectsByBbox:function(left,right,top,bottom) {
// summary: Find all drawable entities that are within a given bounding box.
// returns: Object An object with four properties: .poisInside, .poisOutside, .waysInside, .waysOutside.
// Each one is an array of entities.
var o = {
poisInside: [],
poisOutside: [],
waysInside: [],
waysOutside: []
};
for (var id in this.ways) {
var way = this.ways[id];
if (way.within(left,right,top,bottom)) { o.waysInside.push(way); }
else { o.waysOutside.push(way); }
}
this.pois.each(function(node,v) {
if (node.within(left,right,top,bottom)) { o.poisInside.push(node); }
else { o.poisOutside.push(node); }
});
return o;
},
// ---------------
// Redraw handling
@@ -130,7 +129,6 @@ declare("iD.Connection", null, {
// ------------
// POI handling
updatePOIs:function(nodelist) {
// summary: Update the list of POIs (nodes not in ways) from a supplied array of nodes.
for (var i in nodelist) {
@@ -141,17 +139,17 @@ declare("iD.Connection", null, {
}
}
},
getPOIs:function() {
// summary: Return a list of all the POIs in this Connection.
return this.pois.keys(); // Array
},
registerPOI:function(node) {
// summary: Register a node as a POI (not in a way).
this.pois.put(node,true);
},
unregisterPOI:function(node) {
// summary: Mark a node as no longer being a POI (it's now in a way).
this.pois.remove(node);
@@ -160,25 +158,32 @@ declare("iD.Connection", null, {
// ----------
// OSM parser
loadFromAPI:function(left,right,top,bottom) {
// summary: Request data within the bbox from an external OSM server. Currently hardcoded
// to use Overpass API (which has the relevant CORS headers).
var url="http://www.overpass-api.de/api/xapi?map?bbox="+left+","+bottom+","+right+","+top;
xhr.get({ url: url,
headers: { "X-Requested-With": null },
load: lang.hitch(this, "_processOSM") });
},
loadFromAPI:function(left,right,top,bottom) {
// summary: Request data within the bbox from an external OSM server. Currently hardcoded
// to use Overpass API (which has the relevant CORS headers).
var url="http://www.overpass-api.de/api/xapi?map?bbox="+left+","+bottom+","+right+","+top;
$.ajax({
url: url,
context: this,
headers: { "X-Requested-With": null },
success: this._processOSM
});
},
loadFromURL:function(url) {
// summary: Load all data from a given URL.
xhr.get({ url: url, load: lang.hitch(this, "_processOSM") });
$.ajax({
url: url,
context: this,
success: this._processOSM
});
},
_processOSM:function(result) {
var jsdom = DomParser.parse(result).childNodes[1];
_processOSM:function(dom) {
// var jsdom = $.parseXML(result).childNodes[1];
var nodelist = [];
for (var i in jsdom.childNodes) {
var obj=jsdom.childNodes[i];
for (var i in dom.childNodes[0].childNodes) {
var obj=dom.childNodes[0].childNodes[i];
switch(obj.nodeName) {
case "node":
@@ -252,8 +257,4 @@ declare("iD.Connection", null, {
}).value();
}
}
});
// ----------------------------------------------------------------------
// End of module
});
};
+2 -2
View File
@@ -34,8 +34,8 @@ iD.Node.prototype = {
},
refresh: function() {
var ways=this.parentWays();
var conn=this.connection;
var ways= this.parentWays();
var conn= this.connection;
array.forEach(ways,function(way) { conn.refreshEntity(way); });
this.connection.refreshEntity(this);
},
+20 -20
View File
@@ -145,9 +145,9 @@ declare("iD.renderer.Map", null, {
sublayer:function(layer,groupType,sublayer) {
// summary: Find the gfx.Group for a given OSM layer and rendering sublayer, creating it
// if necessary. Note that sublayers are only implemented for stroke and fill.
// if necessary. Note that sublayers are only implemented for stroke and fill.
// groupType: String 'casing','text','hit','stroke', or 'fill'
var collection=this.layers[layer][groupType];
var collection=this.layers[layer][groupType], sub;
switch (groupType) {
case 'casing':
case 'text':
@@ -157,7 +157,7 @@ declare("iD.renderer.Map", null, {
// Find correct sublayer, inserting if necessary
var insertAt=collection.children.length;
for (var i=0; i<collection.children.length; i++) {
var sub=collection.children[i];
sub=collection.children[i];
if (sub.sublayer==sublayer) { return sub; }
else if (sub.sublayer>sublayer) {
sub=collection.createGroup();
@@ -168,7 +168,7 @@ declare("iD.renderer.Map", null, {
}
sub=collection.createGroup().moveToFront();
sub.sublayer=sublayer;
return sub; // dojox.gfx.Group
return sub; // dojox.gfx.Group
},
createUI:function(entity,stateClasses) {
@@ -193,10 +193,11 @@ declare("iD.renderer.Map", null, {
},
getUI:function(entity) {
// summary: Return the UI for an entity, if it exists.
switch (entity.entityType) {
case 'node': return this.nodeuis[entity.id]; // iD.renderer.EntityUI
case 'way': return this.wayuis[entity.id]; // iD.renderer.EntityUI
// summary: Return the UI for an entity, if it exists.
if (entity.nodeType === 'node') {
return this.nodeuis[entity.id]; // iD.renderer.EntityUI
} else if (entity.nodeType === 'way') {
return this.wayuis[entity.id]; // iD.renderer.EntityUI
}
return null;
},
@@ -204,16 +205,16 @@ declare("iD.renderer.Map", null, {
refreshUI:function(entity) {
// summary: Redraw the UI for an entity.
switch (entity.entityType) {
case 'node': if (this.nodeuis[entity.id]) { this.nodeuis[entity.id].redraw(); } break;
case 'way': if (this.wayuis[entity.id] ) { this.wayuis[entity.id].redraw(); } break;
case 'node': if (this.nodeuis[entity.id]) { this.nodeuis[entity.id].redraw(); } break;
case 'way': if (this.wayuis[entity.id] ) { this.wayuis[entity.id].redraw(); } break;
}
},
deleteUI:function(entity) {
// summary: Delete the UI for an entity.
switch (entity.entityType) {
case 'node': if (this.nodeuis[entity.id]) { this.nodeuis[entity.id].removeSprites(); delete this.nodeuis[entity.id]; } break;
case 'way': if (this.wayuis[entity.id] ) { this.wayuis[entity.id].removeSprites(); delete this.wayuis[entity.id]; } break;
case 'node':if (this.nodeuis[entity.id]) { this.nodeuis[entity.id].removeSprites(); delete this.nodeuis[entity.id]; } break;
case 'way': if (this.wayuis[entity.id] ) { this.wayuis[entity.id].removeSprites(); delete this.wayuis[entity.id]; } break;
}
},
@@ -402,12 +403,12 @@ declare("iD.renderer.Map", null, {
processMove:function(e) {
// summary: Drag the map to a new origin.
// e: MouseEvent The mouse-move event that triggered it.
var x=e.clientX;
var y=e.clientY;
var x = e.clientX;
var y = e.clientY;
if (this.dragging) {
if (this.dragx) {
this.containerx+=(x-this.dragx);
this.containery+=(y-this.dragy);
this.containerx += (x - this.dragx);
this.containery += (y - this.dragy);
this.updateOrigin();
this.dragged=true;
}
@@ -425,8 +426,8 @@ declare("iD.renderer.Map", null, {
},
_mouseEvent:function(e) {
// summary: Catch mouse events on the surface but not the tiles - in other words,
// on drawn items that don't have their own hitzones, like the fill of a shape.
// summary: Catch mouse events on the surface but not the tiles - in other words,
// on drawn items that don't have their own hitzones, like the fill of a shape.
if (e.type=='mousedown') { this.startDrag(e); }
// ** FIXME: we may want to reinstate this at some point...
// this.controller.entityMouseEvent(e,null);
@@ -487,8 +488,7 @@ declare("iD.renderer.Map", null, {
// Turn event co-ordinates into map co-ordinates
mouseX:function(e) { return e.clientX - domGeom.getMarginBox(this.div).l - this.containerx; },
mouseY:function(e) { return e.clientY - domGeom.getMarginBox(this.div).t - this.containery; },
mouseY:function(e) { return e.clientY - domGeom.getMarginBox(this.div).t - this.containery; }
});
// ----------------------------------------------------------------------
+2 -2
View File
@@ -24,8 +24,8 @@ declare("iD.renderer.NodeUI", [iD.renderer.EntityUI], {
this.removeSprites();
// Tags, position and styleList
var x= this.map.lon2coord(this.entity.lon);
var y= this.map.latp2coord(this.entity.latp);
var x = Math.floor(this.map.lon2coord(this.entity.lon));
var y = Math.floor(this.map.latp2coord(this.entity.latp));
var tags = this.getEnhancedTags();
this.refreshStyleList(tags);
+46 -46
View File
@@ -16,12 +16,12 @@ declare("iD.styleparser.RuleSet", null, {
// summary: An entire stylesheet in parsed form.
this.choosers=[];
},
registerCallback:function(callback) {
// summary: Set a callback function to be called when the CSS is loaded and parsed.
this.callback=callback;
},
getStyles:function(entity, tags, zoom) {
// summary: Find the styles for a given entity.
var sl=new iD.styleparser.StyleList();
@@ -35,13 +35,13 @@ declare("iD.styleparser.RuleSet", null, {
// summary: Load a MapCSS file from a URL, then throw it at the parser when it's loaded.
xhr.get({ url: url, load: lang.hitch(this, "parseCSS") });
},
parseCSS:function(css) {
// summary: Parse a CSS document into a set of StyleChoosers.
var previous=0; // what was the previous CSS word?
var sc=new iD.styleparser.StyleChooser(); // currently being assembled
this.choosers=[];
css=css.replace(/[\r\n]/g,""); // strip linebreaks because JavaScript doesn't have the /s modifier
css = css.replace(/[\r\n]/g,""); // strip linebreaks because JavaScript doesn't have the /s modifier
var o={};
while (css.length>0) {
@@ -139,12 +139,12 @@ declare("iD.styleparser.RuleSet", null, {
var o={};
var k, v;
// Create styles
var ss=new iD.styleparser.ShapeStyle() ;
var ps=new iD.styleparser.PointStyle() ;
var ts=new iD.styleparser.TextStyle() ;
var hs=new iD.styleparser.ShieldStyle();
var xs=new iD.styleparser.InstructionStyle();
// Create styles
var ss = new iD.styleparser.ShapeStyle();
var ps = new iD.styleparser.PointStyle();
var ts = new iD.styleparser.TextStyle();
var hs = new iD.styleparser.ShieldStyle();
var xs = new iD.styleparser.InstructionStyle();
var r=s.split(';');
var isEval={};
@@ -163,39 +163,39 @@ declare("iD.styleparser.RuleSet", null, {
if (t['z_index']) { sub=Number(t['z_index']); delete t['z_index']; }
ss.sublayer=ps.sublayer=ts.sublayer=hs.sublayer=sub;
xs.sublayer=10;
// Find "interactive" property - it's true unless explicitly set false
var inter=true;
if (t['interactive']) { inter=t['interactive'].match(this.FALSE) ? false : true; delete t['interactive']; }
ss.interactive=ps.interactive=ts.interactive=hs.interactive=xs.interactive=inter;
// Munge special values
// (we should stop doing this and do it in the style instead)
if (t['font_weight'] ) { t['font_bold' ] = t['font_weight' ].match(this.BOLD ) ? true : false; delete t['font_weight']; }
if (t['font_style'] ) { t['font_italic'] = t['font_style' ].match(this.ITALIC) ? true : false; delete t['font_style']; }
if (t['text_decoration']) { t['font_underline'] = t['text_decoration'].match(this.UNDERLINE) ? true : false; delete t['text_decoration']; }
if (t['text_position'] ) { t['text_center'] = t['text_position' ].match(this.CENTER) ? true : false; delete t['text_position']; }
if (t['text_transform']) {
if (t['text_transform'].match(this.CAPS)) { t['font_caps']=true; } else { t['font_caps']=false; }
delete t['text_transform'];
}
// Munge special values
// (we should stop doing this and do it in the style instead)
if (t['font_weight'] ) { t['font_bold' ] = t['font_weight' ].match(this.BOLD ) ? true : false; delete t['font_weight']; }
if (t['font_style'] ) { t['font_italic'] = t['font_style' ].match(this.ITALIC) ? true : false; delete t['font_style']; }
if (t['text_decoration']) { t['font_underline'] = t['text_decoration'].match(this.UNDERLINE) ? true : false; delete t['text_decoration']; }
if (t['text_position'] ) { t['text_center'] = t['text_position' ].match(this.CENTER) ? true : false; delete t['text_position']; }
if (t['text_transform']) {
if (t['text_transform'].match(this.CAPS)) { t['font_caps']=true; } else { t['font_caps']=false; }
delete t['text_transform'];
}
// Assign each property to the appropriate style
for (a in t) {
// Parse properties
// ** also do units, e.g. px/pt/m
if (a.match(this.COLOR)) { v = this.parseCSSColor(t[a]); }
else { v = t[a]; }
// Set in styles
if (ss.has(a)) { ss.setPropertyFromString(a,v,isEval[a]); }
else if (ps.has(a)) { ps.setPropertyFromString(a,v,isEval[a]); }
else if (ts.has(a)) { ts.setPropertyFromString(a,v,isEval[a]); }
else if (hs.has(a)) { hs.setPropertyFromString(a,v,isEval[a]); }
else { console.log(a+" not found"); }
}
// Assign each property to the appropriate style
for (a in t) {
// Parse properties
// ** also do units, e.g. px/pt/m
if (a.match(this.COLOR)) { v = this.parseCSSColor(t[a]); }
else { v = t[a]; }
// Add each style to list
// Set in styles
if (ss.has(a)) { ss.setPropertyFromString(a,v,isEval[a]); }
else if (ps.has(a)) { ps.setPropertyFromString(a,v,isEval[a]); }
else if (ts.has(a)) { ts.setPropertyFromString(a,v,isEval[a]); }
else if (hs.has(a)) { hs.setPropertyFromString(a,v,isEval[a]); }
else { console.log(a+" not found"); }
}
// Add each style to list
if (ss.edited) { styles.push(ss); }
if (ps.edited) { styles.push(ps); }
if (ts.edited) { styles.push(ts); }
@@ -203,7 +203,7 @@ declare("iD.styleparser.RuleSet", null, {
if (xs.edited) { styles.push(xs); }
return styles;
},
parseZoom:function(s) {
var o={};
if ((o=this.ZOOM_MINMAX.exec(s))) { return [o[1],o[2]]; }
@@ -250,7 +250,7 @@ declare("iD.styleparser.RuleSet", null, {
}
return 0;
},
// Regular expression tests and other constants
WHITESPACE :/^\s+/,
@@ -287,16 +287,16 @@ declare("iD.styleparser.RuleSet", null, {
SET_TAG_EVAL :/^\s*set\s+(\S+)\s*=\s*eval\s*\(\s*'(.+?)'\s*\)\s*$/i,
SET_TAG :/^\s*set\s+(\S+)\s*=\s*(.+?)\s*$/i,
SET_TAG_TRUE :/^\s*set\s+(\S+)\s*$/i,
EXIT :/^\s*exit\s*$/i,
EXIT :/^\s*exit\s*$/i,
oZOOM: 2,
oGROUP: 3,
oCONDITION: 4,
oOBJECT: 5,
oDECLARATION: 6,
oSUBPART: 7,
oZOOM: 2,
oGROUP: 3,
oCONDITION: 4,
oOBJECT: 5,
oDECLARATION: 6,
oSUBPART: 7,
DASH: /\-/g,
DASH: /\-/g,
COLOR: /color$/,
BOLD: /^bold$/i,
ITALIC: /^italic|oblique$/i,
+2 -2
View File
@@ -211,13 +211,13 @@ declare("iD.styleparser.TextStyle", [iD.styleparser.Style], {
return {
decoration: this.font_underline ? 'underline' : 'none',
align: 'middle',
text: _text,
text: _text
};
},
fillStyler:function() {
// not implemented yet
return this.dojoColor(0,1);
},
}
// getTextFormat, getHaloFilter, writeNameLabel
});
+2
View File
File diff suppressed because one or more lines are too long
+15 -6
View File
@@ -20,7 +20,7 @@ way[highway=primary],way[highway=primary_link],
way[highway=secondary],way[highway=secondary_link],
way[highway=tertiary],way[highway=tertiary_link],
way[highway=unclassified],
way[highway=residential] { text: name; text-color: black; font-size: 7; text-position: line;}
way[highway=residential] { text: name; text-color: black; font-size: 6; text-position: line;}
way[highway=motorway],way[highway=motorway_link] { z-index: 9; color: #809BC0; width: 7; casing-color: black; casing-width: 1; }
way[highway=trunk],way[highway=trunk_link] { z-index: 9; color: #7FC97F; width: 7; casing-color: black; casing-width: 1; }
way[highway=primary],way[highway=primary_link] { z-index: 8; color: #E46D71; width: 7; casing-color: black; casing-width: 1; }
@@ -40,13 +40,22 @@ way[highway=bridleway] { z-index:9; color: #996644; width: 2; dashes: 4, 2, 2, 2
way[highway=track] { color: #996644; width: 2; dashes: 4, 2; }
way[highway=path] { color: lightgreen; width: 2; dashes: 2, 2; }
way[waterway=river], way[waterway=canal] { color: blue; width: 2; text:name; text-color:blue; font-size:9; text-position: offset; text-offset: 7;}
way[waterway=river], way[waterway=canal] {
casing-width: 1;
casing-color: #6eafd4;
color: #10539a;
width: 3;
text:name;
text-color:blue;
font-size:7;
text-position: offset;
text-offset: -5;
}
way[barrier] {color: #000000; width: 1}
/* Fills can be solid colour or bitmap images */
way[natural] :area { color: #ADD6A5; width: 1; fill-color: #ADD6A5; fill-opacity: 0.2; }
way[landuse] :area { color: #444444; width: 2; fill-color: #444444; fill-opacity: 0.3; }
way[amenity],way[shop] :area { color: #ADCEB5; width: 1; fill-color: #ADCEB5; fill-opacity: 0.2; }
@@ -96,7 +105,7 @@ node[amenity=school] { icon-image: icons/school.png; icon-width: 16; }
node[amenity=taxi] { icon-image: icons/taxi.png; icon-width: 16; }
node[amenity=telephone] { icon-image: icons/telephone.png; icon-width: 16; }
way node[barrier=gate], way node[highway=gate] { icon-image: icons/gate.png; icon-width: 7; }
/* We can stack styles at different z-index (depth) */
way[railway=rail]
@@ -110,7 +119,7 @@ way[railway=subway]
way[bridge=yes]
{ z-index: 4; color: white; width: eval('_width+3'); }
{ z-index: 3; color: black; width: eval('_width+6'); }
/* Tunnel */
way[tunnel=yes]
{ z-index: 4; color: white; width: eval('_width+2'); }
@@ -138,7 +147,7 @@ node !:drawn :poi { z-index: 2; icon-image: circle; icon-width: 4; color: green;
node :hoverway { z-index: 9; icon-image: square; icon-width: 7; color: blue; layer: 5; }
node::highlight :selected { z-index: 1; icon-image: square; icon-width: eval('_width+10'); color: yellow; }
/* Descendant selectors provide an easy way to style relations: this example means "any way
which is part of a relation whose type=route". */
+3
View File
@@ -12,16 +12,19 @@
<!-- include source files here... -->
<script type="text/javascript" src="../js/lib/underscore-min.js"></script>
<script type="text/javascript" src="../js/lib/jshashtable.js"></script>
<script type="text/javascript" src="../js/lib/jquery-1.8.2.min.js"></script>
<script type="text/javascript" src="../js/iD/Node.js"></script>
<script type="text/javascript" src="../js/iD/Relation.js"></script>
<script type="text/javascript" src="../js/iD/Entity.js"></script>
<script type="text/javascript" src="../js/iD/Way.js"></script>
<script type="text/javascript" src="../js/iD/Connection.js"></script>
<!-- include spec files here... -->
<script type="text/javascript" src="spec/Node.js"></script>
<script type="text/javascript" src="spec/Entity.js"></script>
<script type="text/javascript" src="spec/Relation.js"></script>
<script type="text/javascript" src="spec/Way.js"></script>
<script type="text/javascript" src="spec/Connection.js"></script>
<script type="text/javascript">
(function() {
+11
View File
@@ -0,0 +1,11 @@
describe('Connection', function() {
var c;
beforeEach(function() {
c = new iD.Connection();
});
it('is instantiated', function() {
expect(c).toBeTruthy();
});
});