123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406 |
- if (!org) var org = {};
- if (!org.polymaps) org.polymaps = {};
- (function(po){
- po.version = "2.5.1"; // semver.org
- var zero = {x: 0, y: 0};
- po.ns = {
- svg: "http://www.w3.org/2000/svg",
- xlink: "http://www.w3.org/1999/xlink"
- };
- function ns(name) {
- var i = name.indexOf(":");
- return i < 0 ? name : {
- space: po.ns[name.substring(0, i)],
- local: name.substring(i + 1)
- };
- }
- po.id = (function() {
- var id = 0;
- return function() {
- return ++id;
- };
- })();
- po.svg = function(type) {
- return document.createElementNS(po.ns.svg, type);
- };
- po.transform = function(a, b, c, d, e, f) {
- var transform = {},
- zoomDelta,
- zoomFraction,
- k;
- if (!arguments.length) {
- a = 1; c = 0; e = 0;
- b = 0; d = 1; f = 0;
- }
- transform.zoomFraction = function(x) {
- if (!arguments.length) return zoomFraction;
- zoomFraction = x;
- zoomDelta = Math.floor(zoomFraction + Math.log(Math.sqrt(a * a + b * b + c * c + d * d)) / Math.LN2);
- k = Math.pow(2, -zoomDelta);
- return transform;
- };
- transform.apply = function(x) {
- var k0 = Math.pow(2, -x.zoom),
- k1 = Math.pow(2, x.zoom - zoomDelta);
- return {
- column: (a * x.column * k0 + c * x.row * k0 + e) * k1,
- row: (b * x.column * k0 + d * x.row * k0 + f) * k1,
- zoom: x.zoom - zoomDelta
- };
- };
- transform.unapply = function(x) {
- var k0 = Math.pow(2, -x.zoom),
- k1 = Math.pow(2, x.zoom + zoomDelta);
- return {
- column: (x.column * k0 * d - x.row * k0 * c - e * d + f * c) / (a * d - b * c) * k1,
- row: (x.column * k0 * b - x.row * k0 * a - e * b + f * a) / (c * b - d * a) * k1,
- zoom: x.zoom + zoomDelta
- };
- };
- transform.toString = function() {
- return "matrix(" + [a * k, b * k, c * k, d * k].join(" ") + " 0 0)";
- };
- return transform.zoomFraction(0);
- };
- po.cache = function(load, unload) {
- var cache = {},
- locks = {},
- map = {},
- head = null,
- tail = null,
- size = 64,
- n = 0;
- function remove(tile) {
- n--;
- if (unload) unload(tile);
- delete map[tile.key];
- if (tile.next) tile.next.prev = tile.prev;
- else if (tail = tile.prev) tail.next = null;
- if (tile.prev) tile.prev.next = tile.next;
- else if (head = tile.next) head.prev = null;
- }
- function flush() {
- for (var tile = tail; n > size; tile = tile.prev) {
- if (!tile) break;
- if (tile.lock) continue;
- remove(tile);
- }
- }
- cache.peek = function(c) {
- return map[[c.zoom, c.column, c.row].join("/")];
- };
- cache.load = function(c, projection) {
- var key = [c.zoom, c.column, c.row].join("/"),
- tile = map[key];
- if (tile) {
- if (tile.prev) {
- tile.prev.next = tile.next;
- if (tile.next) tile.next.prev = tile.prev;
- else tail = tile.prev;
- tile.prev = null;
- tile.next = head;
- head.prev = tile;
- head = tile;
- }
- tile.lock = 1;
- locks[key] = tile;
- return tile;
- }
- tile = {
- key: key,
- column: c.column,
- row: c.row,
- zoom: c.zoom,
- next: head,
- prev: null,
- lock: 1
- };
- load.call(null, tile, projection);
- locks[key] = map[key] = tile;
- if (head) head.prev = tile;
- else tail = tile;
- head = tile;
- n++;
- return tile;
- };
- cache.unload = function(key) {
- if (!(key in locks)) return false;
- var tile = locks[key];
- tile.lock = 0;
- delete locks[key];
- if (tile.request && tile.request.abort(false)) remove(tile);
- return tile;
- };
- cache.locks = function() {
- return locks;
- };
- cache.size = function(x) {
- if (!arguments.length) return size;
- size = x;
- flush();
- return cache;
- };
- cache.flush = function() {
- flush();
- return cache;
- };
- cache.clear = function() {
- for (var key in map) {
- var tile = map[key];
- if (tile.request) tile.request.abort(false);
- if (unload) unload(map[key]);
- if (tile.lock) {
- tile.lock = 0;
- tile.element.parentNode.removeChild(tile.element);
- }
- }
- locks = {};
- map = {};
- head = tail = null;
- n = 0;
- return cache;
- };
- return cache;
- };
- po.url = function(template) {
- var hosts = [],
- repeat = true;
- function format(c) {
- var max = c.zoom < 0 ? 1 : 1 << c.zoom,
- column = c.column;
- if (repeat) {
- column = c.column % max;
- if (column < 0) column += max;
- } else if ((column < 0) || (column >= max)) {
- return null;
- }
- return template.replace(/{(.)}/g, function(s, v) {
- switch (v) {
- case "S": return hosts[(Math.abs(c.zoom) + c.row + column) % hosts.length];
- case "Z": return c.zoom;
- case "X": return column;
- case "Y": return c.row;
- case "B": {
- var nw = po.map.coordinateLocation({row: c.row, column: column, zoom: c.zoom}),
- se = po.map.coordinateLocation({row: c.row + 1, column: column + 1, zoom: c.zoom}),
- pn = Math.ceil(Math.log(c.zoom) / Math.LN2);
- return se.lat.toFixed(pn)
- + "," + nw.lon.toFixed(pn)
- + "," + nw.lat.toFixed(pn)
- + "," + se.lon.toFixed(pn);
- }
- }
- return v;
- });
- }
- format.template = function(x) {
- if (!arguments.length) return template;
- template = x;
- return format;
- };
- format.hosts = function(x) {
- if (!arguments.length) return hosts;
- hosts = x;
- return format;
- };
- format.repeat = function(x) {
- if (!arguments.length) return repeat;
- repeat = x;
- return format;
- };
- return format;
- };
- po.dispatch = function(that) {
- var types = {};
- that.on = function(type, handler) {
- var listeners = types[type] || (types[type] = []);
- for (var i = 0; i < listeners.length; i++) {
- if (listeners[i].handler == handler) return that; // already registered
- }
- listeners.push({handler: handler, on: true});
- return that;
- };
- that.off = function(type, handler) {
- var listeners = types[type];
- if (listeners) for (var i = 0; i < listeners.length; i++) {
- var l = listeners[i];
- if (l.handler == handler) {
- l.on = false;
- listeners.splice(i, 1);
- break;
- }
- }
- return that;
- };
- return function(event) {
- var listeners = types[event.type];
- if (!listeners) return;
- listeners = listeners.slice(); // defensive copy
- for (var i = 0; i < listeners.length; i++) {
- var l = listeners[i];
- if (l.on) l.handler.call(that, event);
- }
- };
- };
- po.queue = (function() {
- var queued = [], active = 0, size = 6;
- function process() {
- if ((active >= size) || !queued.length) return;
- active++;
- queued.pop()();
- }
- function dequeue(send) {
- for (var i = 0; i < queued.length; i++) {
- if (queued[i] == send) {
- queued.splice(i, 1);
- return true;
- }
- }
- return false;
- }
- function request(url, callback, mimeType) {
- var req;
- function send() {
- req = new XMLHttpRequest();
- if (mimeType && req.overrideMimeType) {
- req.overrideMimeType(mimeType);
- }
- req.open("GET", url, true);
- req.onreadystatechange = function(e) {
- if (req.readyState == 4) {
- active--;
- if (req.status < 300) callback(req);
- process();
- }
- };
- req.send(null);
- }
- function abort(hard) {
- if (dequeue(send)) return true;
- if (hard && req) { req.abort(); return true; }
- return false;
- }
- queued.push(send);
- process();
- return {abort: abort};
- }
- function text(url, callback, mimeType) {
- return request(url, function(req) {
- if (req.responseText) callback(req.responseText);
- }, mimeType);
- }
- /*
- * We the override MIME type here so that you can load local files; some
- * browsers don't assign a proper MIME type for local files.
- */
- function json(url, callback) {
- return request(url, function(req) {
- if (req.responseText) callback(JSON.parse(req.responseText));
- }, "application/json");
- }
- function xml(url, callback) {
- return request(url, function(req) {
- if (req.responseXML) callback(req.responseXML);
- }, "application/xml");
- }
- function image(image, src, callback) {
- var img;
- function send() {
- img = document.createElement("img");
- img.onerror = function() {
- active--;
- process();
- };
- img.onload = function() {
- active--;
- callback(img);
- process();
- };
- img.src = src;
- image.setAttributeNS(po.ns.xlink, "href", src);
- }
- function abort(hard) {
- if (dequeue(send)) return true;
- if (hard && img) { img.src = "about:"; return true; } // cancels request
- return false;
- }
- queued.push(send);
- process();
- return {abort: abort};
- }
- return {text: text, xml: xml, json: json, image: image};
- })();
- po.map = function() {
- var map = {},
- container,
- size,
- sizeActual = zero,
- sizeRadius = zero, // sizeActual / 2
- tileSize = {x: 256, y: 256},
- center = {lat: 37.76487, lon: -122.41948},
- zoom = 12,
- zoomFraction = 0,
- zoomFactor = 1, // Math.pow(2, zoomFraction)
- zoomRange = [1, 18],
- angle = 0,
- angleCos = 1, // Math.cos(angle)
- angleSin = 0, // Math.sin(angle)
- angleCosi = 1, // Math.cos(-angle)
- angleSini = 0, // Math.sin(-angle)
- ymin = -180, // lat2y(centerRange[0].lat)
- ymax = 180; // lat2y(centerRange[1].lat)
- var centerRange = [
- {lat: y2lat(ymin), lon: -Infinity},
- {lat: y2lat(ymax), lon: Infinity}
- ];
- map.locationCoordinate = function(l) {
- var c = po.map.locationCoordinate(l),
- k = Math.pow(2, zoom);
- c.column *= k;
- c.row *= k;
- c.zoom += zoom;
- return c;
- };
- map.coordinateLocation = po.map.coordinateLocation;
- map.coordinatePoint = function(tileCenter, c) {
- var kc = Math.pow(2, zoom - c.zoom),
- kt = Math.pow(2, zoom - tileCenter.zoom),
- dx = (c.column * kc - tileCenter.column * kt) * tileSize.x * zoomFactor,
- dy = (c.row * kc - tileCenter.row * kt) * tileSize.y * zoomFactor;
- return {
- x: sizeRadius.x + angleCos * dx - angleSin * dy,
- y: sizeRadius.y + angleSin * dx + angleCos * dy
- };
- };
- map.pointCoordinate = function(tileCenter, p) {
- var kt = Math.pow(2, zoom - tileCenter.zoom),
- dx = (p.x - sizeRadius.x) / zoomFactor,
- dy = (p.y - sizeRadius.y) / zoomFactor;
- return {
- column: tileCenter.column * kt + (angleCosi * dx - angleSini * dy) / tileSize.x,
- row: tileCenter.row * kt + (angleSini * dx + angleCosi * dy) / tileSize.y,
- zoom: zoom
- };
- };
- map.locationPoint = function(l) {
- var k = Math.pow(2, zoom + zoomFraction - 3) / 45,
- dx = (l.lon - center.lon) * k * tileSize.x,
- dy = (lat2y(center.lat) - lat2y(l.lat)) * k * tileSize.y;
- return {
- x: sizeRadius.x + angleCos * dx - angleSin * dy,
- y: sizeRadius.y + angleSin * dx + angleCos * dy
- };
- };
- map.pointLocation = function(p) {
- var k = 45 / Math.pow(2, zoom + zoomFraction - 3),
- dx = (p.x - sizeRadius.x) * k,
- dy = (p.y - sizeRadius.y) * k;
- return {
- lon: center.lon + (angleCosi * dx - angleSini * dy) / tileSize.x,
- lat: y2lat(lat2y(center.lat) - (angleSini * dx + angleCosi * dy) / tileSize.y)
- };
- };
- function rezoom() {
- if (zoomRange) {
- if (zoom < zoomRange[0]) zoom = zoomRange[0];
- else if (zoom > zoomRange[1]) zoom = zoomRange[1];
- }
- zoomFraction = zoom - (zoom = Math.round(zoom));
- zoomFactor = Math.pow(2, zoomFraction);
- }
- function recenter() {
- if (!centerRange) return;
- var k = 45 / Math.pow(2, zoom + zoomFraction - 3);
- // constrain latitude
- var y = Math.max(Math.abs(angleSin * sizeRadius.x + angleCos * sizeRadius.y),
- Math.abs(angleSini * sizeRadius.x + angleCosi * sizeRadius.y)),
- lat0 = y2lat(ymin - y * k / tileSize.y),
- lat1 = y2lat(ymax + y * k / tileSize.y);
- center.lat = Math.max(lat0, Math.min(lat1, center.lat));
- // constrain longitude
- var x = Math.max(Math.abs(angleSin * sizeRadius.y + angleCos * sizeRadius.x),
- Math.abs(angleSini * sizeRadius.y + angleCosi * sizeRadius.x)),
- lon0 = centerRange[0].lon - x * k / tileSize.x,
- lon1 = centerRange[1].lon + x * k / tileSize.x;
- center.lon = Math.max(lon0, Math.min(lon1, center.lon));
- }
- // a place to capture mouse events if no tiles exist
- var rect = po.svg("rect");
- rect.setAttribute("visibility", "hidden");
- rect.setAttribute("pointer-events", "all");
- map.container = function(x) {
- if (!arguments.length) return container;
- container = x;
- container.setAttribute("class", "map");
- container.appendChild(rect);
- return map.resize(); // infer size
- };
- map.focusableParent = function() {
- for (var p = container; p; p = p.parentNode) {
- if (p.tabIndex >= 0) return p;
- }
- return window;
- };
- map.mouse = function(e) {
- var point = (container.ownerSVGElement || container).createSVGPoint();
- if ((bug44083 < 0) && (window.scrollX || window.scrollY)) {
- var svg = document.body.appendChild(po.svg("svg"));
- svg.style.position = "absolute";
- svg.style.top = svg.style.left = "0px";
- var ctm = svg.getScreenCTM();
- bug44083 = !(ctm.f || ctm.e);
- document.body.removeChild(svg);
- }
- if (bug44083) {
- point.x = e.pageX;
- point.y = e.pageY;
- } else {
- point.x = e.clientX;
- point.y = e.clientY;
- }
- return point.matrixTransform(container.getScreenCTM().inverse());
- };
- map.size = function(x) {
- if (!arguments.length) return sizeActual;
- size = x;
- return map.resize(); // size tiles
- };
- map.resize = function() {
- if (!size) {
- rect.setAttribute("width", "100%");
- rect.setAttribute("height", "100%");
- b = rect.getBBox();
- sizeActual = {x: b.width, y: b.height};
- resizer.add(map);
- } else {
- sizeActual = size;
- resizer.remove(map);
- }
- rect.setAttribute("width", sizeActual.x);
- rect.setAttribute("height", sizeActual.y);
- sizeRadius = {x: sizeActual.x / 2, y: sizeActual.y / 2};
- recenter();
- map.dispatch({type: "resize"});
- return map;
- };
- map.tileSize = function(x) {
- if (!arguments.length) return tileSize;
- tileSize = x;
- map.dispatch({type: "move"});
- return map;
- };
- map.center = function(x) {
- if (!arguments.length) return center;
- center = x;
- recenter();
- map.dispatch({type: "move"});
- return map;
- };
- map.panBy = function(x) {
- var k = 45 / Math.pow(2, zoom + zoomFraction - 3),
- dx = x.x * k,
- dy = x.y * k;
- return map.center({
- lon: center.lon + (angleSini * dy - angleCosi * dx) / tileSize.x,
- lat: y2lat(lat2y(center.lat) + (angleSini * dx + angleCosi * dy) / tileSize.y)
- });
- };
- map.centerRange = function(x) {
- if (!arguments.length) return centerRange;
- centerRange = x;
- if (centerRange) {
- ymin = centerRange[0].lat > -90 ? lat2y(centerRange[0].lat) : -Infinity;
- ymax = centerRange[0].lat < 90 ? lat2y(centerRange[1].lat) : Infinity;
- } else {
- ymin = -Infinity;
- ymax = Infinity;
- }
- recenter();
- map.dispatch({type: "move"});
- return map;
- };
- map.zoom = function(x) {
- if (!arguments.length) return zoom + zoomFraction;
- zoom = x;
- rezoom();
- return map.center(center);
- };
- map.zoomBy = function(z, x0, l) {
- if (arguments.length < 2) return map.zoom(zoom + zoomFraction + z);
- // compute the location of x0
- if (arguments.length < 3) l = map.pointLocation(x0);
- // update the zoom level
- zoom = zoom + zoomFraction + z;
- rezoom();
- // compute the new point of the location
- var x1 = map.locationPoint(l);
- return map.panBy({x: x0.x - x1.x, y: x0.y - x1.y});
- };
- map.zoomRange = function(x) {
- if (!arguments.length) return zoomRange;
- zoomRange = x;
- return map.zoom(zoom + zoomFraction);
- };
- map.extent = function(x) {
- if (!arguments.length) return [
- map.pointLocation({x: 0, y: sizeActual.y}),
- map.pointLocation({x: sizeActual.x, y: 0})
- ];
- // compute the extent in points, scale factor, and center
- var bl = map.locationPoint(x[0]),
- tr = map.locationPoint(x[1]),
- k = Math.max((tr.x - bl.x) / sizeActual.x, (bl.y - tr.y) / sizeActual.y),
- l = map.pointLocation({x: (bl.x + tr.x) / 2, y: (bl.y + tr.y) / 2});
- // update the zoom level
- zoom = zoom + zoomFraction - Math.log(k) / Math.LN2;
- rezoom();
- // set the new center
- return map.center(l);
- };
- map.angle = function(x) {
- if (!arguments.length) return angle;
- angle = x;
- angleCos = Math.cos(angle);
- angleSin = Math.sin(angle);
- angleCosi = Math.cos(-angle);
- angleSini = Math.sin(-angle);
- recenter();
- map.dispatch({type: "move"});
- return map;
- };
- map.add = function(x) {
- x.map(map);
- return map;
- };
- map.remove = function(x) {
- x.map(null);
- return map;
- };
- map.dispatch = po.dispatch(map);
- return map;
- };
- function resizer(e) {
- for (var i = 0; i < resizer.maps.length; i++) {
- resizer.maps[i].resize();
- }
- }
- resizer.maps = [];
- resizer.add = function(map) {
- for (var i = 0; i < resizer.maps.length; i++) {
- if (resizer.maps[i] == map) return;
- }
- resizer.maps.push(map);
- };
- resizer.remove = function(map) {
- for (var i = 0; i < resizer.maps.length; i++) {
- if (resizer.maps[i] == map) {
- resizer.maps.splice(i, 1);
- return;
- }
- }
- };
- // Note: assumes single window (no frames, iframes, etc.)!
- if (window.addEventListener) {
- window.addEventListener("resize", resizer, false);
- window.addEventListener("load", resizer, false);
- }
- // See http://wiki.openstreetmap.org/wiki/Mercator
- function y2lat(y) {
- return 360 / Math.PI * Math.atan(Math.exp(y * Math.PI / 180)) - 90;
- }
- function lat2y(lat) {
- return 180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + lat * Math.PI / 360));
- }
- po.map.locationCoordinate = function(l) {
- var k = 1 / 360;
- return {
- column: (l.lon + 180) * k,
- row: (180 - lat2y(l.lat)) * k,
- zoom: 0
- };
- };
- po.map.coordinateLocation = function(c) {
- var k = 45 / Math.pow(2, c.zoom - 3);
- return {
- lon: k * c.column - 180,
- lat: y2lat(180 - k * c.row)
- };
- };
- // https://bugs.webkit.org/show_bug.cgi?id=44083
- var bug44083 = /WebKit/.test(navigator.userAgent) ? -1 : 0;
- po.layer = function(load, unload) {
- var layer = {},
- cache = layer.cache = po.cache(load, unload).size(512),
- tile = true,
- visible = true,
- zoom,
- id,
- map,
- container = po.svg("g"),
- transform,
- levelZoom,
- levels = {};
- container.setAttribute("class", "layer");
- for (var i = -4; i <= -1; i++) levels[i] = container.appendChild(po.svg("g"));
- for (var i = 2; i >= 1; i--) levels[i] = container.appendChild(po.svg("g"));
- levels[0] = container.appendChild(po.svg("g"));
- function zoomIn(z) {
- var end = levels[0].nextSibling;
- for (; levelZoom < z; levelZoom++) {
- // -4, -3, -2, -1, +2, +1, =0 // current order
- // -3, -2, -1, +2, +1, =0, -4 // insertBefore(-4, end)
- // -3, -2, -1, +1, =0, -4, +2 // insertBefore(+2, end)
- // -3, -2, -1, =0, -4, +2, +1 // insertBefore(+1, end)
- // -4, -3, -2, -1, +2, +1, =0 // relabel
- container.insertBefore(levels[-4], end);
- container.insertBefore(levels[2], end);
- container.insertBefore(levels[1], end);
- var t = levels[-4];
- for (var dz = -4; dz < 2;) levels[dz] = levels[++dz];
- levels[dz] = t;
- }
- }
- function zoomOut(z) {
- var end = levels[0].nextSibling;
- for (; levelZoom > z; levelZoom--) {
- // -4, -3, -2, -1, +2, +1, =0 // current order
- // -4, -3, -2, +2, +1, =0, -1 // insertBefore(-1, end)
- // +2, -4, -3, -2, +1, =0, -1 // insertBefore(+2, -4)
- // -4, -3, -2, -1, +2, +1, =0 // relabel
- container.insertBefore(levels[-1], end);
- container.insertBefore(levels[2], levels[-4]);
- var t = levels[2];
- for (var dz = 2; dz > -4;) levels[dz] = levels[--dz];
- levels[dz] = t;
- }
- }
- function move() {
- var map = layer.map(), // in case the layer is removed
- mapZoom = map.zoom(),
- mapZoomFraction = mapZoom - (mapZoom = Math.round(mapZoom)),
- mapSize = map.size(),
- mapAngle = map.angle(),
- tileSize = map.tileSize(),
- tileCenter = map.locationCoordinate(map.center());
- // set the layer zoom levels
- if (levelZoom != mapZoom) {
- if (levelZoom < mapZoom) zoomIn(mapZoom);
- else if (levelZoom > mapZoom) zoomOut(mapZoom);
- else levelZoom = mapZoom;
- for (var z = -4; z <= 2; z++) {
- var l = levels[z];
- l.setAttribute("class", "zoom" + (z < 0 ? "" : "+") + z + " zoom" + (mapZoom + z));
- l.setAttribute("transform", "scale(" + Math.pow(2, -z) + ")");
- }
- }
- // set the layer transform
- container.setAttribute("transform",
- "translate(" + (mapSize.x / 2) + "," + (mapSize.y / 2) + ")"
- + (mapAngle ? "rotate(" + mapAngle / Math.PI * 180 + ")" : "")
- + (mapZoomFraction ? "scale(" + Math.pow(2, mapZoomFraction) + ")" : "")
- + (transform ? transform.zoomFraction(mapZoomFraction) : ""));
- // get the coordinates of the four corners
- var c0 = map.pointCoordinate(tileCenter, zero),
- c1 = map.pointCoordinate(tileCenter, {x: mapSize.x, y: 0}),
- c2 = map.pointCoordinate(tileCenter, mapSize),
- c3 = map.pointCoordinate(tileCenter, {x: 0, y: mapSize.y});
- // round to pixel boundary to avoid anti-aliasing artifacts
- if (!mapZoomFraction && !mapAngle && !transform) {
- tileCenter.column = (Math.round(tileSize.x * tileCenter.column) + (mapSize.x & 1) / 2) / tileSize.x;
- tileCenter.row = (Math.round(tileSize.y * tileCenter.row) + (mapSize.y & 1) / 2) / tileSize.y;
- }
- // layer-specific coordinate transform
- if (transform) {
- c0 = transform.unapply(c0);
- c1 = transform.unapply(c1);
- c2 = transform.unapply(c2);
- c3 = transform.unapply(c3);
- tileCenter = transform.unapply(tileCenter);
- }
- // layer-specific zoom transform
- var tileLevel = zoom ? zoom(c0.zoom) - c0.zoom : 0;
- if (tileLevel) {
- var k = Math.pow(2, tileLevel);
- c0.column *= k; c0.row *= k;
- c1.column *= k; c1.row *= k;
- c2.column *= k; c2.row *= k;
- c3.column *= k; c3.row *= k;
- c0.zoom = c1.zoom = c2.zoom = c3.zoom += tileLevel;
- }
- // tile-specific projection
- function projection(c) {
- var zoom = c.zoom,
- max = zoom < 0 ? 1 : 1 << zoom,
- column = c.column % max,
- row = c.row;
- if (column < 0) column += max;
- return {
- locationPoint: function(l) {
- var c = po.map.locationCoordinate(l),
- k = Math.pow(2, zoom - c.zoom);
- return {
- x: tileSize.x * (k * c.column - column),
- y: tileSize.y * (k * c.row - row)
- };
- }
- };
- }
- // record which tiles are visible
- var oldLocks = cache.locks(), newLocks = {};
- // reset the proxy counts
- for (var key in oldLocks) {
- oldLocks[key].proxyCount = 0;
- }
- // load the tiles!
- if (visible && tileLevel > -5 && tileLevel < 3) {
- var ymax = c0.zoom < 0 ? 1 : 1 << c0.zoom;
- if (tile) {
- scanTriangle(c0, c1, c2, 0, ymax, scanLine);
- scanTriangle(c2, c3, c0, 0, ymax, scanLine);
- } else {
- var x = Math.floor((c0.column + c2.column) / 2),
- y = Math.max(0, Math.min(ymax - 1, Math.floor((c1.row + c3.row) / 2))),
- z = Math.min(4, c0.zoom);
- x = x >> z << z;
- y = y >> z << z;
- scanLine(x, x + 1, y);
- }
- }
- // scan-line conversion
- function scanLine(x0, x1, y) {
- var z = c0.zoom,
- z0 = 2 - tileLevel,
- z1 = 4 + tileLevel;
- for (var x = x0; x < x1; x++) {
- var t = cache.load({column: x, row: y, zoom: z}, projection);
- if (!t.ready && !(t.key in newLocks)) {
- t.proxyRefs = {};
- var c, full, proxy;
- // downsample high-resolution tiles
- for (var dz = 1; dz <= z0; dz++) {
- full = true;
- for (var dy = 0, k = 1 << dz; dy <= k; dy++) {
- for (var dx = 0; dx <= k; dx++) {
- proxy = cache.peek(c = {
- column: (x << dz) + dx,
- row: (y << dz) + dy,
- zoom: z + dz
- });
- if (proxy && proxy.ready) {
- newLocks[proxy.key] = cache.load(c);
- proxy.proxyCount++;
- t.proxyRefs[proxy.key] = proxy;
- } else {
- full = false;
- }
- }
- }
- if (full) break;
- }
- // upsample low-resolution tiles
- if (!full) {
- for (var dz = 1; dz <= z1; dz++) {
- proxy = cache.peek(c = {
- column: x >> dz,
- row: y >> dz,
- zoom: z - dz
- });
- if (proxy && proxy.ready) {
- newLocks[proxy.key] = cache.load(c);
- proxy.proxyCount++;
- t.proxyRefs[proxy.key] = proxy;
- break;
- }
- }
- }
- }
- newLocks[t.key] = t;
- }
- }
- // position tiles
- for (var key in newLocks) {
- var t = newLocks[key],
- k = Math.pow(2, t.level = t.zoom - tileCenter.zoom);
- t.element.setAttribute("transform", "translate("
- + (t.x = tileSize.x * (t.column - tileCenter.column * k)) + ","
- + (t.y = tileSize.y * (t.row - tileCenter.row * k)) + ")");
- }
- // remove tiles that are no longer visible
- for (var key in oldLocks) {
- if (!(key in newLocks)) {
- var t = cache.unload(key);
- t.element.parentNode.removeChild(t.element);
- delete t.proxyRefs;
- }
- }
- // append tiles that are now visible
- for (var key in newLocks) {
- var t = newLocks[key];
- if (t.element.parentNode != levels[t.level]) {
- levels[t.level].appendChild(t.element);
- if (layer.show) layer.show(t);
- }
- }
- // flush the cache, clearing no-longer-needed tiles
- cache.flush();
- // dispatch the move event
- layer.dispatch({type: "move"});
- }
- // remove proxy tiles when tiles load
- function cleanup(e) {
- if (e.tile.proxyRefs) {
- for (var proxyKey in e.tile.proxyRefs) {
- var proxyTile = e.tile.proxyRefs[proxyKey];
- if ((--proxyTile.proxyCount <= 0) && cache.unload(proxyKey)) {
- proxyTile.element.parentNode.removeChild(proxyTile.element);
- }
- }
- delete e.tile.proxyRefs;
- }
- }
- layer.map = function(x) {
- if (!arguments.length) return map;
- if (map) {
- if (map == x) {
- container.parentNode.appendChild(container); // move to end
- return layer;
- }
- map.off("move", move).off("resize", move);
- container.parentNode.removeChild(container);
- }
- map = x;
- if (map) {
- map.container().appendChild(container);
- if (layer.init) layer.init(container);
- map.on("move", move).on("resize", move);
- move();
- }
- return layer;
- };
- layer.container = function() {
- return container;
- };
- layer.levels = function() {
- return levels;
- };
- layer.id = function(x) {
- if (!arguments.length) return id;
- id = x;
- container.setAttribute("id", x);
- return layer;
- };
- layer.visible = function(x) {
- if (!arguments.length) return visible;
- if (visible = x) container.removeAttribute("visibility")
- else container.setAttribute("visibility", "hidden");
- if (map) move();
- return layer;
- };
- layer.transform = function(x) {
- if (!arguments.length) return transform;
- transform = x;
- if (map) move();
- return layer;
- };
- layer.zoom = function(x) {
- if (!arguments.length) return zoom;
- zoom = typeof x == "function" || x == null ? x : function() { return x; };
- if (map) move();
- return layer;
- };
- layer.tile = function(x) {
- if (!arguments.length) return tile;
- tile = x;
- if (map) move();
- return layer;
- };
- layer.reload = function() {
- cache.clear();
- if (map) move();
- return layer;
- };
- layer.dispatch = po.dispatch(layer);
- layer.on("load", cleanup);
- return layer;
- };
- // scan-line conversion
- function edge(a, b) {
- if (a.row > b.row) { var t = a; a = b; b = t; }
- return {
- x0: a.column,
- y0: a.row,
- x1: b.column,
- y1: b.row,
- dx: b.column - a.column,
- dy: b.row - a.row
- };
- }
- // scan-line conversion
- function scanSpans(e0, e1, ymin, ymax, scanLine) {
- var y0 = Math.max(ymin, Math.floor(e1.y0)),
- y1 = Math.min(ymax, Math.ceil(e1.y1));
- // sort edges by x-coordinate
- if ((e0.x0 == e1.x0 && e0.y0 == e1.y0)
- ? (e0.x0 + e1.dy / e0.dy * e0.dx < e1.x1)
- : (e0.x1 - e1.dy / e0.dy * e0.dx < e1.x0)) {
- var t = e0; e0 = e1; e1 = t;
- }
- // scan lines!
- var m0 = e0.dx / e0.dy,
- m1 = e1.dx / e1.dy,
- d0 = e0.dx > 0, // use y + 1 to compute x0
- d1 = e1.dx < 0; // use y + 1 to compute x1
- for (var y = y0; y < y1; y++) {
- var x0 = m0 * Math.max(0, Math.min(e0.dy, y + d0 - e0.y0)) + e0.x0,
- x1 = m1 * Math.max(0, Math.min(e1.dy, y + d1 - e1.y0)) + e1.x0;
- scanLine(Math.floor(x1), Math.ceil(x0), y);
- }
- }
- // scan-line conversion
- function scanTriangle(a, b, c, ymin, ymax, scanLine) {
- var ab = edge(a, b),
- bc = edge(b, c),
- ca = edge(c, a);
- // sort edges by y-length
- if (ab.dy > bc.dy) { var t = ab; ab = bc; bc = t; }
- if (ab.dy > ca.dy) { var t = ab; ab = ca; ca = t; }
- if (bc.dy > ca.dy) { var t = bc; bc = ca; ca = t; }
- // scan span! scan span!
- if (ab.dy) scanSpans(ca, ab, ymin, ymax, scanLine);
- if (bc.dy) scanSpans(ca, bc, ymin, ymax, scanLine);
- }
- po.image = function() {
- var image = po.layer(load, unload),
- url;
- function load(tile) {
- var element = tile.element = po.svg("image"), size = image.map().tileSize();
- element.setAttribute("preserveAspectRatio", "none");
- element.setAttribute("width", size.x);
- element.setAttribute("height", size.y);
- if (typeof url == "function") {
- element.setAttribute("opacity", 0);
- var tileUrl = url(tile);
- if (tileUrl != null) {
- tile.request = po.queue.image(element, tileUrl, function(img) {
- delete tile.request;
- tile.ready = true;
- tile.img = img;
- element.removeAttribute("opacity");
- image.dispatch({type: "load", tile: tile});
- });
- } else {
- tile.ready = true;
- image.dispatch({type: "load", tile: tile});
- }
- } else {
- tile.ready = true;
- if (url != null) element.setAttributeNS(po.ns.xlink, "href", url);
- image.dispatch({type: "load", tile: tile});
- }
- }
- function unload(tile) {
- if (tile.request) tile.request.abort(true);
- }
- image.url = function(x) {
- if (!arguments.length) return url;
- url = typeof x == "string" && /{.}/.test(x) ? po.url(x) : x;
- return image.reload();
- };
- return image;
- };
- po.geoJson = function(fetch) {
- var geoJson = po.layer(load, unload),
- container = geoJson.container(),
- url,
- clip = true,
- clipId = "org.polymaps." + po.id(),
- clipHref = "url(#" + clipId + ")",
- clipPath = container.insertBefore(po.svg("clipPath"), container.firstChild),
- clipRect = clipPath.appendChild(po.svg("rect")),
- scale = "auto",
- zoom = null,
- features;
- container.setAttribute("fill-rule", "evenodd");
- clipPath.setAttribute("id", clipId);
- if (!arguments.length) fetch = po.queue.json;
- function projection(proj) {
- var l = {lat: 0, lon: 0};
- return function(coordinates) {
- l.lat = coordinates[1];
- l.lon = coordinates[0];
- var p = proj(l);
- coordinates.x = p.x;
- coordinates.y = p.y;
- return p;
- };
- }
- function geometry(o, proj) {
- return o && o.type in types && types[o.type](o, proj);
- }
- var types = {
- Point: function(o, proj) {
- var p = proj(o.coordinates),
- c = po.svg("circle");
- c.setAttribute("r", 4.5);
- c.setAttribute("transform", "translate(" + p.x + "," + p.y + ")");
- return c;
- },
- MultiPoint: function(o, proj) {
- var g = po.svg("g"),
- c = o.coordinates,
- p, // proj(c[i])
- x, // svg:circle
- i = -1,
- n = c.length;
- while (++i < n) {
- x = g.appendChild(po.svg("circle"));
- x.setAttribute("r", 4.5);
- x.setAttribute("transform", "translate(" + (p = proj(c[i])).x + "," + p.y + ")");
- }
- return g;
- },
- LineString: function(o, proj) {
- var x = po.svg("path"),
- d = ["M"],
- c = o.coordinates,
- p, // proj(c[i])
- i = -1,
- n = c.length;
- while (++i < n) d.push((p = proj(c[i])).x, ",", p.y, "L");
- d.pop();
- if (!d.length) return;
- x.setAttribute("d", d.join(""));
- return x;
- },
- MultiLineString: function(o, proj) {
- var x = po.svg("path"),
- d = [],
- ci = o.coordinates,
- cj, // ci[i]
- i = -1,
- j,
- n = ci.length,
- m;
- while (++i < n) {
- cj = ci[i];
- j = -1;
- m = cj.length;
- d.push("M");
- while (++j < m) d.push((p = proj(cj[j])).x, ",", p.y, "L");
- d.pop();
- }
- if (!d.length) return;
- x.setAttribute("d", d.join(""));
- return x;
- },
- Polygon: function(o, proj) {
- var x = po.svg("path"),
- d = [],
- ci = o.coordinates,
- cj, // ci[i]
- i = -1,
- j,
- n = ci.length,
- m;
- while (++i < n) {
- cj = ci[i];
- j = -1;
- m = cj.length - 1;
- d.push("M");
- while (++j < m) d.push((p = proj(cj[j])).x, ",", p.y, "L");
- d[d.length - 1] = "Z";
- }
- if (!d.length) return;
- x.setAttribute("d", d.join(""));
- return x;
- },
- MultiPolygon: function(o, proj) {
- var x = po.svg("path"),
- d = [],
- ci = o.coordinates,
- cj, // ci[i]
- ck, // cj[j]
- i = -1,
- j,
- k,
- n = ci.length,
- m,
- l;
- while (++i < n) {
- cj = ci[i];
- j = -1;
- m = cj.length;
- while (++j < m) {
- ck = cj[j];
- k = -1;
- l = ck.length - 1;
- d.push("M");
- while (++k < l) d.push((p = proj(ck[k])).x, ",", p.y, "L");
- d[d.length - 1] = "Z";
- }
- }
- if (!d.length) return;
- x.setAttribute("d", d.join(""));
- return x;
- },
- GeometryCollection: function(o, proj) {
- var g = po.svg("g"),
- i = -1,
- c = o.geometries,
- n = c.length,
- x;
- while (++i < n) {
- x = geometry(c[i], proj);
- if (x) g.appendChild(x);
- }
- return g;
- }
- };
- function rescale(o, e, k) {
- return o.type in rescales && rescales[o.type](o, e, k);
- }
- var rescales = {
- Point: function (o, e, k) {
- var p = o.coordinates;
- e.setAttribute("transform", "translate(" + p.x + "," + p.y + ")" + k);
- },
- MultiPoint: function (o, e, k) {
- var c = o.coordinates,
- i = -1,
- n = p.length,
- x = e.firstChild,
- p;
- while (++i < n) {
- p = c[i];
- x.setAttribute("transform", "translate(" + p.x + "," + p.y + ")" + k);
- x = x.nextSibling;
- }
- }
- };
- function load(tile, proj) {
- var g = tile.element = po.svg("g");
- tile.features = [];
- proj = projection(proj(tile).locationPoint);
- function update(data) {
- var updated = [];
- /* Fetch the next batch of features, if so directed. */
- if (data.next) tile.request = fetch(data.next.href, update);
- /* Convert the GeoJSON to SVG. */
- switch (data.type) {
- case "FeatureCollection": {
- for (var i = 0; i < data.features.length; i++) {
- var feature = data.features[i],
- element = geometry(feature.geometry, proj);
- if (element) updated.push({element: g.appendChild(element), data: feature});
- }
- break;
- }
- case "Feature": {
- var element = geometry(data.geometry, proj);
- if (element) updated.push({element: g.appendChild(element), data: data});
- break;
- }
- default: {
- var element = geometry(data, proj);
- if (element) updated.push({element: g.appendChild(element), data: {type: "Feature", geometry: data}});
- break;
- }
- }
- tile.ready = true;
- updated.push.apply(tile.features, updated);
- geoJson.dispatch({type: "load", tile: tile, features: updated});
- }
- if (url != null) {
- tile.request = fetch(typeof url == "function" ? url(tile) : url, update);
- } else {
- update({type: "FeatureCollection", features: features || []});
- }
- }
- function unload(tile) {
- if (tile.request) tile.request.abort(true);
- }
- function move() {
- var zoom = geoJson.map().zoom(),
- tiles = geoJson.cache.locks(), // visible tiles
- key, // key in locks
- tile, // locks[key]
- features, // tile.features
- i, // current feature index
- n, // current feature count, features.length
- feature, // features[i]
- k; // scale transform
- if (scale == "fixed") {
- for (key in tiles) {
- if ((tile = tiles[key]).scale != zoom) {
- k = "scale(" + Math.pow(2, tile.zoom - zoom) + ")";
- i = -1;
- n = (features = tile.features).length;
- while (++i < n) rescale((feature = features[i]).data.geometry, feature.element, k);
- tile.scale = zoom;
- }
- }
- } else {
- for (key in tiles) {
- i = -1;
- n = (features = (tile = tiles[key]).features).length;
- while (++i < n) rescale((feature = features[i]).data.geometry, feature.element, "");
- delete tile.scale;
- }
- }
- }
- geoJson.url = function(x) {
- if (!arguments.length) return url;
- url = typeof x == "string" && /{.}/.test(x) ? po.url(x) : x;
- if (url != null) features = null;
- if (typeof url == "string") geoJson.tile(false);
- return geoJson.reload();
- };
- geoJson.features = function(x) {
- if (!arguments.length) return features;
- if (features = x) {
- url = null;
- geoJson.tile(false);
- }
- return geoJson.reload();
- };
- geoJson.clip = function(x) {
- if (!arguments.length) return clip;
- if (clip) container.removeChild(clipPath);
- if (clip = x) container.insertBefore(clipPath, container.firstChild);
- var locks = geoJson.cache.locks();
- for (var key in locks) {
- if (clip) locks[key].element.setAttribute("clip-path", clipHref);
- else locks[key].element.removeAttribute("clip-path");
- }
- return geoJson;
- };
- var __tile__ = geoJson.tile;
- geoJson.tile = function(x) {
- if (arguments.length && !x) geoJson.clip(x);
- return __tile__.apply(geoJson, arguments);
- };
- var __map__ = geoJson.map;
- geoJson.map = function(x) {
- if (x && clipRect) {
- var size = x.tileSize();
- clipRect.setAttribute("width", size.x);
- clipRect.setAttribute("height", size.y);
- }
- return __map__.apply(geoJson, arguments);
- };
- geoJson.scale = function(x) {
- if (!arguments.length) return scale;
- if (scale = x) geoJson.on("move", move);
- else geoJson.off("move", move);
- if (geoJson.map()) move();
- return geoJson;
- };
- geoJson.show = function(tile) {
- if (clip) tile.element.setAttribute("clip-path", clipHref);
- else tile.element.removeAttribute("clip-path");
- geoJson.dispatch({type: "show", tile: tile, features: tile.features});
- return geoJson;
- };
- geoJson.reshow = function() {
- var locks = geoJson.cache.locks();
- for (var key in locks) geoJson.show(locks[key]);
- return geoJson;
- };
- return geoJson;
- };
- po.dblclick = function() {
- var dblclick = {},
- zoom = "mouse",
- map,
- container;
- function handle(e) {
- var z = map.zoom();
- if (e.shiftKey) z = Math.ceil(z) - z - 1;
- else z = 1 - z + Math.floor(z);
- zoom === "mouse" ? map.zoomBy(z, map.mouse(e)) : map.zoomBy(z);
- }
- dblclick.zoom = function(x) {
- if (!arguments.length) return zoom;
- zoom = x;
- return dblclick;
- };
- dblclick.map = function(x) {
- if (!arguments.length) return map;
- if (map) {
- container.removeEventListener("dblclick", handle, false);
- container = null;
- }
- if (map = x) {
- container = map.container();
- container.addEventListener("dblclick", handle, false);
- }
- return dblclick;
- };
- return dblclick;
- };
- po.drag = function() {
- var drag = {},
- map,
- container,
- dragging;
- function mousedown(e) {
- if (e.shiftKey) return;
- dragging = {
- x: e.clientX,
- y: e.clientY
- };
- map.focusableParent().focus();
- e.preventDefault();
- document.body.style.setProperty("cursor", "move", null);
- }
- function mousemove(e) {
- if (!dragging) return;
- map.panBy({x: e.clientX - dragging.x, y: e.clientY - dragging.y});
- dragging.x = e.clientX;
- dragging.y = e.clientY;
- }
- function mouseup(e) {
- if (!dragging) return;
- mousemove(e);
- dragging = null;
- document.body.style.removeProperty("cursor");
- }
- drag.map = function(x) {
- if (!arguments.length) return map;
- if (map) {
- container.removeEventListener("mousedown", mousedown, false);
- container = null;
- }
- if (map = x) {
- container = map.container();
- container.addEventListener("mousedown", mousedown, false);
- }
- return drag;
- };
- window.addEventListener("mousemove", mousemove, false);
- window.addEventListener("mouseup", mouseup, false);
- return drag;
- };
- po.wheel = function() {
- var wheel = {},
- timePrev = 0,
- last = 0,
- smooth = true,
- zoom = "mouse",
- location,
- map,
- container;
- function move(e) {
- location = null;
- }
- // mousewheel events are totally broken!
- // https://bugs.webkit.org/show_bug.cgi?id=40441
- // not only that, but Chrome and Safari differ in re. to acceleration!
- var inner = document.createElement("div"),
- outer = document.createElement("div");
- outer.style.visibility = "hidden";
- outer.style.top = "0px";
- outer.style.height = "0px";
- outer.style.width = "0px";
- outer.style.overflowY = "scroll";
- inner.style.height = "2000px";
- outer.appendChild(inner);
- document.body.appendChild(outer);
- function mousewheel(e) {
- var delta = e.wheelDelta || -e.detail,
- point;
- /* Detect the pixels that would be scrolled by this wheel event. */
- if (delta) {
- if (smooth) {
- try {
- outer.scrollTop = 1000;
- outer.dispatchEvent(e);
- delta = 1000 - outer.scrollTop;
- } catch (error) {
- // Derp! Hope for the best?
- }
- delta *= .005;
- }
- /* If smooth zooming is disabled, batch events into unit steps. */
- else {
- var timeNow = Date.now();
- if (timeNow - timePrev > 200) {
- delta = delta > 0 ? +1 : -1;
- timePrev = timeNow;
- } else {
- delta = 0;
- }
- }
- }
- if (delta) {
- switch (zoom) {
- case "mouse": {
- point = map.mouse(e);
- if (!location) location = map.pointLocation(point);
- map.off("move", move).zoomBy(delta, point, location).on("move", move);
- break;
- }
- case "location": {
- map.zoomBy(delta, map.locationPoint(location), location);
- break;
- }
- default: { // center
- map.zoomBy(delta);
- break;
- }
- }
- }
- e.preventDefault();
- return false; // for Firefox
- }
- wheel.smooth = function(x) {
- if (!arguments.length) return smooth;
- smooth = x;
- return wheel;
- };
- wheel.zoom = function(x, l) {
- if (!arguments.length) return zoom;
- zoom = x;
- location = l;
- if (map) {
- if (zoom == "mouse") map.on("move", move);
- else map.off("move", move);
- }
- return wheel;
- };
- wheel.map = function(x) {
- if (!arguments.length) return map;
- if (map) {
- container.removeEventListener("mousemove", move, false);
- container.removeEventListener("mousewheel", mousewheel, false);
- container.removeEventListener("MozMousePixelScroll", mousewheel, false);
- container = null;
- map.off("move", move);
- }
- if (map = x) {
- if (zoom == "mouse") map.on("move", move);
- container = map.container();
- container.addEventListener("mousemove", move, false);
- container.addEventListener("mousewheel", mousewheel, false);
- container.addEventListener("MozMousePixelScroll", mousewheel, false);
- }
- return wheel;
- };
- return wheel;
- };
- po.arrow = function() {
- var arrow = {},
- key = {left: 0, right: 0, up: 0, down: 0},
- last = 0,
- repeatTimer,
- repeatDelay = 250,
- repeatInterval = 50,
- speed = 16,
- map,
- parent;
- function keydown(e) {
- if (e.ctrlKey || e.altKey || e.metaKey) return;
- var now = Date.now(), dx = 0, dy = 0;
- switch (e.keyCode) {
- case 37: {
- if (!key.left) {
- last = now;
- key.left = 1;
- if (!key.right) dx = speed;
- }
- break;
- }
- case 39: {
- if (!key.right) {
- last = now;
- key.right = 1;
- if (!key.left) dx = -speed;
- }
- break;
- }
- case 38: {
- if (!key.up) {
- last = now;
- key.up = 1;
- if (!key.down) dy = speed;
- }
- break;
- }
- case 40: {
- if (!key.down) {
- last = now;
- key.down = 1;
- if (!key.up) dy = -speed;
- }
- break;
- }
- default: return;
- }
- if (dx || dy) map.panBy({x: dx, y: dy});
- if (!repeatTimer && (key.left | key.right | key.up | key.down)) {
- repeatTimer = setInterval(repeat, repeatInterval);
- }
- e.preventDefault();
- }
- function keyup(e) {
- last = Date.now();
- switch (e.keyCode) {
- case 37: key.left = 0; break;
- case 39: key.right = 0; break;
- case 38: key.up = 0; break;
- case 40: key.down = 0; break;
- default: return;
- }
- if (repeatTimer && !(key.left | key.right | key.up | key.down)) {
- repeatTimer = clearInterval(repeatTimer);
- }
- e.preventDefault();
- }
- function keypress(e) {
- switch (e.charCode) {
- case 45: case 95: map.zoom(Math.ceil(map.zoom()) - 1); break; // - _
- case 43: case 61: map.zoom(Math.floor(map.zoom()) + 1); break; // = +
- default: return;
- }
- e.preventDefault();
- }
- function repeat() {
- if (!map) return;
- if (Date.now() < last + repeatDelay) return;
- var dx = (key.left - key.right) * speed,
- dy = (key.up - key.down) * speed;
- if (dx || dy) map.panBy({x: dx, y: dy});
- }
- arrow.map = function(x) {
- if (!arguments.length) return map;
- if (map) {
- parent.removeEventListener("keypress", keypress, false);
- parent.removeEventListener("keydown", keydown, false);
- parent.removeEventListener("keyup", keyup, false);
- parent = null;
- }
- if (map = x) {
- parent = map.focusableParent();
- parent.addEventListener("keypress", keypress, false);
- parent.addEventListener("keydown", keydown, false);
- parent.addEventListener("keyup", keyup, false);
- }
- return arrow;
- };
- arrow.speed = function(x) {
- if (!arguments.length) return speed;
- speed = x;
- return arrow;
- };
- return arrow;
- };
- po.hash = function() {
- var hash = {},
- s0, // cached location.hash
- lat = 90 - 1e-8, // allowable latitude range
- map;
- var parser = function(map, s) {
- var args = s.split("/").map(Number);
- if (args.length < 3 || args.some(isNaN)) return true; // replace bogus hash
- else {
- var size = map.size();
- map.zoomBy(args[0] - map.zoom(),
- {x: size.x / 2, y: size.y / 2},
- {lat: Math.min(lat, Math.max(-lat, args[1])), lon: args[2]});
- }
- };
- var formatter = function(map) {
- var center = map.center(),
- zoom = map.zoom(),
- precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
- return "#" + zoom.toFixed(2)
- + "/" + center.lat.toFixed(precision)
- + "/" + center.lon.toFixed(precision);
- };
- function move() {
- var s1 = formatter(map);
- if (s0 !== s1) location.replace(s0 = s1); // don't recenter the map!
- }
- function hashchange() {
- if (location.hash === s0) return; // ignore spurious hashchange events
- if (parser(map, (s0 = location.hash).substring(1)))
- move(); // replace bogus hash
- }
- hash.map = function(x) {
- if (!arguments.length) return map;
- if (map) {
- map.off("move", move);
- window.removeEventListener("hashchange", hashchange, false);
- }
- if (map = x) {
- map.on("move", move);
- window.addEventListener("hashchange", hashchange, false);
- location.hash ? hashchange() : move();
- }
- return hash;
- };
- hash.parser = function(x) {
- if (!arguments.length) return parser;
- parser = x;
- return hash;
- };
- hash.formatter = function(x) {
- if (!arguments.length) return formatter;
- formatter = x;
- return hash;
- };
- return hash;
- };
- po.touch = function() {
- var touch = {},
- map,
- container,
- rotate = false,
- last = 0,
- zoom,
- angle,
- locations = {}; // touch identifier -> location
- window.addEventListener("touchmove", touchmove, false);
- function touchstart(e) {
- var i = -1,
- n = e.touches.length,
- t = Date.now();
- // doubletap detection
- if ((n == 1) && (t - last < 300)) {
- var z = map.zoom();
- map.zoomBy(1 - z + Math.floor(z), map.mouse(e.touches[0]));
- e.preventDefault();
- }
- last = t;
- // store original zoom & touch locations
- zoom = map.zoom();
- angle = map.angle();
- while (++i < n) {
- t = e.touches[i];
- locations[t.identifier] = map.pointLocation(map.mouse(t));
- }
- }
- function touchmove(e) {
- switch (e.touches.length) {
- case 1: { // single-touch pan
- var t0 = e.touches[0];
- map.zoomBy(0, map.mouse(t0), locations[t0.identifier]);
- e.preventDefault();
- break;
- }
- case 2: { // double-touch pan + zoom + rotate
- var t0 = e.touches[0],
- t1 = e.touches[1],
- p0 = map.mouse(t0),
- p1 = map.mouse(t1),
- p2 = {x: (p0.x + p1.x) / 2, y: (p0.y + p1.y) / 2}, // center point
- c0 = po.map.locationCoordinate(locations[t0.identifier]),
- c1 = po.map.locationCoordinate(locations[t1.identifier]),
- c2 = {row: (c0.row + c1.row) / 2, column: (c0.column + c1.column) / 2, zoom: 0},
- l2 = po.map.coordinateLocation(c2); // center location
- map.zoomBy(Math.log(e.scale) / Math.LN2 + zoom - map.zoom(), p2, l2);
- if (rotate) map.angle(e.rotation / 180 * Math.PI + angle);
- e.preventDefault();
- break;
- }
- }
- }
- touch.rotate = function(x) {
- if (!arguments.length) return rotate;
- rotate = x;
- return touch;
- };
- touch.map = function(x) {
- if (!arguments.length) return map;
- if (map) {
- container.removeEventListener("touchstart", touchstart, false);
- container = null;
- }
- if (map = x) {
- container = map.container();
- container.addEventListener("touchstart", touchstart, false);
- }
- return touch;
- };
- return touch;
- };
- // Default map controls.
- po.interact = function() {
- var interact = {},
- drag = po.drag(),
- wheel = po.wheel(),
- dblclick = po.dblclick(),
- touch = po.touch(),
- arrow = po.arrow();
- interact.map = function(x) {
- drag.map(x);
- wheel.map(x);
- dblclick.map(x);
- touch.map(x);
- arrow.map(x);
- return interact;
- };
- return interact;
- };
- po.compass = function() {
- var compass = {},
- g = po.svg("g"),
- ticks = {},
- r = 30,
- speed = 16,
- last = 0,
- repeatDelay = 250,
- repeatInterval = 50,
- position = "top-left", // top-left, top-right, bottom-left, bottom-right
- zoomStyle = "small", // none, small, big
- zoomContainer,
- panStyle = "small", // none, small
- panTimer,
- panDirection,
- panContainer,
- drag,
- dragRect = po.svg("rect"),
- map,
- container,
- window;
- g.setAttribute("class", "compass");
- dragRect.setAttribute("class", "back fore");
- dragRect.setAttribute("pointer-events", "none");
- dragRect.setAttribute("display", "none");
- function panStart(e) {
- g.setAttribute("class", "compass active");
- if (!panTimer) panTimer = setInterval(panRepeat, repeatInterval);
- if (panDirection) map.panBy(panDirection);
- last = Date.now();
- return cancel(e);
- }
- function panRepeat() {
- if (panDirection && (Date.now() > last + repeatDelay)) {
- map.panBy(panDirection);
- }
- }
- function mousedown(e) {
- if (e.shiftKey) {
- drag = {x0: map.mouse(e)};
- map.focusableParent().focus();
- return cancel(e);
- }
- }
- function mousemove(e) {
- if (!drag) return;
- drag.x1 = map.mouse(e);
- dragRect.setAttribute("x", Math.min(drag.x0.x, drag.x1.x));
- dragRect.setAttribute("y", Math.min(drag.x0.y, drag.x1.y));
- dragRect.setAttribute("width", Math.abs(drag.x0.x - drag.x1.x));
- dragRect.setAttribute("height", Math.abs(drag.x0.y - drag.x1.y));
- dragRect.removeAttribute("display");
- }
- function mouseup(e) {
- g.setAttribute("class", "compass");
- if (drag) {
- if (drag.x1) {
- map.extent([
- map.pointLocation({
- x: Math.min(drag.x0.x, drag.x1.x),
- y: Math.max(drag.x0.y, drag.x1.y)
- }),
- map.pointLocation({
- x: Math.max(drag.x0.x, drag.x1.x),
- y: Math.min(drag.x0.y, drag.x1.y)
- })
- ]);
- dragRect.setAttribute("display", "none");
- }
- drag = null;
- }
- if (panTimer) {
- clearInterval(panTimer);
- panTimer = 0;
- }
- }
- function panBy(x) {
- return function() {
- x ? this.setAttribute("class", "active") : this.removeAttribute("class");
- panDirection = x;
- };
- }
- function zoomBy(x) {
- return function(e) {
- g.setAttribute("class", "compass active");
- var z = map.zoom();
- map.zoom(x < 0 ? Math.ceil(z) - 1 : Math.floor(z) + 1);
- return cancel(e);
- };
- }
- function zoomTo(x) {
- return function(e) {
- map.zoom(x);
- return cancel(e);
- };
- }
- function zoomOver() {
- this.setAttribute("class", "active");
- }
- function zoomOut() {
- this.removeAttribute("class");
- }
- function cancel(e) {
- e.stopPropagation();
- e.preventDefault();
- return false;
- }
- function pan(by) {
- var x = Math.SQRT1_2 * r,
- y = r * .7,
- z = r * .2,
- g = po.svg("g"),
- dir = g.appendChild(po.svg("path")),
- chv = g.appendChild(po.svg("path"));
- dir.setAttribute("class", "direction");
- dir.setAttribute("pointer-events", "all");
- dir.setAttribute("d", "M0,0L" + x + "," + x + "A" + r + "," + r + " 0 0,1 " + -x + "," + x + "Z");
- chv.setAttribute("class", "chevron");
- chv.setAttribute("d", "M" + z + "," + (y - z) + "L0," + y + " " + -z + "," + (y - z));
- chv.setAttribute("pointer-events", "none");
- g.addEventListener("mousedown", panStart, false);
- g.addEventListener("mouseover", panBy(by), false);
- g.addEventListener("mouseout", panBy(null), false);
- g.addEventListener("dblclick", cancel, false);
- return g;
- }
- function zoom(by) {
- var x = r * .4,
- y = x / 2,
- g = po.svg("g"),
- back = g.appendChild(po.svg("path")),
- dire = g.appendChild(po.svg("path")),
- chev = g.appendChild(po.svg("path")),
- fore = g.appendChild(po.svg("path"));
- back.setAttribute("class", "back");
- back.setAttribute("d", "M" + -x + ",0V" + -x + "A" + x + "," + x + " 0 1,1 " + x + "," + -x + "V0Z");
- dire.setAttribute("class", "direction");
- dire.setAttribute("d", back.getAttribute("d"));
- chev.setAttribute("class", "chevron");
- chev.setAttribute("d", "M" + -y + "," + -x + "H" + y + (by > 0 ? "M0," + (-x - y) + "V" + -y : ""));
- fore.setAttribute("class", "fore");
- fore.setAttribute("fill", "none");
- fore.setAttribute("d", back.getAttribute("d"));
- g.addEventListener("mousedown", zoomBy(by), false);
- g.addEventListener("mouseover", zoomOver, false);
- g.addEventListener("mouseout", zoomOut, false);
- g.addEventListener("dblclick", cancel, false);
- return g;
- }
- function tick(i) {
- var x = r * .2,
- y = r * .4,
- g = po.svg("g"),
- back = g.appendChild(po.svg("rect")),
- chev = g.appendChild(po.svg("path"));
- back.setAttribute("pointer-events", "all");
- back.setAttribute("fill", "none");
- back.setAttribute("x", -y);
- back.setAttribute("y", -.75 * y);
- back.setAttribute("width", 2 * y);
- back.setAttribute("height", 1.5 * y);
- chev.setAttribute("class", "chevron");
- chev.setAttribute("d", "M" + -x + ",0H" + x);
- g.addEventListener("mousedown", zoomTo(i), false);
- g.addEventListener("dblclick", cancel, false);
- return g;
- }
- function move() {
- var x = r + 6, y = x, size = map.size();
- switch (position) {
- case "top-left": break;
- case "top-right": x = size.x - x; break;
- case "bottom-left": y = size.y - y; break;
- case "bottom-right": x = size.x - x; y = size.y - y; break;
- }
- g.setAttribute("transform", "translate(" + x + "," + y + ")");
- dragRect.setAttribute("transform", "translate(" + -x + "," + -y + ")");
- for (var i in ticks) {
- i == map.zoom()
- ? ticks[i].setAttribute("class", "active")
- : ticks[i].removeAttribute("class");
- }
- }
- function draw() {
- while (g.lastChild) g.removeChild(g.lastChild);
- g.appendChild(dragRect);
- if (panStyle != "none") {
- panContainer = g.appendChild(po.svg("g"));
- panContainer.setAttribute("class", "pan");
- var back = panContainer.appendChild(po.svg("circle"));
- back.setAttribute("class", "back");
- back.setAttribute("r", r);
- var s = panContainer.appendChild(pan({x: 0, y: -speed}));
- s.setAttribute("transform", "rotate(0)");
- var w = panContainer.appendChild(pan({x: speed, y: 0}));
- w.setAttribute("transform", "rotate(90)");
- var n = panContainer.appendChild(pan({x: 0, y: speed}));
- n.setAttribute("transform", "rotate(180)");
- var e = panContainer.appendChild(pan({x: -speed, y: 0}));
- e.setAttribute("transform", "rotate(270)");
- var fore = panContainer.appendChild(po.svg("circle"));
- fore.setAttribute("fill", "none");
- fore.setAttribute("class", "fore");
- fore.setAttribute("r", r);
- } else {
- panContainer = null;
- }
- if (zoomStyle != "none") {
- zoomContainer = g.appendChild(po.svg("g"));
- zoomContainer.setAttribute("class", "zoom");
- var j = -.5;
- if (zoomStyle == "big") {
- ticks = {};
- for (var i = map.zoomRange()[0], j = 0; i <= map.zoomRange()[1]; i++, j++) {
- (ticks[i] = zoomContainer.appendChild(tick(i)))
- .setAttribute("transform", "translate(0," + (-(j + .75) * r * .4) + ")");
- }
- }
- var p = panStyle == "none" ? .4 : 2;
- zoomContainer.setAttribute("transform", "translate(0," + r * (/^top-/.test(position) ? (p + (j + .5) * .4) : -p) + ")");
- zoomContainer.appendChild(zoom(+1)).setAttribute("transform", "translate(0," + (-(j + .5) * r * .4) + ")");
- zoomContainer.appendChild(zoom(-1)).setAttribute("transform", "scale(-1)");
- } else {
- zoomContainer = null;
- }
- move();
- }
- compass.radius = function(x) {
- if (!arguments.length) return r;
- r = x;
- if (map) draw();
- return compass;
- };
- compass.speed = function(x) {
- if (!arguments.length) return r;
- speed = x;
- return compass;
- };
- compass.position = function(x) {
- if (!arguments.length) return position;
- position = x;
- if (map) draw();
- return compass;
- };
- compass.pan = function(x) {
- if (!arguments.length) return panStyle;
- panStyle = x;
- if (map) draw();
- return compass;
- };
- compass.zoom = function(x) {
- if (!arguments.length) return zoomStyle;
- zoomStyle = x;
- if (map) draw();
- return compass;
- };
- compass.map = function(x) {
- if (!arguments.length) return map;
- if (map) {
- container.removeEventListener("mousedown", mousedown, false);
- container.removeChild(g);
- container = null;
- window.removeEventListener("mousemove", mousemove, false);
- window.removeEventListener("mouseup", mouseup, false);
- window = null;
- map.off("move", move).off("resize", move);
- }
- if (map = x) {
- container = map.container();
- container.appendChild(g);
- container.addEventListener("mousedown", mousedown, false);
- window = container.ownerDocument.defaultView;
- window.addEventListener("mousemove", mousemove, false);
- window.addEventListener("mouseup", mouseup, false);
- map.on("move", move).on("resize", move);
- draw();
- }
- return compass;
- };
- return compass;
- };
- po.grid = function() {
- var grid = {},
- map,
- g = po.svg("g");
- g.setAttribute("class", "grid");
- function move(e) {
- var p,
- line = g.firstChild,
- size = map.size(),
- nw = map.pointLocation(zero),
- se = map.pointLocation(size),
- step = Math.pow(2, 4 - Math.round(map.zoom()));
- // Round to step.
- nw.lat = Math.floor(nw.lat / step) * step;
- nw.lon = Math.ceil(nw.lon / step) * step;
- // Longitude ticks.
- for (var x; (x = map.locationPoint(nw).x) <= size.x; nw.lon += step) {
- if (!line) line = g.appendChild(po.svg("line"));
- line.setAttribute("x1", x);
- line.setAttribute("x2", x);
- line.setAttribute("y1", 0);
- line.setAttribute("y2", size.y);
- line = line.nextSibling;
- }
- // Latitude ticks.
- for (var y; (y = map.locationPoint(nw).y) <= size.y; nw.lat -= step) {
- if (!line) line = g.appendChild(po.svg("line"));
- line.setAttribute("y1", y);
- line.setAttribute("y2", y);
- line.setAttribute("x1", 0);
- line.setAttribute("x2", size.x);
- line = line.nextSibling;
- }
- // Remove extra ticks.
- while (line) {
- var next = line.nextSibling;
- g.removeChild(line);
- line = next;
- }
- }
- grid.map = function(x) {
- if (!arguments.length) return map;
- if (map) {
- g.parentNode.removeChild(g);
- map.off("move", move).off("resize", move);
- }
- if (map = x) {
- map.on("move", move).on("resize", move);
- map.container().appendChild(g);
- map.dispatch({type: "move"});
- }
- return grid;
- };
- return grid;
- };
- po.stylist = function() {
- var attrs = [],
- styles = [],
- title;
- function stylist(e) {
- var ne = e.features.length,
- na = attrs.length,
- ns = styles.length,
- f, // feature
- d, // data
- o, // element
- x, // attr or style or title descriptor
- v, // attr or style or title value
- i,
- j;
- for (i = 0; i < ne; ++i) {
- if (!(o = (f = e.features[i]).element)) continue;
- d = f.data;
- for (j = 0; j < na; ++j) {
- v = (x = attrs[j]).value;
- if (typeof v === "function") v = v.call(null, d);
- v == null ? (x.name.local
- ? o.removeAttributeNS(x.name.space, x.name.local)
- : o.removeAttribute(x.name)) : (x.name.local
- ? o.setAttributeNS(x.name.space, x.name.local, v)
- : o.setAttribute(x.name, v));
- }
- for (j = 0; j < ns; ++j) {
- v = (x = styles[j]).value;
- if (typeof v === "function") v = v.call(null, d);
- v == null
- ? o.style.removeProperty(x.name)
- : o.style.setProperty(x.name, v, x.priority);
- }
- if (v = title) {
- if (typeof v === "function") v = v.call(null, d);
- while (o.lastChild) o.removeChild(o.lastChild);
- if (v != null) o.appendChild(po.svg("title")).appendChild(document.createTextNode(v));
- }
- }
- }
- stylist.attr = function(n, v) {
- attrs.push({name: ns(n), value: v});
- return stylist;
- };
- stylist.style = function(n, v, p) {
- styles.push({name: n, value: v, priority: arguments.length < 3 ? null : p});
- return stylist;
- };
- stylist.title = function(v) {
- title = v;
- return stylist;
- };
- return stylist;
- };
- })(org.polymaps);
|