Skip to content

Instantly share code, notes, and snippets.

@yhahn
Created September 24, 2012 18:24
Show Gist options
  • Save yhahn/3777462 to your computer and use it in GitHub Desktop.
Save yhahn/3777462 to your computer and use it in GitHub Desktop.

Foursquare Store Locator

This template uses the foursquare API to build a store locator feature that maps all addresses for venues in a foursquare list and allows users to search for closest venues.

This whole template can be emedded as an iframe or integrated into your existing website template.

By adding your store location data to foursquare, you have a simple interface to manage your locations and allow customers interact with them both on-line and off. While browsing the map for nearby locations, users will see the total checkins and foursquare users who have visited your location, and they will have the option to add your location to their foursquare todo list. When users with the foursquare mobile app walk by venues on their todo list, they'll get reminded to check out your store.

About Map Site Templates

Map Site templates from MapBox are a way to jumpstart building a map-based web feature. The map-site templates bundles common html and css formatting with reusable javascript components.

To build a project based on this template, fork this repository, edit the html content and css, and alter the configuration script.

To make your custom base map, sign up for MapBox and create a map.

Using this template

Edit the content by adjusting, removing, or adding to index.html. This is the main markup document with the content and layout for the map-site.

Adjust the design by editing the style.css file and adding any additional supporting structure to index.html.

Set the map features by writing a configuration script at the bottom of index.html.

HTML layout

The html markup for the template is in index.html. It's a simple html page layout. Generally, you'll want to change the content elements like title, h1, img#logo and div#about.

CSS styles

Most of the hard work on a map site build is template design implemented through CSS. This template by default is simple and clean so you can modify or replace it. This design and be completely overridden by applying new CSS styles or changing the exisiting rules in style.css.

CSS rules are set in two files:

  • style.css contains all the layout and typographic styles as well as some overridden styles for map controls, and a reset stylesheet. Implement your design by editing this file.
  • map.css holds the default map styles from tiles.mapbox.com embeds.

Javascript interaction

All of the external javascript libraries to make the map interactive and connect it to MapBox are stored in the ext directory. For this template, we're using Modest Maps and Wax to make the map interactive, Easey for smooth aninmated panning and zooming, and MMG for adding markers to the map based on geojson-formatted data.

An internal javascript library, script.js, abstracts common map settings, and foursquare.js is the library we put together map the foursquare API.

We're also using jQuery for DOM manipulation and handling events, and Underscore.js for data processing.

Map configuration

The map is added to the <div> container in index.html with id="map". Styles to lay out the map container come from class="map".

<div id="map" class="map"></div>

At the bottom of the index.html document, we set up the map. The id of the container is the first argument ('map'), and an object of options is the second argument. The third arugement is the name of an optional callback function, which we use to start the foursquare.js main function, once the map is loaded.

The only required option is api, and it should contain the API URL from MapBox. After you create a new map through your MapBox account, click embed on the info tab and copy the API URL.

var main = Map('map', { 
    api: 'http://a.tiles.mapbox.com/v3/mapbox.map-hv50mbs9.jsonp' 
});

The map options object can take several options:

  • api The MapBox API URL from the embed button on your map:
  • center An object of { lat: ##, lon: ##, zoom: ## } that defines the map's initial view. If not is provided, the default center set from MapBox will be used
  • zoomRange An array of [##, ##] where the first element is the minimum zoom level and the second is the max
  • features An array of additional features for the map

The features object may contain any of the following:

  • zoomwheel Use the scroll wheel on the mouse to zoom the map
  • tooltips or movetips For layers with interactive overlays, display fixed tooltips or movetips, which are overlays the follow the cursor
  • zoombox Allow uses to zoom to a bounding box by holding the shift key and dragging over the map
  • zoompan Show zoom controls on the map
  • legend Show a legend on the map. Legends from multiple layers will stack on top of each other
  • share Show a share button on the map with Twitter, Facebook links and an embed code for the map. The embedded view of the map will add a class="embed" to the <body> element of the page for easy theming. For instance, by default the embed layout is a full screen map with the layer switcher over it on the left. The header and content are hidden.
  • bwdetect Automatically detect low bandwidth contections and decrease the quality of the map images to accomodate

A map with all the options and a callback function would look like this:

var main =  Map('map', {
    api: 'http://a.tiles.mapbox.com/v3/mapbox.map-hv50mbs9.jsonp',
    center: {
        lat: 38.8850033656251,
        lon: -77.01439615889109,
        zoom: 14
    },
    zoomRange: [0, 15],
    features: [
        'zoomwheel',
        'tooltips', // or 'movetips'
        'zoombox',
        'zoompan',
        'legend',
        'share',
        'bwdetect'
    ]
}, foursquare.start);

foursquare.js

All data about store locations for this template comes from the foursquare API. Begin by logging into foursquare and creating a list of all of your venues. This example pulls addresses and phone numbers from the API, but you could extend it to include business hours, menues, photos and more by entering more information about your stores in their foursquare venue profiles. See here more about entering your store locations as foursquare venues.

To connect this template with your foursquare list, add the following to the top of your index.html configuration:

// Set up the foursquare API
foursquare.settings = {
    /* foursquare API keys. See: https://foursquare.com/oauth/register */
    client_id: '1SHOHFLYHC3KIQKMBMKRWHASORK0TPCNPPH04OQCT1Y5ZRGW',
    client_secret: '2DMK0XSZL3ZMZDNR0G0UQ4ARJYN2HIJXL4FKXZ1WUALXZYZV',
    /* List ID. See: https://developer.foursquare.com/docs/explore#req=users/self/lists */
    list: '4fc674d7e4b07a1f71542757',
    /* Search radius for nearby address matches */
    radius: 8046.72 // 5 miles in meters
};
  • client_id and client_secret These are your foursquare API keys. To get them, register your site at https://foursquare.com/oauth/register and replace the ones we are using here.
  • list This is the foursquare list ID for the list you made with your locations. To find it, we need to browse the foursquare API. Visit the foursquare API explorer and scan the json data until you find the ID for your list in the items array.
  • radius This is the radius in meters in which an location is considered a match for an address search. You could also allow the user to set this value by setting it with javascript.

The work of fetching, parsing, mapping, and filtering the venues (store locations) in your foursquare list is all handled by foursquare.js.

Further Reading

a.wax-fullscreen {
/* TODO: sprite-based fullscreen button */
position: absolute;
top: 5px;
left: 5px;
z-index: 99999;
}
a.zoomer {
text-decoration:none;
position:absolute;
background-color:#444;
color:#fff;
line-height:25px;
font-size:20px;
z-index:99999;
text-align:center;
width:25px;
height:25px;
}
a.zoomin {
left:5px;
}
a.zoomout {
left:35px;
}
a.zoomdisabled {
background-color:#333;
}
.wax-fullscreen-map {
position:fixed !important;
width:auto !important;
height:auto !important;
top:0;
left:0;
right:0;
bottom:0;
z-index:999999999999;
}
.wax-legends {
position:absolute;
left:10px;
bottom:10px;
z-index:999999;
}
.wax-legends .wax-legend {
padding:10px;
background:#333;
color:#fff;
}
.wax-tooltip {
z-index:999999;
position:absolute;
background:#333;
color:#fff;
padding:10px;
-webkit-user-select:auto;
left:10px;
top:10px;
max-width:300px;
opacity:1;
-webkit-transition:opacity 150ms;
-moz-transition:opacity 150ms;
}
.wax-movetip {
position:absolute;
z-index:999999;
background:#333;
color:#fff;
padding:10px;
max-width:300px;
}
.wax-fade { opacity:0; }
.wax-tooltip .close {
display:block;
position:absolute;
top:0px;
right:0px;
}
.wax-mobile-body .wax-tooltip {
position:absolute;
top:50px;
}
.zoombox-box,
.boxselector-box {
margin:0;
padding:0;
border:1px dashed #888;
background: rgba(255,255,255,0.25);
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
display: none;
}
.zoombox-box-container,
.boxselector-box-container,
.pointselector-box-container {
margin:0;
padding:0;
position:absolute;
background: url(blank.gif);
top:0;
left:0;
}
.wax-point-div {
width:10px;
height:10px;
margin-left:-5px;
margin-top:-5px;
background:#fff;
border:1px solid #333;
-webkit-border-radius:5px;
}
div.wax-attribution {
position:absolute;
background-color:rgba(255, 255, 255, 0.7);
color:#333;
font-size:11px;
line-height:20px;
z-index:99999;
text-align:center;
padding:0 5px;
bottom:0;
left:0;
}
.wax-attribution.wax-g {
left:65px;
bottom:4px;
background:transparent;
}
.wax-latlngtooltip {
position:absolute;
background:#caedf4;
padding:3px;
border:1px solid #75c1d0;
border-radius:3px;
}
(function(context, MM) {
easey.TouchHandler = function() {
var handler = {};
handler.init = function(map) {
var prevT = 0,
acceleration = 25.0,
speed = null,
maxTapTime = 250,
maxTapDistance = 30,
maxDoubleTapDelay = 350,
drag = 0.10,
locations = {},
taps = [],
wasPinching = false,
nowPoint = null,
oldPoint = null,
lastMove = null,
lastPinchCenter = null;
function animate(t) {
var dir = { x: 0, y: 0 };
var dt = Math.max(0.001,(t - prevT) / 1000.0);
if (nowPoint && oldPoint &&
(lastMove > (+new Date() - 50))) {
dir.x = nowPoint.x - oldPoint.x;
dir.y = nowPoint.y - oldPoint.y;
speed.x = dir.x;
speed.y = dir.y;
} else {
speed.x -= speed.x * drag;
speed.y -= speed.y * drag;
if (Math.abs(speed.x) < 0.001) {
speed.x = 0;
}
if (Math.abs(speed.y) < 0.001) {
speed.y = 0;
}
}
if (speed.x || speed.y) {
map.panBy(speed.x, speed.y);
}
prevT = t;
// tick every frame for time-based anim accuracy
MM.getFrame(animate);
}
// Test whether touches are from the same source -
// whether this is the same touchmove event.
function sameTouch (event, touch) {
return (event && event.touch) &&
(touch.identifier == event.touch.identifier);
}
function updateTouches (e) {
for (var i = 0; i < e.touches.length; i += 1) {
var t = e.touches[i];
if (t.identifier in locations) {
var l = locations[t.identifier];
l.x = t.screenX;
l.y = t.screenY;
l.scale = e.scale;
}
else {
locations[t.identifier] = {
scale: e.scale,
startPos: { x: t.screenX, y: t.screenY },
x: t.screenX,
y: t.screenY,
time: new Date().getTime()
};
}
}
}
function touchStartMachine(e) {
updateTouches(e);
return MM.cancelEvent(e);
}
function touchMoveMachine(e) {
switch (e.touches.length) {
case 1:
onPanning(e.touches[0]);
break;
case 2:
onPinching(e);
break;
}
updateTouches(e);
return MM.cancelEvent(e);
}
// Fail early if this isn't a touch device.
// TODO: move to add fn
if (!isTouchable()) return false;
MM.addEvent(map.parent, 'touchstart',
touchStartMachine);
MM.addEvent(map.parent, 'touchmove',
touchMoveMachine);
MM.addEvent(map.parent, 'touchend',
touchEndMachine);
prevT = new Date().getTime();
speed = { x: 0, y: 0 };
MM.getFrame(animate);
// Handle a tap event - mainly watch for a doubleTap
function onTap(tap) {
if (taps.length &&
(tap.time - taps[0].time) < maxDoubleTapDelay) {
onDoubleTap(tap);
taps = [];
return;
}
taps = [tap];
}
// Handle a double tap by zooming in a single zoom level to a
// round zoom.
function onDoubleTap(tap) {
// zoom in to a round number
easey().map(map)
.to(map.pointCoordinate(tap).zoomTo(map.getZoom() + 1))
.path('about').run(200, function() {
map.dispatchCallback('zoomed');
});
}
function isTouchable () {
var el = document.createElement('div');
el.setAttribute('ongesturestart', 'return;');
return (typeof el.ongesturestart === 'function');
}
function remove() {
// Fail early if this isn't a touch device.
if (!isTouchable()) return false;
MM.removeEvent(map.parent, 'touchstart',
touchStartMachine);
MM.removeEvent(map.parent, 'touchmove',
touchMoveMachine);
MM.removeEvent(map.parent, 'touchend',
touchEndMachine);
}
// Re-transform the actual map parent's CSS transformation
function onPanning(touch) {
lastMove = +new Date();
oldPoint = nowPoint;
nowPoint = { x: touch.screenX, y: touch.screenY };
// oldPoint = locations[touch.identifier];
}
function onPinching(e) {
// use the first two touches and their previous positions
var t0 = e.touches[0],
t1 = e.touches[1],
p0 = new MM.Point(t0.screenX, t0.screenY),
p1 = new MM.Point(t1.screenX, t1.screenY),
l0 = locations[t0.identifier],
l1 = locations[t1.identifier];
// mark these touches so they aren't used as taps/holds
l0.wasPinch = true;
l1.wasPinch = true;
// scale about the center of these touches
var center = MM.Point.interpolate(p0, p1, 0.5);
map.zoomByAbout(
Math.log(e.scale) / Math.LN2 -
Math.log(l0.scale) / Math.LN2,
center);
// pan from the previous center of these touches
var prevCenter = MM.Point.interpolate(l0, l1, 0.5);
map.panBy(center.x - prevCenter.x,
center.y - prevCenter.y);
wasPinching = true;
lastPinchCenter = center;
}
// When a pinch event ends, round the zoom of the map.
function onPinched(p) {
// TODO: easing
if (true) {
var z = map.getZoom(), // current zoom
tz = Math.round(z); // target zoom
map.zoomByAbout(tz - z, p);
}
wasPinching = false;
}
function touchEndMachine(e) {
var now = new Date().getTime();
// round zoom if we're done pinching
if (e.touches.length === 0 && wasPinching) {
onPinched(lastPinchCenter);
}
oldPoint = nowPoint = null;
// Look at each changed touch in turn.
for (var i = 0; i < e.changedTouches.length; i += 1) {
var t = e.changedTouches[i],
loc = locations[t.identifier];
// if we didn't see this one (bug?)
// or if it was consumed by pinching already
// just skip to the next one
if (!loc || loc.wasPinch) {
continue;
}
// we now know we have an event object and a
// matching touch that's just ended. Let's see
// what kind of event it is based on how long it
// lasted and how far it moved.
var pos = { x: t.screenX, y: t.screenY },
time = now - loc.time,
travel = MM.Point.distance(pos, loc.startPos);
if (travel > maxTapDistance) {
// we will to assume that the drag has been handled separately
} else if (time > maxTapTime) {
// close in space, but not in time: a hold
pos.end = now;
pos.duration = time;
onHold(pos);
} else {
// close in both time and space: a tap
pos.time = now;
onTap(pos);
}
}
// Weird, sometimes an end event doesn't get thrown
// for a touch that nevertheless has disappeared.
// Still, this will eventually catch those ids:
var validTouchIds = {};
for (var j = 0; j < e.touches.length; j++) {
validTouchIds[e.touches[j].identifier] = true;
}
for (var id in locations) {
if (!(id in validTouchIds)) {
delete validTouchIds[id];
}
}
return MM.cancelEvent(e);
}
};
return handler;
};
easey.DoubleClickHandler = function() {
var handler = {},
map;
function doubleClick(e) {
// Ensure that this handler is attached once.
// Get the point on the map that was double-clicked
var point = MM.getMousePoint(e, map);
z = map.getZoom() + (e.shiftKey ? -1 : 1);
// use shift-double-click to zoom out
easey().map(map)
.to(map.pointCoordinate(MM.getMousePoint(e, map)).zoomTo(z))
.path('about').run(100, function() {
map.dispatchCallback('zoomed');
});
return MM.cancelEvent(e);
}
handler.init = function(x) {
map = x;
MM.addEvent(map.parent, 'dblclick', doubleClick);
return handler;
};
handler.remove = function() {
MM.removeEvent(map.parent, 'dblclick', doubleClick);
};
return handler;
};
easey.MouseWheelHandler = function() {
var handler = {},
map,
_zoomDiv,
ea = easey(),
prevTime,
precise = false;
function mouseWheel(e) {
var delta = 0;
prevTime = prevTime || new Date().getTime();
try {
_zoomDiv.scrollTop = 1000;
_zoomDiv.dispatchEvent(e);
delta = 1000 - _zoomDiv.scrollTop;
} catch (error) {
delta = e.wheelDelta || (-e.detail * 5);
}
// limit mousewheeling to once every 200ms
var timeSince = new Date().getTime() - prevTime;
var point = MM.getMousePoint(e, map);
function dispatchZoomed() {
map.dispatchCallback('zoomed');
}
if (!ea.running()) {
var point = MM.getMousePoint(e, map),
z = map.getZoom();
ea.map(map)
.to(map.pointCoordinate(MM.getMousePoint(e, map)).zoomTo(z + (delta > 0 ? 1 : -1)))
.path('about').run(200, dispatchZoomed);
} else {
ea.zoom(ea.to().zoom + (delta > 0 ? 1 : -1));
}
// Cancel the event so that the page doesn't scroll
return MM.cancelEvent(e);
}
handler.init = function(x) {
map = x;
_zoomDiv = document.body.appendChild(document.createElement('div'));
_zoomDiv.style.cssText = 'visibility:hidden;top:0;height:0;width:0;overflow-y:scroll';
var innerDiv = _zoomDiv.appendChild(document.createElement('div'));
innerDiv.style.height = '2000px';
MM.addEvent(map.parent, 'mousewheel', mouseWheel);
return handler;
};
handler.precise = function(x) {
if (!arguments.length) return precise;
precise = x;
return handler;
};
handler.remove = function() {
MM.removeEvent(map.parent, 'mousewheel', mouseWheel);
_zoomDiv.parentNode.removeChild(_zoomDiv);
};
return handler;
};
easey.DragHandler = function() {
var handler = {},
map;
handler.init = function(map) {
var prevT = 0,
speed = null,
drag = 0.15,
mouseDownPoint = null,
mouseDownTime = 0,
mousePoint = null,
prevMousePoint = null,
moveTime = null,
prevMoveTime = null,
animatedLastPoint = true;
function mouseDown(e) {
if (e.shiftKey || e.button == 2) return;
MM.addEvent(document, 'mousemove', mouseMove);
MM.addEvent(document, 'mouseup', mouseUp);
mousePoint = prevMousePoint = MM.getMousePoint(e, map);
moveTime = prevMoveTime = +new Date();
map.parent.style.cursor = 'move';
return MM.cancelEvent(e);
}
function mouseMove(e) {
if (mousePoint) {
if (animatedLastPoint) {
prevMousePoint = mousePoint;
prevMoveTime = moveTime;
animatedLastPoint = false;
}
mousePoint = MM.getMousePoint(e, map);
moveTime = +new Date();
return MM.cancelEvent(e);
}
}
function mouseUp(e) {
MM.removeEvent(document, 'mousemove', mouseMove);
MM.removeEvent(document, 'mouseup', mouseUp);
if (+new Date() - prevMoveTime < 50) {
dt = Math.max(1, moveTime - prevMoveTime);
var dir = { x: 0, y: 0 };
dir.x = mousePoint.x - prevMousePoint.x;
dir.y = mousePoint.y - prevMousePoint.y;
speed.x = dir.x / dt;
speed.y = dir.y / dt;
} else {
speed.x = 0;
speed.y = 0;
}
mousePoint = prevMousePoint = null;
moveTime = lastMoveTime = null;
map.parent.style.cursor = '';
return MM.cancelEvent(e);
}
function animate(t) {
var dir = { x: 0, y: 0 };
var dt = Math.max(1, t - prevT);
if (mousePoint && prevMousePoint) {
if (!animatedLastPoint) {
dir.x = mousePoint.x - prevMousePoint.x;
dir.y = mousePoint.y - prevMousePoint.y;
map.panBy(dir.x, dir.y);
animatedLastPoint = true;
}
} else {
// Rough time based animation accuracy
// using a linear approximation approach
speed.x *= Math.pow(1 - drag, dt * 60 / 1000);
speed.y *= Math.pow(1 - drag, dt * 60 / 1000);
if (Math.abs(speed.x) < 0.001) {
speed.x = 0;
}
if (Math.abs(speed.y) < 0.001) {
speed.y = 0;
}
if (speed.x || speed.y) {
map.panBy(speed.x * dt, speed.y * dt);
}
}
prevT = t;
MM.getFrame(animate);
}
MM.addEvent(map.parent, 'click', function(e) {
map.parent.focus();
});
MM.addEvent(map.parent, 'mousedown', mouseDown);
prevT = new Date().getTime();
speed = { x: 0, y: 0 };
MM.getFrame(animate);
};
return handler;
};
})(this, MM);
(function(context, MM) {
var easey = function() {
var easey = {},
running = false,
abort = false; // killswitch for transitions
var easings = {
easeIn: function(t) { return t * t; },
easeOut: function(t) { return Math.sin(t * Math.PI / 2); },
linear: function(t) { return t; }
};
// to is the singular coordinate that any transition is based off
// three dimensions:
//
// * to
// * time
// * path
var from, to, map;
easey.stop = function() {
abort = true;
};
easey.running = function() {
return running;
};
easey.point = function(x) {
to = map.pointCoordinate(x);
return easey;
};
easey.zoom = function(x) {
to.zoomTo(x);
return easey;
};
easey.location = function(x) {
to = map.locationCoordinate(x);
return easey;
};
easey.from = function(x) {
if (!arguments.length) return from.copy();
from = x.copy();
return easey;
};
easey.to = function(x) {
if (!arguments.length) return to.copy();
to = x.copy();
return easey;
};
easey.path = function(x) {
path = paths[x];
return easey;
};
easey.map = function(x) {
map = x;
from = map.coordinate.copy();
to = map.coordinate.copy();
return easey;
};
function interp(a, b, p) {
if (p === 0) return a;
if (p === 1) return b;
return a + ((b - a) * p);
}
var paths = {};
// The screen path simply moves between
// coordinates in a non-geographical way
paths.screen = function(a, b, t) {
var zoom_lerp = interp(a.zoom, b.zoom, t);
var az = a.copy();
var bz = b.copy().zoomTo(a.zoom);
return (new MM.Coordinate(
interp(az.row, bz.row, t),
interp(az.column, bz.column, t),
az.zoom)).zoomTo(zoom_lerp);
};
function ptWithCoords(a, b) {
// distance from the center of the map
var point = new MM.Point(map.dimensions.x / 2, map.dimensions.y / 2);
point.x += map.tileSize.x * (b.column - a.column);
point.y += map.tileSize.y * (b.row - a.row);
return point;
}
// The screen path means that the b
// coordinate should maintain its point on screen
// throughout the transition, but the map
// should move to its zoom level
paths.about = function(a, b, t) {
var zoom_lerp = interp(a.zoom, b.zoom, t);
var bs = b.copy().zoomTo(a.zoom);
var az = a.copy().zoomTo(zoom_lerp);
var bz = b.copy().zoomTo(zoom_lerp);
var start = ptWithCoords(a, bs);
var end = ptWithCoords(az, bz);
az.column -= (start.x - end.x) / map.tileSize.x;
az.row -= (start.y - end.y) / map.tileSize.y;
return az;
};
var path = paths.screen;
easey.t = function(t) {
map.coordinate = path(from, to, t);
map.draw();
return easey;
};
easey.future = function(parts) {
var futures = [];
for (var t = 0; t < 1; t += (1 / parts)) {
futures.push(lerp(from, to, t));
}
return futures;
};
var fastFrame = function(callback) {
window.setTimeout(function () {
callback(+new Date());
}, 1);
};
easey.run = function(time, callback) {
var start = (+new Date());
running = true;
function tick() {
var delta = (+new Date()) - start;
if (abort) {
return void (abort = running = false);
} else if (delta > time) {
running = false;
map.coordinate = path(from, to, 1);
map.draw();
if (callback) return callback(map);
} else {
map.coordinate = path(from, to, easings.easeIn(delta / time));
map.draw();
fastFrame(tick);
}
}
MM.getFrame(tick);
};
return easey;
};
this.easey = easey;
})(this, com.modestmaps);
var foursquare = {};
// Array for venues queue
foursquare.venues = [];
// Get venues
foursquare.start = function() {
// Default ajax params
foursquare.params = {
client_id: foursquare.settings.client_id,
client_secret: foursquare.settings.client_secret,
v: '20120530',
callback: 'callback'
};
foursquare.geocoder();
foursquare.getVenues();
};
// Fetch venues from foursquare
foursquare.getVenues = function() {
query = '?' + _.map(foursquare.params, function(num, key) {
return key + "=" + num;
}).join('&');
reqwest({
url: 'https://api.foursquare.com/v2/lists/' + foursquare.settings.list + query,
type: 'jsonp',
jsonCallback: 'callback',
success: function(d) {
foursquare.processVenues(d);
}
});
};
// Extract relevant data from venues
foursquare.processVenues = function(d) {
_.each(d.response.list.listItems.items, function(item, index) {
if (item.venue.location && item.venue.location.lat && item.venue.location.lng) {
foursquare.venues.push(item.venue);
}
});
foursquare.table();
foursquare.map();
};
// Build a table of locations
foursquare.table = function() {
var template = _.template(
'<div class="venue">' +
'<div class="location"><a href="#<%= id %>"><%= location.address %></a> ' +
'<% if(location.crossStreet) { %><%= location.crossStreet %><%}%>' +
'<% if(location.city !=="Washington") { %><br><em><%= location.city %></em><%}%>' +
'</div>' +
'<% if(contact.formattedPhone) { %>' +
'<div class="phone"><%= contact.formattedPhone %></div>' +
'<%}%>' +
'</div>'
);
var groups = _.groupBy(foursquare.venues, function(item) {
return (item.location.state||'').replace(/\./g,'');
});
var output = [];
_.each(groups, function(items, state) {
output.push('<div class="state-group '+ state.toLowerCase().replace(/\./g,'') + '">' +
'<h3 class="state-label">'+ state.replace(/\./g, '') + '</h3>');
_.each(items, function(item) {
output.push(template(item));
});
output.push('</div>');
});
$('#content').append(output.join(''));
$('.location a').click(function(e) {
e.preventDefault();
var id = $(this).attr('href').substring(1);
if ($(this).parent().parent().hasClass('active')) {
$(this).parent().parent().removeClass('active');
$('#' + id).removeClass('active');
} else {
var point = _.find(foursquare.venues, function(item) {
return item.id === id
});
$('.mmg, .venue').removeClass('active');
$(this).parent().parent().addClass('active');
// Move map to adjusted center
MM_map.easey = easey().map(MM_map)
.to(MM_map.locationCoordinate(locationOffset({
lat: point.location.lat,
lon: point.location.lng
})).zoomTo(MM_map.getZoom())).run(500, function() {
$('#' + id).addClass('active');
});
}
});
// Foursquare button
(function() {
window.___fourSq = {"uid":"19778482"};
var s = document.createElement('script');
s.type = 'text/javascript';
s.src = 'http://platform.foursquare.com/js/widgets.js';
s.async = true;
var ph = document.getElementsByTagName('script')[0];
ph.parentNode.insertBefore(s, ph);
})();
};
// Map the venues
foursquare.map = function() {
var points = { 'type': 'FeatureCollection',
'features': []
};
_.each(_.rest(foursquare.venues, foursquare.last || 0), function(venue) {
points.features.push({
type: 'Feature',
id: venue.id,
geometry: {
type: 'Point',
coordinates: [venue.location.lng, venue.location.lat]
},
properties: {
name: venue.name,
location: venue.location,
stats: venue.stats
}
});
});
foursquare.last = foursquare.venues.length;
if (MM_map.venueLayer) {
MM_map.venueLayer.geojson(points);
} else {
MM_map.venueLayer = mmg().factory(function(x) {
var d = document.createElement('div'),
overlay = document.createElement('div'),
anchor = document.createElement('div');
var template = _.template(
'<div class="location">' +
'<span class="name fn"><%= name %></span>' +
'<span class="adr">' +
'<span class="address street-address"><%= location.address %></span>' +
'<% if (location.crossStreet) { %>' +
'<span class="cross-street"><%= location.crossStreet %></span>' +
'<% } %>' +
'<span class="city-state">' +
'<span class="locality"><%= location.city %></span>, ' +
'<span class="region"><%= location.state %></span>' +
'</span>' +
'</span>' +
'</div>' +
'<div class="foursquare">' +
'<a href="https://foursquare.com/intent/venue.html" class="fourSq-widget" data-variant="wide" data-context="'+ x.id +'">Save to foursquare</a>' +
'<div class="checkins">' +
'<span class="number"><%= stats.checkinsCount %></span>' +
'<span class="label">checkins</span>' +
'</div>' +
'<div class="users">' +
'<span class="number"><%= stats.usersCount %></span>' +
'<span class="label">users</span>' +
'</div>' +
'</div>'
);
overlay.className = 'overlay';
overlay.innerHTML = template(x.properties);
anchor.className = 'anchor';
anchor.appendChild(overlay);
d.id = x.id;
d.className = 'mmg vcard';
d.appendChild(anchor);
return d;
}).geojson(points);
MM_map.addLayer(MM_map.venueLayer);
}
MM_map.setCenter({
lat: MM_map.getCenter().lat,
lon: MM_map.getCenter().lon
});
// Handlers
$('.mmg').click(function(e) {
e.preventDefault();
$('[href=#' + $(this).attr('id') + ']').click();
});
$('#showall').click(function(e) {
e.preventDefault();
$('.venue, .state-group').removeClass('hidden');
$('.venue, .mmg').removeClass('active');
$(this).addClass('hidden');
$('#no-venues').addClass('hidden');
$('input[type=text]', '#search form').val('').focus();
});
};
foursquare.refresh = function(coords) {
// Remove active states
$('.venue, .mmg').removeClass('active');
$('.venue, .state-group').removeClass('hidden');
$('#no-venues, #showall').addClass('hidden');
var radius = foursquare.settings.radius,
closest = { dist: radius, id: '', loc: {} };
// Loop through venues and calculate distance
_.each(foursquare.venues, function(venue) {
var center = coords,
location = { lat: venue.location.lat, lon: venue.location.lng },
distance = MM.Location.distance(center, location);
// Hide venues outsite radius,
if (distance > radius /* 5 miles in meters */) {
$('[href=#' + venue.id + ']').parent().parent().addClass('hidden');
} else {
if (distance < closest.dist) {
closest = { dist: distance, id: venue.id, loc: location};
}
}
});
// Hide labels
$('.state-group').each(function() {
if($('.venue', this).not('.hidden').size() === 0)
$(this).addClass('hidden');
});
// Display a 'show all' link
$('#showall').removeClass('hidden');
// Show 'no results' message'
if($('.venue').not('.hidden').size() === 0)
$('#no-venues').removeClass('hidden');
// If there are results
if(closest.id) {
$('[href=#' + closest.id + ']').parent().parent().addClass('active');
$('#' + closest.id).addClass('active');
// Center on point
MM_map.zoom(14).center(locationOffset(closest.loc));
} else {
MM_map.zoom(8).center(locationOffset(coords));
}
};
foursquare.geocoder = function() {
$('#search').submit(function(e) {
e.preventDefault();
geocode($('input[type=text]', this).val(), MM_map);
});
var geocode = function(query, m) {
params = '?' + _.map(foursquare.params, function(num, key) {
return key + "=" + num;
}).join('&');
query = encodeURIComponent(query);
$('form.geocode').addClass('loading');
reqwest({
url: 'https://api.foursquare.com/v2/venues/search'+
params + '&limit=1&intent=match&near=' + query,
type: 'jsonp',
jsonpCallback: 'callback',
success: function (r) {
$('form.geocode').removeClass('loading');
if (r.response.geocode === undefined) {
$('#geocode-error').text('This address cannot be found.').fadeIn('fast');
} else {
r = r.response.geocode.feature;
$('#geocode-error').hide();
var attribution = 'Search by ' + r.attribution;
if ($('.wax-attribution').html().indexOf(attribution) < 0) {
$('.wax-attribution').append(' - ' + attribution);
}
foursquare.refresh({
lat: r.geometry.center.lat,
lon: r.geometry.center.lng
});
}
}
});
};
};
// Calculate offset given #content
function locationOffset(location) {
var offset = MM_map.locationPoint({
lat: location.lat,
lon: location.lon
});
offset = MM_map.pointLocation({
x: offset.x - $('#content').width() / 2,
y: offset.y
});
return offset;
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Sweetgreen</title>
<meta name="Description" content="Sweetgreen." />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<!-- Scripts -->
<script type="text/javascript" src="http://sweetgreen.com/scripts/jquery-1.4.1.min.js"></script>
<script type="text/javascript" src="http://sweetgreen.com/scripts/sweetgreen.js"></script>
<script type="text/javascript" src="http://sweetgreen.com/fancybox/jquery.mousewheel-3.0.2.pack.js"></script>
<script type="text/javascript" src="http://sweetgreen.com/fancybox/jquery.fancybox-1.3.1.js"></script>
<link rel="stylesheet" type="text/css" href="http://sweetgreen.com/fancybox/jquery.fancybox-1.3.1.css" media="screen" />
<!-- SWEETGREEN API KEY -->
<!-- CSS -->
<link href="http://sweetgreen.com/css/global.css" type="text/css" rel="stylesheet" />
<link href="http://sweetgreen.com/css/layout.css" type="text/css" rel="stylesheet" />
<link href="http://sweetgreen.com/css/text.css" type="text/css" rel="stylesheet" />
<script type="text/javascript">
var geocoder;
var locations;
var map;
var markers;
$(document).ready(function() {
initVIP();
initializeMap();
$("a#g2").fancybox({
'titleShow' : false
});
$("a#d2").fancybox({
'titleShow' : false
});
$("a#c2").fancybox({
'titleShow' : false
});
$("a#r2").fancybox({
'titleShow' : false
});
$("#vipsubmit").fancybox({
'titlePosition' : 'inside',
'transitionIn' : 'none',
'transitionOut' : 'none'
});
});
</script>
</head>
<body>
<div class="page">
<!-- Header -->
<div class="header clearfix" style="margin-bottom:44px;">
<!-- Navigation -->
<div id="navigation" class="clearfix">
<div id="navigation_primary" class="clearfix">
<div id="nav_sweetlife" class="navItem_y"><a href="http://sweetlife.is/" alt="Sweetlife"><img src="http://sweetgreen.com/images/navigation/sweetlife.png" alt="sweetlife" border="0" /></a></div>
<div id="nav_philosophy" class="navItem"><a href="http://sweetgreen.com/philosophy/" alt="Philosophy"><img src="http://sweetgreen.com/images/navigation/philosophy.png" alt="philosophy" border="0" /></a></div>
<div id="nav_menu" class="navItem"><a href="http://sweetgreen.com/menu/" alt="Menu"><img src="http://sweetgreen.com/images/navigation/menu.png" alt="menu" border="0" /></a></div>
<div id="nav_locations" class="navItemOn_2010"><a href="http://sweetgreen.com/locations/" alt="Locations"><img src="http://sweetgreen.com/images/navigation/locations.png" alt="locations" border="0" /></a></div>
<!--<div id="nav_shop" class="navItem"><a href="http://sweetgreen.com/shop.php" alt="Shop"><img src="http://sweetgreen.com/images/navigation/shop.png" alt="shop" border="0" /></a></div>-->
<div id="nav_sustainability" class="navItem"><a href="http://sweetgreen.com/sustainability/" alt="Sustainability"><img src="http://sweetgreen.com/images/navigation/sustainability.png" alt="sustainability" border="0" /></a></div>
<!--<div id="nav_sweetflow" class=""><a href="http://sweetgreen.com/sweetflow.php" alt="Sweetflow"><img src="http://sweetgreen.com/images/navigation/sweetflow.png" alt="sweetflow mobile" border="0" /></a></div>-->
<div id="nav_careers" class="navItem"><a href="http://sweetgreen.com/careers.php" alt="Careers"><img src="http://sweetgreen.com/images/navigation/careers_new.png" alt="careers" border="0" /></a></div>
</div>
<div id="navigation_secondary" class="clearfix">
<!--<div id="nav_careers" class="navItem"><a href="http://sweetgreen.com/careers.php" alt="Careers"><img src="http://sweetgreen.com/images/navigation/careers.png" alt="careers" border="0"/></a></div>-->
<div id="nav_media" class="navItem"><a href="http://sweetgreen.com/media.php" alt="Media"><img src="http://sweetgreen.com/images/navigation/media.png" alt="media" border="0"/></a></div>
<div id="nav_contact" class="navItem"><a href="http://sweetgreen.com/contact.php" alt="Contact"><img src="http://sweetgreen.com/images/navigation/contact.png" alt="contact" border="0"/></a></div>
</div>
</div>
<div id="logo"><a href="http://sweetgreen.com/" alt="Home"><img src="http://sweetgreen.com/images/logo.png" alt="Home" border="0"/></a></div>
<a class="savetime" href="http://sweetgreen.com/ordering.php" onClick="recordOutboundLink(this, 'Outbound Links', 'sweetgreen.exit41.com/Exit41Online/home.htm');return true;"><div id="savetime_div"></div></a>
<div id="social_container" >
<div id="twitter_btn">
<a href="http://twitter.com/sweetgreen" class="twitter-follow-button" data-show-count="false" data-button="grey" data-link-color="8FBE30" data-text-color="8FBE30"></a>
<script src="http://platform.twitter.com/widgets.js" type="text/javascript"></script>
</div>
<div id="fb_btn">
<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fwww.facebook.com%2Fsweetgreen&amp;layout=button_count&amp;show_faces=false&amp;width=80&amp;action=like&amp;font=arial&amp;colorscheme=light&amp;" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:80px;height:25px;" allowTransparency="true"></iframe>
</div>
<div id="clear_it"></div>
</div>
</div>
<div class="content">
<div class="secondary_content clearfix">
<iframe src="index.html" frameborder="0" width="100%" height="620px"></iframe>
</div>
</div>
<!-- Footer -->
<script>
$(document).ready(function() {
$("a#inline").fancybox({
'transitionIn' : 'elastic',
'transitionOut' : 'elastic'
});
});//document ready end
</script>
<div style="display:none;">
<div id="data" style="color:#666666;width:420px;text-align:center;">
<img src="http://sweetgreen.com/images/sweetflow/sf_truck.jpg" alt="Sweetflow Mobile" border="0" usemap="#sfMap" />
<br />
<map name="sfMap" id="sfMap">
<area shape="rect" coords="6,244,45,332" href="http://twitter.com/SweetflowMobile" target="_blank" alt="Sweetflow Mobile Twitter" />
<area shape="rect" coords="50,243,91,331" href="http://www.facebook.com/sweetflowmobile" target="_blank" alt="Sweetflow Facebook" />
</map>
<br />
<div style="width:400px;height:150px;overflow:auto;background-color:#e1e1e1;padding:10px;text-align:left;">
<h2><span style="font-size: 12px;">monday</span></h2>
<p>TBD! Help us decide where to go this summer?</p>
<h3>tuesday</h3>
<p>11:30am - 1:30pm &nbsp;L'Enfant Plaza (7th &amp; Maryland SW)<br />2:30 - 6:30pm &nbsp;Crystal City Farmer's Market! (20th and S Ball Street)<br /><br /></p>
<p><span style="font-size: 12px; font-weight: bold;">wednesday</span></p>
<p>10:30am - 2:00pm Health &amp; Human Resources Farmer's Market (L'Enfant)<br />7:30pm - 10:00pm NOMA Movies</p>
<p><span style="font-size: 12px; font-weight: bold;">thursday</span></p>
<p>11:30am - 1:30pm &nbsp;L'Enfant Plaza!</p>
<p>TBD! Give us a good spot to try!&nbsp;</p>
<h3>friday</h3>
<p>11:30 - 1:30pm Farragut Square</p>
</div>
<br />
<strong>Book us for an event via <a href="mailto:tim@sweetgreen.com">tim@sweetgreen.com</a></strong></div>
</div>
<div class="footer">
<div id="social" class="clearfix">
<div id="email">
<div id="vipemailform">
<table border="0" cellspacing="0" cellpadding="3" >
<tr>
<h3>Become a VIP</h3></tr>
<tr>
<td>
<form name="ccoptin" action="http://visitor.constantcontact.com/d.jsp" target="_blank" type="text" method="post" style="margin-bottom:2;">
<input type="hidden" name="m" value="1103469146266">
<input type="hidden" name="p" value="oi">
<input type="text" class="textinput transparency" name="ea" size="20" value="Email" style="font-size:10pt;">
&nbsp;<input style="position:absolute;" type="image" src="http://sweetgreen.com/images/footer/arrow.gif" name="button" />
</form>
</td>
</tr>
</table>
</div>
</div>
<div id="links">
<!--<a id="inline" href="#data" title=""><img src="http://sweetgreen.com/images/footer/sf_big_icon.png" border="0"></a>
<a href="http://twitter.com/sweetgreen" target="_blank"><img src="http://sweetgreen.com/images/footer/tw_2011.png" border="0"></a>
<a href="http://www.facebook.com/sweetgreen" target="_blank"><img src="http://sweetgreen.com/images/footer/fb_2011.png" border="0"></a>--> </div>
</div>
<div style="margin-bottom:40px"></div>
<div id="s508" class="clearfix">
<div id="s508_about">
<h3><a href="http://sweetgreen.com/philosophy/">Welcome to sweetgreen</a></h3>
<p>sweetgreen is the answer to the new era of fast-casual dining. We <br />
offer customers delicious, all-natural salads and refreshing frozen yogurts. With local, farm-fresh ingredients, award winning decor and operational simplicity, sweetgreen creates a chic atmosphere and a unique dining experience.</p>
</div>
<div id="s508_nav">
<div class="leftbucket">
<h3><a href="http://sweetlife.is/">blog</a></h3>
</div>
<div class="leftbucket">
<h3><a href="http://sweetgreen.com/philosophy/">philosophy</a></h3>
</div>
<div class="leftbucket">
<h3><a href="http://sweetgreen.com/menu/">menu</a></h3>
<a href="http://sweetgreen.com/menu/">salads</a><br />
<a href="http://sweetgreen.com/menu/mixyourown.php">mix-your-own</a><br />
<a href="http://sweetgreen.com/menu/yogurt.php">yogurt</a><br />
<a href="http://sweetgreen.com/menu/seasonal.php">seasonal</a><br />
</div>
<div class="leftbucket">
<h3><a href="http://sweetgreen.com/locations/">locations</a></h3>
<p><a href="http://sweetgreen.com/locations/">capitol hill, dc</a><br />
<a href="http://sweetgreen.com/locations/">dupont, dc</a><br />
<a href="http://sweetgreen.com/locations/">foggy bottom, dc</a><br />
<a href="http://sweetgreen.com/locations/">georgetown, dc</a><br />
<a href="http://sweetgreen.com/locations/">logan circle, dc</a>
<br />
<a href="http://sweetgreen.com/locations/">bethesda, md</a><br />
<a href="http://sweetgreen.com/locations/">college park, md</a><br />
<a href="http://sweetgreen.com/locations/">reston, va</a><br />
<a href="http://sweetgreen.com/locations/">ballston, va</a><br />
<a href="http://sweetgreen.com/locations/">ardmore, pa</a><br />
<a href="http://sweetgreen.com/locations/">upenn, pa</a>
<br />
<br />
</p>
</div>
<div class="leftbucket">
<h3><a href="http://sweetgreen.com/shop.php">shop</a></h3>
</div>
<div class="leftbucket">
<h3><a href="http://sweetgreen.com/sustainability/">sustainability</a></h3>
</div>
<!--<div class="leftbucket">
<h3><a href="http://sweetgreen.com/sweetflow.php">sweetflow</a></h3>
<a href="http://sweetgreen.com/sweetflow.php">about</a><br />
<a href="http://sweetgreen.com/sweetflow_menu.php">menu</a><br />
<a href="http://sweetgreen.com/sweetflow_schedule.php">schedule</a><br />
</div>
<div class="leftbucket">
<h3><a href="http://sweetgreen.com/catering.php">catering</a></h3>
</div> -->
</div>
<div style="clear:both"></div>
</div>
<div style="height:100px;"></div>
<div id="privacy clearfix">
<div style="float:left" class="fineprint">
&copy; 2012 sweetgreen, Inc. | All rights reserved | <a href="http://sweetgreen.com/privacy.php">Privacy</a>
</div>
<div style="float:right">
<a href="http://www.unisonagency.com"><img src="http://sweetgreen.com/images/unison.png" border="0" /></a>
</div>
</div>
<div style="height:20px;"></div></div>
<div style="display: none;">
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-8921332-1");
pageTracker._trackPageview();
} catch(err) {}</script>
<script type="text/javascript">
function recordOutboundLink(link, category, action) {
try {
var pageTracker=_gat._getTracker("UA-8921332-1");
pageTracker._trackEvent(category, action);
//setTimeout('document.location = "' + link.href + '"', 100)
setTimeout(null, 100)
}catch(err){}
}
</script>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Foursquare Store Locator</title>
<link rel="stylesheet" href="map.css" type="text/css" />
<link rel="stylesheet" href="style.css" type="text/css" />
<link rel="shortcut icon" href="http://mapbox.com/images/favicon.ico" type="image/x-icon" />
</head>
<body class="left">
<div id="content"><div class="limiter">
<h1>Store Locator</h1>
<a id="showall" class="hidden" href="#">Address filter</a>
<div id="no-venues" class="hidden">Oops! Looks like there are no <strong>sweetgreen</strong> locations within five miles of this address. Try another search.</div>
</div></div>
<div id="map" class="map"></div>
<a href="https://foursquare.com/" target="_blank">
<img id="fsq-attribution" src="img/powered-by.png">
</a>
<div id="search">
<form class="geocode">
<input placeholder='Enter city, state, or ZIP' type="text">
<input type='submit' />
<div id='geocode-error'></div>
</form>
</div>
<!-- External libraries and site script -->
<script src="ext/jquery.min.js"></script>
<script src="ext/underscore.min.js"></script>
<script src="ext/modestmaps.min.js"></script>
<script src="ext/wax/wax.mm.js"></script>
<script src="ext/wax/wax.ext.js"></script>
<script src="ext/easey.js"></script>
<script src="ext/easey.handlers.js"></script>
<script src="ext/mmg.js"></script>
<script src="script.js"></script>
<script src="foursquare.js"></script>
<!-- Site configuration -->
<script type="text/javascript">
// Set up the foursquare API
foursquare.settings = {
/* foursquare API keys. See: https://foursquare.com/oauth/register */
client_id: 'SX5IVSDFBGQ2L4RB5W5O42MCIUH303JJTLWZFD4BQ55ZSA10',
client_secret: 'KEK45KXVWGVHLSBGUBQCBR3OJX423I5TARTXNFV0OPBYJGOR',
/* List ID. See: https://developer.foursquare.com/docs/explore#req=users/self/lists */
list: '50498c34e4b00235e830d4fe',
/* Search radius for nearby address matches */
radius: 8046.72 // 5 miles in meters
};
// Make a new map in #map
var main = Map('map', {
api: 'http://a.tiles.mapbox.com/v3/snkatk.map-bdkwanmh.jsonp',
center: {
lat: 39,
lon: -110,
zoom: 4
},
zoomRange: [1, 17],
features: [
'zoomwheel',
'zoombox',
'zoompan',
]
}, foursquare.start);
</script>
</body>
</html>
/*! jQuery v1.7.3pre jquery.com | jquery.org/license */
(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"<!doctype html>":"")+"<html><body>"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&f.type(b)==="object")for(var e in b)b_(a+"["+e+"]",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bZ(a,c,d,e,"*",g));return l}function bY(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bB(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?1:0,g=4;if(d>0){if(c!=="border")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,"padding"+bx[e]))||0),c==="margin"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0;return d+"px"}d=by(a,b);if(d<0||d==null)d=a.style[b];if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,"padding"+bx[e]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+"px"}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?b.outerHTML=a.outerHTML:c!=="input"||a.type!=="checkbox"&&a.type!=="radio"?c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute("_submit_attached"),b.removeAttribute("_change_attached"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.3pre",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d=="object"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?n(g):h==="function"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.shift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement("div"),q=c.documentElement;p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="<div "+n+"display:block;'><div style='"+t+"0;display:block;overflow:hidden;'></div></div>"+"<table "+n+"' cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="<table><tr><td style='"+t+"0;display:none'></td><td>t</td></tr></table>",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="<div style='width:5px;'></div>",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,"parsedAttrs")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf("data-")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,"parsedAttrs",!0)}}return m}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!";return f.access(this,function(c){if(c===b){m=this.triggerHandler("getData"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler("setData"+e,d),f.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,""),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/
,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:g&&G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!=="click")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);return c.result}},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(l.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function v(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\W/;[0,0].sort(function(){i=!1;return 0});var l=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,m,p,q,s,t,u=!0,v=l.isXML(d),w=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],w.push(i[1]);if(i[2]){m=i[3];break}}}while(i);if(w.length>1&&o.exec(b))if(w.length===2&&n.relative[w[0]])j=x(w[0]+w[1],d,f);else{j=n.relative[w[0]]?[d]:l(w.shift(),d);while(w.length)b=w.shift(),n.relative[b]&&(b+=w.shift()),j=x(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&n.match.ID.test(w[0])&&!n.match.ID.test(w[w.length-1])&&(p=l.find(w.shift(),d,v),d=p.expr?l.filter(p.expr,p.set)[0]:p.set[0]);if(d){p=f?{expr:w.pop(),set:r(f)}:l.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=p.expr?l.filter(p.expr,p.set):p.set,w.length>0?k=r(j):u=!1;while(w.length)q=w.pop(),s=q,n.relative[q]?s=w.pop():q="",s==null&&(s=d),n.relative[q](k,s,v)}else k=w=[]}k||(k=j),k||l.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&l.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else r(k,e);m&&(l(m,h,e,f),l.uniqueSort(e));return e};l.uniqueSort=function(a){if(t){h=i,a.sort(t);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},l.matches=function(a,b){return l(a,null,null,b)},l.matchesSelector=function(a,b){return l(b,null,null,[a]).length>0},l.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=n.order.length;e<f;e++){h=n.order[e];if(g=n.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=n.find[h](g,b,c);if(d!=null){a=a.replace(n.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},l.filter=function(a,c,d,e){var f,g,h,i,j,k,m,o,p,q=a,r=[],s=c,t=c&&c[0]&&l.isXML(c[0]);while(a&&c.length){for(h in n.filter)if((f=n.leftMatch[h].exec(a))!=null&&f[2]){k=n.filter[h],m=f[1],g=!1,f.splice(1,1);if(m.substr(m.length-1)==="\\")continue;s===r&&(r=[]);if(n.preFilter[h]){f=n.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(o=0;(j=s[o])!=null;o++)j&&(i=k(j,f,o,s),p=e^i,d&&i!=null?p?g=!0:s[o]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(n.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)l.error(a);else break;q=a}return s},l.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var m=l.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9||d===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)e+=m(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=m(c));return e},n=l.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!k.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&l.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!k.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&l.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=w;typeof b=="string"&&!k.test(b)&&(b=b.toLowerCase(),d=b,g=v),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=w;typeof b=="string"&&!k.test(b)&&(b=b.toLowerCase(),d=b,g=v),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||l.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&l.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&n.attrMap[g]&&(a[1]=n.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=l(b[3],null,null,c);else{var g=l.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(n.match.POS.test(b[0])||n.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!l(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=n.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||m([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}l.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attr?l.attr(a,c):n.attrHandle[c]?n.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&l.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=n.setFilters[e];if(f)return f(a,c,b,d)}}},o=n.match.POS,p=function(a,b){return"\\"+(b-0+1)};for(var q in n.match)n.match[q]=new RegExp(n.match[q].source+/(?![^\[]*\])(?![^\(]*\))/.source),n.leftMatch[q]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[q].source.replace(/\\(\d+)/g,p));n.match.globalPOS=o;var r=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(s){r=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var t,u;c.documentElement.compareDocumentPosition?t=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(t=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return u(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return u(e[k],f[k]);return k===c?u(a,f[k],-1):u(e[k],b,1)},u=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(n.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},n.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(n.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(n.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=l,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){l=function(b,e,f,g){e=e||c;if(!g&&!l.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return r(e.getElementsByTagName(b),f);if(h[2]&&n.find.CLASS&&e.getElementsByClassName)return r(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return r([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return r([],f);if(i.id===h[3])return r([i],f)}try{return r(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,m=e.getAttribute("id"),o=m||d,p=e.parentNode,q=/^\s*[+~]/.test(b);m?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),q&&p&&(e=e.parentNode);try{if(!q||p)return r(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{m||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)l[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}l.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!l.isXML(a))try{if(e||!n.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return l(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;n.order.splice(1,0,"CLASS"),n.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?l.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?l.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:l.contains=function(){return!1},l.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var x=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=n.match.PSEUDO.exec(a))f+=d[0],a=a.replace(n.match.PSEUDO,"");a=n.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)l(a,g[h],e,c);return l.filter(f,e)};l.attr=f.attr,l.selectors.attrMap={},f.find=l,f.expr=l.selectors,f.expr[":"]=f.expr.filters,f.unique=l.uniqueSort,f.text=l.getText,f.isXMLDoc=l.isXML,f.contains=l.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")[\\s/>]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack
(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:"GET",global:!1,url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1></$2>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]==="<table>"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,"script")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName("script"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\([^)]*\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\-+]?(?:\d*\.)?\d+$/i,bt=/^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,bu=/^([\-+])=([\-+.\de]+)/,bv=/^margin/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Top","Right","Bottom","Left"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),(e===""&&f.css(d,"display")==="none"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,"olddisplay",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(ct("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&"expand"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),q?(f._data(this,"toggle"+i,q==="show"?"hide":"show"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?"":"px"),p!=="px"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]==="-="?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct("show",1),slideUp:ct("hide",1),slideToggle:ct("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,"fxshow"+e.prop)===b&&(e.options.hide?f._data(e.elem,"fxshow"+e.prop,e.start):e.options.show&&f._data(e.elem,"fxshow"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf("margin")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,left:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position==="fixed")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position==="relative"||j.position==="static")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position==="fixed"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
Copyright (c) 2012, Development Seed
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
.ts-error {
margin:0px;
padding:0px;
color:#222;
font:normal 13px/20px Arial,sans-serif;
}
a,
.ts-error a {
color:#489;
text-decoration:none;
}
small { font-size:11px; }
h1,
h2,
h3,
h4,
h5,
h6 { font-size:16px; }
h1,
h2,
h3,
h4,
h5,
h6,
p { margin:0px 0px 10px; }
/* ### General control styles ### */
.close,
.share,
.zoomer,
.wax-legend,
.wax-tooltip,
.wax-share div,
.wax-share .twitter,
.wax-share .facebook {
display:block;
position:absolute;
border:1px solid #ccc;
background:#fff;
border-radius:3px;
-moz-border-radius:3px;
-webkit-border-radius:3px;
box-shadow:rgba(0,0,0,0.1) 0px 1px 3px;
-moz-box-shadow:rgba(0,0,0,0.1) 0px 1px 3px;
-webkit-box-shadow:rgba(0,0,0,0.1) 0px 1px 3px;
}
/* ### Tooltips, legends ### */
.wax-legends,
.wax-tooltip {
position:absolute;
z-index:999998;
right:10px;
}
.wax-legends { bottom:10px; }
.wax-tooltip { top:10px; }
.wax-legend,
.wax-tooltip {
padding:4px 9px;
min-width:180px;
max-width:280px;
max-height:400px;
overflow:auto;
width:220px\9; /* IE 8 and below */
}
.wax-legend { position:relative; }
/* ### Zoomer, close buttons, share ### */
.close,
.zoomer {
text-indent:-9999px;
background-image:url(/assets/tilestream-pro/images/controls.png);
background-position:60px 60px;
background-repeat:no-repeat;
overflow:hidden;
}
.close:active,
.zoomer:active {
border-color:#bbb;
background-color:#ddd;
box-shadow:inset rgba(0,0,0,0.1) 0px 1px 3px;
-moz-box-shadow:inset rgba(0,0,0,0.1) 0px 1px 3px;
-webkit-box-shadow:inset rgba(0,0,0,0.1) 0px 1px 3px;
}
.close {
top:4px;
right:4px;
width:18px;
height:18px;
background-position:-6px -6px;
}
.zoomer {
width:28px;
height:28px;
top:10px;
left:10px;
z-index: 2;
}
.zoomin {
background-position:-31px -1px;
left:39px;
border-radius:0px 3px 3px 0px;
-moz-border-radius:0px 3px 3px 0px;
-webkit-border-radius:0px 3px 3px 0px;
}
.zoomout {
background-position:-61px -1px;
border-radius:3px 0px 0px 3px;
-moz-border-radius:3px 0px 0px 3px;
-webkit-border-radius:3px 0px 0px 3px;
}
.share {
clear:left;
left:10px;
top:10px;
width:57px;
height:18px;
font:bold 10px/18px Arial,sans-serif;
text-align:center;
text-transform:uppercase;
background:#333;
background:rgba(32,32,32,0.75);
border-color:#666;
border-color:rgba(128,128,128,0.75);
color:#fff;
}
.zoompan .share { top:45px; }
/* ### Zoombox ### */
.zoombox-box,
.boxselector-box {
border:1px dashed #888;
background:rgba(255,255,255,0.25);
position:absolute;
top:0px; left:0px; width:0px; height:0px;
display:none;
z-index: 10;
}
/* ### Attribution ### */
.wax-attribution {
position:absolute;
background:#fff;
font:normal 10px/20px Arial,sans-serif;
z-index:99999;
text-align:center;
padding:0px 5px;
bottom:0px;
left:0px;
}
.wax-attribution.wax-g {
left:65px;
bottom:4px;
background:transparent;
}
/* ### Share ### */
.ts-error,
.wax-share {
background:#666;
background:rgba(32,32,32,0.75);
position:absolute;
width:100%;
height:100%;
top:0px; left:0px; right:0px; bottom:0px;
z-index:999999;
}
.wax-share div {
right:50%;
top:50%;
margin:-120px -180px 0px 0px;
padding:19px;
width:320px;
height:200px;
overflow:hidden;
}
.wax-share small { color:#999; }
.wax-share textarea {
display:block;
font:normal 10px/15px Arial,sans-serif;
resize:none;
border:1px solid #ccc;
padding:4px;
width:310px;
}
.wax-share .twitter,
.wax-share .facebook {
display:inline-block;
position:relative;
padding:2px 18px;
margin-right:10px;
background:#fff;
color:#fff;
font-weight:bold;
border:2px solid #ccc;
}
.wax-share .twitter {
background:#0ac;
border-color:#4ce;
}
.wax-share .facebook {
background:#359;
border-color:#68c;
}
/* ### Google maps adjustments ### */
.g .share {
position:absolute;
left:5px;
top:5px;
z-index:1000;
}
.g.zoompan .share { left:30px; top:15px; }
/* ### Error message ### */
.ts-error .error-message {
background:#fff;
position:absolute;
right:50%;
top:50%;
margin:-50px -110px 0px 0px;
padding:10px 0px;
height:80px;
width:220px;
color:#999;
text-align:center;
font-weight:bold;
border-radius:5px;
-moz-border-radius:5px;
-webkit-border-radius:5px;
box-shadow:#fff 0px 0px 40px;
-moz-box-shadow:#fff 0px 0px 40px;
-webkit-box-shadow:#fff 0px 0px 40px;
}
.ts-error .mapbox-logo {
display:block;
width:140px;
height:40px;
margin:5px auto;
background:url(/assets/tilestream-pro/images/controls.png) 0px -40px no-repeat;
}
.mapbox-watermark {
position:absolute;
left:5px;
bottom:5px;
z-index:99999;
display:block;
width:65px;
height:20px;
text-indent:-9999px;
overflow:hidden;
background:url(/assets/tilestream-pro/images/controls.png) 0px -90px no-repeat;
}
.attribution .mapbox-watermark { bottom:25px; }
/* Override image location */
.zoomer,
.close,
.mapbox-watermark,
.ts-error .mapbox-logo { background-image:url(img/map.png); }
// Array.indexOf polyfill courtesy of Mozilla MDN:
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
"use strict";
if (this === void 0 || this === null) {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (len === 0) {
return -1;
}
var n = 0;
if (arguments.length > 0) {
n = Number(arguments[1]);
if (n !== n) { // shortcut for verifying if it's NaN
n = 0;
} else if (n !== 0 && n !== Infinity && n !== -Infinity) {
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
}
if (n >= len) {
return -1;
}
var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
for (; k < len; k++) {
if (k in t && t[k] === searchElement) {
return k;
}
}
return -1;
};
}
function mmg() {
var l = {},
// a list of our markers
markers = [],
// the absolute position of the parent element
position = null,
factory = null,
// map bounds
left = null,
right = null;
var parent = document.createElement('div');
parent.style.cssText = 'position: absolute; top: 0px;' +
'left: 0px; width: 100%; height: 100%; margin: 0; padding: 0; z-index: 1';
function defaultFactory(feature) {
var d = document.createElement('div');
d.className = 'mmg-default';
return d;
}
function fLocation (feature) {
// GeoJSON
var geom = feature.geometry;
// coerce the lat and lon values, just in case
var lon = Number(geom.coordinates[0]),
lat = Number(geom.coordinates[1]);
return new MM.Location(lat, lon);
}
// Reposition al markers
function repositionAllMarkers() {
left = l.map.pointLocation(new MM.Point(0, 0));
right = l.map.pointLocation(new MM.Point(l.map.dimensions.x, 0));
for (var i = 0; i < markers.length; i++) {
repositionMarker(markers[i]);
}
}
// reposition a single marker element
function repositionMarker(marker) {
// remember the tile coordinate so we don't have to reproject every time
if (!marker.coord) marker.coord = l.map.locationCoordinate(marker.location);
var pos = l.map.coordinatePoint(marker.coord);
var pos_loc;
if (pos.x < 0) {
pos_loc = new MM.Location(marker.location.lat, marker.location.lon);
pos_loc.lon += Math.ceil((left.lon - marker.location.lon) / 360) * 360;
pos = l.map.locationPoint(pos_loc);
} else if (pos.x > l.map.dimensions.x) {
pos_loc = new MM.Location(marker.location.lat, marker.location.lon);
pos_loc.lon -= Math.ceil((marker.location.lon - right.lon) / 360) * 360;
pos = l.map.locationPoint(pos_loc);
}
if (pos_loc) {
marker.coord = l.map.locationCoordinate(pos_loc);
}
pos.scale = 1;
pos.width = pos.height = 0;
MM.moveElement(marker, pos);
}
/**
* Add an HTML element as a marker, located at the position of the
* provided GeoJSON feature, Location instance (or {lat,lon} object
* literal), or "lat,lon" string.
*/
var first = true;
l.addMarker = function(marker, feature) {
if (!marker || !feature) {
return null;
}
// convert the feature to a Location instance
marker.location = fLocation(feature);
// position: absolute
marker.style.position = 'absolute';
// update the marker's position
if (l.map) repositionMarker(marker);
// append it to the DOM
parent.appendChild(marker);
// add it to the list
markers.push(marker);
return marker;
};
l.geojson = function(x) {
if (!x) return markers;
for (var i = 0; i < x.features.length; i++) {
l.addMarker(factory(x.features[i]), x.features[i]);
}
return this;
};
l.draw = function() {
repositionAllMarkers();
};
/**
* Remove the element marker from the layer and the DOM.
*/
l.removeMarker = function(marker) {
var index = markers.indexOf(marker);
if (index > -1) {
markers.splice(index, 1);
}
if (marker.parentNode == parent) {
parent.removeChild(marker);
}
return marker;
};
// remove all markers
l.removeAllMarkers = function() {
while (markers.length > 0) {
this.removeMarker(markers[0]);
}
};
l.factory = function(x) {
if (!x) return factory;
factory = x;
return this;
};
l.parent = parent;
l.factory(defaultFactory);
return l;
}
/*
* Modest Maps JS v1.1.1
* http://modestmaps.com/
*
* Copyright (c) 2011 Stamen Design, All Rights Reserved.
*
* Open source under the BSD License.
* http://creativecommons.org/licenses/BSD/
*
* Versioned using Semantic Versioning (v.major.minor.patch)
* See CHANGELOG and http://semver.org/ for more details.
*
*/
var previousMM=MM;if(!com){var com={};if(!com.modestmaps){com.modestmaps={}}}var MM=com.modestmaps={noConflict:function(){MM=previousMM;return this}};(function(a){a.extend=function(d,b){for(var c in b.prototype){if(typeof d.prototype[c]=="undefined"){d.prototype[c]=b.prototype[c]}}return d};a.getFrame=function(){return function(b){(window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(c){window.setTimeout(function(){c(+new Date())},10)})(b)}}();a.transformProperty=(function(d){if(!this.document){return}var c=document.documentElement.style;for(var b=0;b<d.length;b++){if(d[b] in c){return d[b]}}return false})(["transformProperty","WebkitTransform","OTransform","MozTransform","msTransform"]);a.matrixString=function(b){if(b.scale*b.width%1){b.scale+=(1-b.scale*b.width%1)/b.width}var c=b.scale||1;if(a._browser.webkit3d){return"translate3d("+b.x.toFixed(0)+"px,"+b.y.toFixed(0)+"px, 0px)scale3d("+c+","+c+", 1)"}else{return"translate("+b.x.toFixed(6)+"px,"+b.y.toFixed(6)+"px)scale("+c+","+c+")"}};a._browser=(function(b){return{webkit:("WebKitCSSMatrix" in b),webkit3d:("WebKitCSSMatrix" in b)&&("m11" in new WebKitCSSMatrix())}})(this);a.moveElement=function(d,b){if(a.transformProperty){if(!b.scale){b.scale=1}if(!b.width){b.width=0}if(!b.height){b.height=0}var c=a.matrixString(b);if(d[a.transformProperty]!==c){d.style[a.transformProperty]=d[a.transformProperty]=c}}else{d.style.left=b.x+"px";d.style.top=b.y+"px";if(b.width&&b.height&&b.scale){d.style.width=Math.ceil(b.width*b.scale)+"px";d.style.height=Math.ceil(b.height*b.scale)+"px"}}};a.cancelEvent=function(b){b.cancelBubble=true;b.cancel=true;b.returnValue=false;if(b.stopPropagation){b.stopPropagation()}if(b.preventDefault){b.preventDefault()}return false};a.coerceLayer=function(b){if(typeof b=="string"){return new a.Layer(new a.TemplatedLayer(b))}else{if("draw" in b&&typeof b.draw=="function"){return b}else{return new a.Layer(b)}}};a.addEvent=function(d,c,b){if(d.addEventListener){d.addEventListener(c,b,false);if(c=="mousewheel"){d.addEventListener("DOMMouseScroll",b,false)}}else{if(d.attachEvent){d["e"+c+b]=b;d[c+b]=function(){d["e"+c+b](window.event)};d.attachEvent("on"+c,d[c+b])}}};a.removeEvent=function(d,c,b){if(d.removeEventListener){d.removeEventListener(c,b,false);if(c=="mousewheel"){d.removeEventListener("DOMMouseScroll",b,false)}}else{if(d.detachEvent){d.detachEvent("on"+c,d[c+b]);d[c+b]=null}}};a.getStyle=function(c,b){if(c.currentStyle){return c.currentStyle[b]}else{if(window.getComputedStyle){return document.defaultView.getComputedStyle(c,null).getPropertyValue(b)}}};a.Point=function(b,c){this.x=parseFloat(b);this.y=parseFloat(c)};a.Point.prototype={x:0,y:0,toString:function(){return"("+this.x.toFixed(3)+", "+this.y.toFixed(3)+")"},copy:function(){return new a.Point(this.x,this.y)}};a.Point.distance=function(c,b){return Math.sqrt(Math.pow(b.x-c.x,2)+Math.pow(b.y-c.y,2))};a.Point.interpolate=function(d,c,b){return new a.Point(d.x+(c.x-d.x)*b,d.y+(c.y-d.y)*b)};a.Coordinate=function(d,b,c){this.row=d;this.column=b;this.zoom=c};a.Coordinate.prototype={row:0,column:0,zoom:0,toString:function(){return"("+this.row.toFixed(3)+", "+this.column.toFixed(3)+" @"+this.zoom.toFixed(3)+")"},toKey:function(){return this.zoom+","+this.row+","+this.column},copy:function(){return new a.Coordinate(this.row,this.column,this.zoom)},container:function(){return new a.Coordinate(Math.floor(this.row),Math.floor(this.column),Math.floor(this.zoom))},zoomTo:function(b){var c=Math.pow(2,b-this.zoom);return new a.Coordinate(this.row*c,this.column*c,b)},zoomBy:function(c){var b=Math.pow(2,c);return new a.Coordinate(this.row*b,this.column*b,this.zoom+c)},up:function(b){if(b===undefined){b=1}return new a.Coordinate(this.row-b,this.column,this.zoom)},right:function(b){if(b===undefined){b=1}return new a.Coordinate(this.row,this.column+b,this.zoom)},down:function(b){if(b===undefined){b=1}return new a.Coordinate(this.row+b,this.column,this.zoom)},left:function(b){if(b===undefined){b=1}return new a.Coordinate(this.row,this.column-b,this.zoom)}};a.Location=function(b,c){this.lat=parseFloat(b);this.lon=parseFloat(c)};a.Location.prototype={lat:0,lon:0,toString:function(){return"("+this.lat.toFixed(3)+", "+this.lon.toFixed(3)+")"},copy:function(){return new a.Location(this.lat,this.lon)}};a.Location.distance=function(i,h,b){if(!b){b=6378000}var o=Math.PI/180,g=i.lat*o,n=i.lon*o,f=h.lat*o,m=h.lon*o,l=Math.cos(g)*Math.cos(n)*Math.cos(f)*Math.cos(m),k=Math.cos(g)*Math.sin(n)*Math.cos(f)*Math.sin(m),j=Math.sin(g)*Math.sin(f);return Math.acos(l+k+j)*b};a.Location.interpolate=function(i,g,m){if(i.lat===g.lat&&i.lon===g.lon){return new a.Location(i.lat,i.lon)}var s=Math.PI/180,k=i.lat*s,n=i.lon*s,j=g.lat*s,l=g.lon*s;var o=2*Math.asin(Math.sqrt(Math.pow(Math.sin((k-j)/2),2)+Math.cos(k)*Math.cos(j)*Math.pow(Math.sin((n-l)/2),2)));var e=Math.sin((1-m)*o)/Math.sin(o);var b=Math.sin(m*o)/Math.sin(o);var r=e*Math.cos(k)*Math.cos(n)+b*Math.cos(j)*Math.cos(l);var q=e*Math.cos(k)*Math.sin(n)+b*Math.cos(j)*Math.sin(l);var p=e*Math.sin(k)+b*Math.sin(j);var c=Math.atan2(p,Math.sqrt(Math.pow(r,2)+Math.pow(q,2)));var h=Math.atan2(q,r);return new a.Location(c/s,h/s)};a.Location.bearing=function(d,c){var b=Math.atan2(Math.sin(lon1-lon2)*Math.cos(lat2),Math.cos(lat1)*Math.sin(lat2)-Math.sin(lat1)*Math.cos(lat2)*Math.cos(lon1-lon2))/-(Math.PI/180);return(b<0)?b+360:b};a.Extent=function(g,c,f,e){if(g instanceof a.Location&&c instanceof a.Location){var d=g,b=c;g=d.lat;c=d.lon;f=b.lat;e=b.lon}if(isNaN(f)){f=g}if(isNaN(e)){e=c}this.north=Math.max(g,f);this.south=Math.min(g,f);this.east=Math.max(e,c);this.west=Math.min(e,c)};a.Extent.prototype={north:0,south:0,east:0,west:0,copy:function(){return new a.Extent(this.north,this.west,this.south,this.east)},toString:function(b){if(isNaN(b)){b=3}return[this.north.toFixed(b),this.west.toFixed(b),this.south.toFixed(b),this.east.toFixed(b)].join(", ")},northWest:function(){return new a.Location(this.north,this.west)},southEast:function(){return new a.Location(this.south,this.east)},northEast:function(){return new a.Location(this.north,this.east)},southWest:function(){return new a.Location(this.south,this.west)},center:function(){return new a.Location(this.south+(this.north-this.south)/2,this.east+(this.west-this.east)/2)},encloseLocation:function(b){if(b.lat>this.north){this.north=b.lat}if(b.lat<this.south){this.south=b.lat}if(b.lon>this.east){this.east=b.lon}if(b.lon<this.west){this.west=b.lon}},encloseLocations:function(c){var b=c.length;for(var d=0;d<b;d++){this.encloseLocation(c[d])}},setFromLocations:function(c){var b=c.length,e=c[0];this.north=this.south=e.lat;this.east=this.west=e.lon;for(var d=1;d<b;d++){this.encloseLocation(c[d])}},encloseExtent:function(b){if(b.north>this.north){this.north=b.north}if(b.south<this.south){this.south=b.south}if(b.east>this.east){this.east=b.east}if(b.west<this.west){this.west=b.west}},containsLocation:function(b){return b.lat>=this.south&&b.lat<=this.north&&b.lon>=this.west&&b.lon<=this.east},toArray:function(){return[this.northWest(),this.southEast()]}};a.Extent.fromString=function(c){var b=c.split(/\s*,\s*/);if(b.length!=4){throw"Invalid extent string (expecting 4 comma-separated numbers)"}return new a.Extent(parseFloat(b[0]),parseFloat(b[1]),parseFloat(b[2]),parseFloat(b[3]))};a.Extent.fromArray=function(b){var c=new a.Extent();c.setFromLocations(b);return c};a.Transformation=function(d,f,b,c,e,g){this.ax=d;this.bx=f;this.cx=b;this.ay=c;this.by=e;this.cy=g};a.Transformation.prototype={ax:0,bx:0,cx:0,ay:0,by:0,cy:0,transform:function(b){return new a.Point(this.ax*b.x+this.bx*b.y+this.cx,this.ay*b.x+this.by*b.y+this.cy)},untransform:function(b){return new a.Point((b.x*this.by-b.y*this.bx-this.cx*this.by+this.cy*this.bx)/(this.ax*this.by-this.ay*this.bx),(b.x*this.ay-b.y*this.ax-this.cx*this.ay+this.cy*this.ax)/(this.bx*this.ay-this.by*this.ax))}};a.deriveTransformation=function(l,k,f,e,b,o,h,g,d,c,n,m){var j=a.linearSolution(l,k,f,b,o,h,d,c,n);var i=a.linearSolution(l,k,e,b,o,g,d,c,m);return new a.Transformation(j[0],j[1],j[2],i[0],i[1],i[2])};a.linearSolution=function(f,o,i,e,n,h,d,m,g){f=parseFloat(f);o=parseFloat(o);i=parseFloat(i);e=parseFloat(e);n=parseFloat(n);h=parseFloat(h);d=parseFloat(d);m=parseFloat(m);g=parseFloat(g);var l=(((h-g)*(o-n))-((i-h)*(n-m)))/(((e-d)*(o-n))-((f-e)*(n-m)));var k=(((h-g)*(f-e))-((i-h)*(e-d)))/(((n-m)*(f-e))-((o-n)*(e-d)));var j=i-(f*l)-(o*k);return[l,k,j]};a.Projection=function(c,b){if(!b){b=new a.Transformation(1,0,0,0,1,0)}this.zoom=c;this.transformation=b};a.Projection.prototype={zoom:0,transformation:null,rawProject:function(b){throw"Abstract method not implemented by subclass."},rawUnproject:function(b){throw"Abstract method not implemented by subclass."},project:function(b){b=this.rawProject(b);if(this.transformation){b=this.transformation.transform(b)}return b},unproject:function(b){if(this.transformation){b=this.transformation.untransform(b)}b=this.rawUnproject(b);return b},locationCoordinate:function(c){var b=new a.Point(Math.PI*c.lon/180,Math.PI*c.lat/180);b=this.project(b);return new a.Coordinate(b.y,b.x,this.zoom)},coordinateLocation:function(c){c=c.zoomTo(this.zoom);var b=new a.Point(c.column,c.row);b=this.unproject(b);return new a.Location(180*b.y/Math.PI,180*b.x/Math.PI)}};a.LinearProjection=function(c,b){a.Projection.call(this,c,b)};a.LinearProjection.prototype={rawProject:function(b){return new a.Point(b.x,b.y)},rawUnproject:function(b){return new a.Point(b.x,b.y)}};a.extend(a.LinearProjection,a.Projection);a.MercatorProjection=function(c,b){a.Projection.call(this,c,b)};a.MercatorProjection.prototype={rawProject:function(b){return new a.Point(b.x,Math.log(Math.tan(0.25*Math.PI+0.5*b.y)))},rawUnproject:function(b){return new a.Point(b.x,2*Math.atan(Math.pow(Math.E,b.y))-0.5*Math.PI)}};a.extend(a.MercatorProjection,a.Projection);a.MapProvider=function(b){if(b){this.getTile=b}};a.MapProvider.prototype={tileLimits:[new a.Coordinate(0,0,0),new a.Coordinate(1,1,0).zoomTo(18)],getTileUrl:function(b){throw"Abstract method not implemented by subclass."},getTile:function(b){throw"Abstract method not implemented by subclass."},releaseTile:function(b){},setZoomRange:function(c,b){this.tileLimits[0]=this.tileLimits[0].zoomTo(c);this.tileLimits[1]=this.tileLimits[1].zoomTo(b)},sourceCoordinate:function(f){var c=this.tileLimits[0].zoomTo(f.zoom),d=this.tileLimits[1].zoomTo(f.zoom),b=Math.pow(2,f.zoom),e;if(f.column<0){e=(f.column+b)%b}else{e=f.column%b}if(f.row<c.row||f.row>=d.row){return null}else{if(e<c.column||e>=d.column){return null}else{return new a.Coordinate(f.row,e,f.zoom)}}}};a.Template=function(e,b){var f=e.match(/{(Q|quadkey)}/);if(f){e=e.replace("{subdomains}","{S}").replace("{zoom}","{Z}").replace("{quadkey}","{Q}")}var d=(b&&b.length&&e.indexOf("{S}")>=0);function c(m,k,l){var j="";for(var h=1;h<=l;h++){j+=(((m>>l-h)&1)<<1)|((k>>l-h)&1)}return j||"0"}var g=function(k){var j=this.sourceCoordinate(k);if(!j){return null}var i=e;if(d){var h=parseInt(j.zoom+j.row+j.column,10)%b.length;i=i.replace("{S}",b[h])}if(f){return i.replace("{Z}",j.zoom.toFixed(0)).replace("{Q}",c(j.row,j.column,j.zoom))}else{return i.replace("{Z}",j.zoom.toFixed(0)).replace("{X}",j.column.toFixed(0)).replace("{Y}",j.row.toFixed(0))}};a.MapProvider.call(this,g)};a.Template.prototype={getTile:function(b){return this.getTileUrl(b)}};a.extend(a.Template,a.MapProvider);a.TemplatedLayer=function(c,b){return new a.Layer(new a.Template(c,b))};a.getMousePoint=function(f,d){var b=new a.Point(f.clientX,f.clientY);b.x+=document.body.scrollLeft+document.documentElement.scrollLeft;b.y+=document.body.scrollTop+document.documentElement.scrollTop;for(var c=d.parent;c;c=c.offsetParent){b.x-=c.offsetLeft;b.y-=c.offsetTop}return b};a.MouseWheelHandler=function(){var d={},g,f,c,b=false;function e(k){var l=0;c=c||new Date().getTime();try{f.scrollTop=1000;f.dispatchEvent(k);l=1000-f.scrollTop}catch(i){l=k.wheelDelta||(-k.detail*5)}var j=new Date().getTime()-c;var h=a.getMousePoint(k,g);if(Math.abs(l)>0&&(j>200)&&!b){g.zoomByAbout(l>0?1:-1,h);c=new Date().getTime()}else{if(b){g.zoomByAbout(l*0.001,h)}}return a.cancelEvent(k)}d.init=function(h){g=h;f=document.body.appendChild(document.createElement("div"));f.style.cssText="visibility:hidden;top:0;height:0;width:0;overflow-y:scroll";var i=f.appendChild(document.createElement("div"));i.style.height="2000px";a.addEvent(g.parent,"mousewheel",e);return d};d.precise=function(h){if(!arguments.length){return b}b=h;return d};d.remove=function(){a.removeEvent(g.parent,"mousewheel",e);f.parentNode.removeChild(f)};return d};a.DoubleClickHandler=function(){var b={},d;function c(g){var f=a.getMousePoint(g,d);d.zoomByAbout(g.shiftKey?-1:1,f);return a.cancelEvent(g)}b.init=function(e){d=e;a.addEvent(d.parent,"dblclick",c);return b};b.remove=function(){a.removeEvent(d.parent,"dblclick",c)};return b};a.DragHandler=function(){var f={},e,g;function c(h){if(h.shiftKey||h.button==2){return}a.addEvent(document,"mouseup",b);a.addEvent(document,"mousemove",d);e=new a.Point(h.clientX,h.clientY);g.parent.style.cursor="move";return a.cancelEvent(h)}function b(h){a.removeEvent(document,"mouseup",b);a.removeEvent(document,"mousemove",d);e=null;g.parent.style.cursor="";return a.cancelEvent(h)}function d(h){if(e){g.panBy(h.clientX-e.x,h.clientY-e.y);e.x=h.clientX;e.y=h.clientY;e.t=+new Date()}return a.cancelEvent(h)}f.init=function(h){g=h;a.addEvent(g.parent,"mousedown",c);return f};f.remove=function(){a.removeEvent(g.parent,"mousedown",c)};return f};a.MouseHandler=function(){var c={},d,b;c.init=function(e){d=e;b=[a.DragHandler().init(d),a.DoubleClickHandler().init(d),a.MouseWheelHandler().init(d)];return c};c.remove=function(){for(var e=0;e<b.length;e++){b[e].remove()}return c};return c};a.TouchHandler=function(){var c={},v,q=250,l=30,b=350,u={},o=[],n=true,s=false,i=null;function m(){var x=document.createElement("div");x.setAttribute("ongesturestart","return;");return(typeof x.ongesturestart==="function")}function h(A){for(var z=0;z<A.touches.length;z+=1){var y=A.touches[z];if(y.identifier in u){var x=u[y.identifier];x.x=y.screenX;x.y=y.screenY;x.scale=A.scale}else{u[y.identifier]={scale:A.scale,startPos:{x:y.screenX,y:y.screenY},x:y.screenX,y:y.screenY,time:new Date().getTime()}}}}function e(x,y){return(x&&x.touch)&&(y.identifier==x.touch.identifier)}function d(x){h(x);return a.cancelEvent(x)}function r(x){switch(x.touches.length){case 1:k(x.touches[0]);break;case 2:t(x);break}h(x);return a.cancelEvent(x)}function f(E){var y=new Date().getTime();if(E.touches.length===0&&s){j(i)}for(var C=0;C<E.changedTouches.length;C+=1){var H=E.changedTouches[C],D=u[H.identifier];if(!D||D.wasPinch){continue}var G={x:H.screenX,y:H.screenY},A=y-D.time,z=a.Point.distance(G,D.startPos);if(z>l){}else{if(A>q){G.end=y;G.duration=A;g(G)}else{G.time=y;w(G)}}}var F={};for(var B=0;B<E.touches.length;B++){F[E.touches[B].identifier]=true}for(var x in u){if(!(x in F)){delete F[x]}}return a.cancelEvent(E)}function g(x){}function w(x){if(o.length&&(x.time-o[0].time)<b){p(x);o=[];return}o=[x]}function p(y){var B=v.getZoom(),C=Math.round(B)+1,x=C-B;var A=new a.Point(y.x,y.y);v.zoomByAbout(x,A)}function k(z){var y={x:z.screenX,y:z.screenY},x=u[z.identifier];v.panBy(y.x-x.x,y.y-x.y)}function t(D){var C=D.touches[0],B=D.touches[1],F=new a.Point(C.screenX,C.screenY),E=new a.Point(B.screenX,B.screenY),z=u[C.identifier],y=u[B.identifier];z.wasPinch=true;y.wasPinch=true;var x=a.Point.interpolate(F,E,0.5);v.zoomByAbout(Math.log(D.scale)/Math.LN2-Math.log(z.scale)/Math.LN2,x);var A=a.Point.interpolate(z,y,0.5);v.panBy(x.x-A.x,x.y-A.y);s=true;i=x}function j(x){if(n){var y=v.getZoom(),A=Math.round(y);v.zoomByAbout(A-y,x)}s=false}c.init=function(y){v=y;if(!m()){return c}a.addEvent(v.parent,"touchstart",d);a.addEvent(v.parent,"touchmove",r);a.addEvent(v.parent,"touchend",f);return c};c.remove=function(){if(!m()){return c}a.removeEvent(v.parent,"touchstart",d);a.removeEvent(v.parent,"touchmove",r);a.removeEvent(v.parent,"touchend",f);return c};return c};a.CallbackManager=function(b,d){this.owner=b;this.callbacks={};for(var c=0;c<d.length;c++){this.callbacks[d[c]]=[]}};a.CallbackManager.prototype={owner:null,callbacks:null,addCallback:function(b,c){if(typeof(c)=="function"&&this.callbacks[b]){this.callbacks[b].push(c)}},removeCallback:function(e,f){if(typeof(f)=="function"&&this.callbacks[e]){var c=this.callbacks[e],b=c.length;for(var d=0;d<b;d++){if(c[d]===f){c.splice(d,1);break}}}},dispatchCallback:function(d,c){if(this.callbacks[d]){for(var b=0;b<this.callbacks[d].length;b+=1){try{this.callbacks[d][b](this.owner,c)}catch(f){}}}}};a.RequestManager=function(){this.loadingBay=document.createDocumentFragment();this.requestsById={};this.openRequestCount=0;this.maxOpenRequests=4;this.requestQueue=[];this.callbackManager=new a.CallbackManager(this,["requestcomplete","requesterror"])};a.RequestManager.prototype={loadingBay:null,requestsById:null,requestQueue:null,openRequestCount:null,maxOpenRequests:null,callbackManager:null,addCallback:function(b,c){this.callbackManager.addCallback(b,c)},removeCallback:function(b,c){this.callbackManager.removeCallback(b,c)},dispatchCallback:function(c,b){this.callbackManager.dispatchCallback(c,b)},clear:function(){this.clearExcept({})},clearRequest:function(d){if(d in this.requestsById){delete this.requestsById[d]}for(var b=0;b<this.requestQueue.length;b++){var c=this.requestQueue[b];if(c&&c.id==d){this.requestQueue[b]=null}}},clearExcept:function(f){for(var e=0;e<this.requestQueue.length;e++){var g=this.requestQueue[e];if(g&&!(g.id in f)){this.requestQueue[e]=null}}var b=this.loadingBay.childNodes;for(var d=b.length-1;d>=0;d--){var c=b[d];if(!(c.id in f)){this.loadingBay.removeChild(c);this.openRequestCount--;c.src=c.coord=c.onload=c.onerror=null}}for(var k in this.requestsById){if(!(k in f)){if(this.requestsById.hasOwnProperty(k)){var h=this.requestsById[k];delete this.requestsById[k];if(h!==null){h=h.id=h.coord=h.url=null}}}}},hasRequest:function(b){return(b in this.requestsById)},requestTile:function(e,d,b){if(!(e in this.requestsById)){var c={id:e,coord:d.copy(),url:b};this.requestsById[e]=c;if(b){this.requestQueue.push(c)}}},getProcessQueue:function(){if(!this._processQueue){var b=this;this._processQueue=function(){b.processQueue()}}return this._processQueue},processQueue:function(d){if(d&&this.requestQueue.length>8){this.requestQueue.sort(d)}while(this.openRequestCount<this.maxOpenRequests&&this.requestQueue.length>0){var c=this.requestQueue.pop();if(c){this.openRequestCount++;var b=document.createElement("img");b.id=c.id;b.style.position="absolute";b.coord=c.coord;this.loadingBay.appendChild(b);b.onload=b.onerror=this.getLoadComplete();b.src=c.url;c=c.id=c.coord=c.url=null}}},_loadComplete:null,getLoadComplete:function(){if(!this._loadComplete){var b=this;this._loadComplete=function(d){d=d||window.event;var c=d.srcElement||d.target;c.onload=c.onerror=null;b.loadingBay.removeChild(c);b.openRequestCount--;delete b.requestsById[c.id];if(d.type==="load"&&(c.complete||(c.readyState&&c.readyState=="complete"))){b.dispatchCallback("requestcomplete",c)}else{b.dispatchCallback("requesterror",c.src);c.src=null}setTimeout(b.getProcessQueue(),0)}}return this._loadComplete}};a.Layer=function(c,b){this.parent=b||document.createElement("div");this.parent.style.cssText="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; margin: 0; padding: 0; z-index: 0";this.levels={};this.requestManager=new a.RequestManager();this.requestManager.addCallback("requestcomplete",this.getTileComplete());if(c){this.setProvider(c)}};a.Layer.prototype={map:null,parent:null,tiles:null,levels:null,requestManager:null,provider:null,_tileComplete:null,getTileComplete:function(){if(!this._tileComplete){var b=this;this._tileComplete=function(c,d){b.tiles[d.id]=d;b.positionTile(d)}}return this._tileComplete},draw:function(){var p=this.map.coordinate.zoomTo(Math.round(this.map.coordinate.zoom));function f(t,s){if(t&&s){var v=t.coord;var u=s.coord;if(v.zoom==u.zoom){var r=Math.abs(p.row-v.row-0.5)+Math.abs(p.column-v.column-0.5);var w=Math.abs(p.row-u.row-0.5)+Math.abs(p.column-u.column-0.5);return r<w?1:r>w?-1:0}else{return v.zoom<u.zoom?1:v.zoom>u.zoom?-1:0}}return t?1:s?-1:0}var o=Math.round(this.map.coordinate.zoom);var n=this.map.pointCoordinate(new a.Point(0,0)).zoomTo(o).container();var i=this.map.pointCoordinate(this.map.dimensions).zoomTo(o).container().right().down();var k={};var m=this.createOrGetLevel(n.zoom);var h=n.copy();for(h.column=n.column;h.column<=i.column;h.column++){for(h.row=n.row;h.row<=i.row;h.row++){var c=this.inventoryVisibleTile(m,h);while(c.length){k[c.pop()]=true}}}for(var e in this.levels){if(this.levels.hasOwnProperty(e)){var q=parseInt(e,10);if(q>=n.zoom-5&&q<n.zoom+2){continue}var d=this.levels[e];d.style.display="none";var g=this.tileElementsInLevel(d);while(g.length){this.provider.releaseTile(g[0].coord);this.requestManager.clearRequest(g[0].coord.toKey());d.removeChild(g[0]);g.shift()}}}var b=n.zoom-5;var l=n.zoom+2;for(var j=b;j<l;j++){this.adjustVisibleLevel(this.levels[j],j,k)}this.requestManager.clearExcept(k);this.requestManager.processQueue(f)},inventoryVisibleTile:function(m,c){var g=c.toKey(),d=[g];if(g in this.tiles){var f=this.tiles[g];if(f.parentNode!=m){m.appendChild(f);if("reAddTile" in this.provider){this.provider.reAddTile(g,c,f)}}return d}if(!this.requestManager.hasRequest(g)){var l=this.provider.getTile(c);if(typeof l=="string"){this.addTileImage(g,c,l)}else{if(l){this.addTileElement(g,c,l)}}}var e=false;var j=c.zoom;for(var h=1;h<=j;h++){var b=c.zoomBy(-h).container();var k=b.toKey();if(k in this.tiles){d.push(k);e=true;break}}if(!e){var i=c.zoomBy(1);d.push(i.toKey());i.column+=1;d.push(i.toKey());i.row+=1;d.push(i.toKey());i.column-=1;d.push(i.toKey())}return d},tileElementsInLevel:function(d){var b=[];for(var c=d.firstChild;c;c=c.nextSibling){if(c.nodeType==1){b.push(c)}}return b},adjustVisibleLevel:function(c,k,d){if(!c){return}var e=1;var j=this.map.coordinate.copy();if(c.childNodes.length>0){c.style.display="block";e=Math.pow(2,this.map.coordinate.zoom-k);j=j.zoomTo(k)}else{c.style.display="none";return false}var h=this.map.tileSize.x*e;var f=this.map.tileSize.y*e;var b=new a.Point(this.map.dimensions.x/2,this.map.dimensions.y/2);var i=this.tileElementsInLevel(c);while(i.length){var g=i.pop();if(!d[g.id]){this.provider.releaseTile(g.coord);this.requestManager.clearRequest(g.coord.toKey());c.removeChild(g)}else{a.moveElement(g,{x:Math.round(b.x+(g.coord.column-j.column)*h),y:Math.round(b.y+(g.coord.row-j.row)*f),scale:e,width:this.map.tileSize.x,height:this.map.tileSize.y})}}},createOrGetLevel:function(b){if(b in this.levels){return this.levels[b]}var c=document.createElement("div");c.id=this.parent.id+"-zoom-"+b;c.style.cssText=this.parent.style.cssText;c.style.zIndex=b;this.parent.appendChild(c);this.levels[b]=c;return c},addTileImage:function(c,d,b){this.requestManager.requestTile(c,d,b)},addTileElement:function(c,d,b){b.id=c;b.coord=d.copy();this.positionTile(b)},positionTile:function(d){var c=this.map.coordinate.zoomTo(d.coord.zoom);d.style.cssText="position:absolute;-webkit-user-select:none;-webkit-user-drag:none;-moz-user-drag:none;-webkit-transform-origin:0 0;-moz-transform-origin:0 0;-o-transform-origin:0 0;-ms-transform-origin:0 0;";d.ondragstart=function(){return false};var e=Math.pow(2,this.map.coordinate.zoom-d.coord.zoom);a.moveElement(d,{x:Math.round((this.map.dimensions.x/2)+(d.coord.column-c.column)*this.map.tileSize.x),y:Math.round((this.map.dimensions.y/2)+(d.coord.row-c.row)*this.map.tileSize.y),scale:e,width:this.map.tileSize.x,height:this.map.tileSize.y});var b=this.levels[d.coord.zoom];b.appendChild(d);d.className="map-tile-loaded";if(Math.round(this.map.coordinate.zoom)==d.coord.zoom){b.style.display="block"}this.requestRedraw()},_redrawTimer:undefined,requestRedraw:function(){if(!this._redrawTimer){this._redrawTimer=setTimeout(this.getRedraw(),1000)}},_redraw:null,getRedraw:function(){if(!this._redraw){var b=this;this._redraw=function(){b.draw();b._redrawTimer=0}}return this._redraw},setProvider:function(c){var d=(this.provider===null);if(!d){this.requestManager.clear();for(var b in this.levels){if(this.levels.hasOwnProperty(b)){var e=this.levels[b];while(e.firstChild){this.provider.releaseTile(e.firstChild.coord);e.removeChild(e.firstChild)}}}}this.tiles={};this.provider=c;if(!d){this.draw()}},destroy:function(){this.requestManager.clear();this.requestManager.removeCallback("requestcomplete",this.getTileComplete());this.provider=null;if(this.parent.parentNode){this.parent.parentNode.removeChild(this.parent)}this.map=null}};a.Map=function(f,e,g,h){if(typeof f=="string"){f=document.getElementById(f);if(!f){throw"The ID provided to modest maps could not be found."}}this.parent=f;this.parent.style.padding="0";this.parent.style.overflow="hidden";var b=a.getStyle(this.parent,"position");if(b!="relative"&&b!="absolute"){this.parent.style.position="relative"}this.layers=[];if(!(e instanceof Array)){e=[e]}for(var d=0;d<e.length;d++){this.addLayer(e[d])}this.projection=new a.MercatorProjection(0,a.deriveTransformation(-Math.PI,Math.PI,0,0,Math.PI,Math.PI,1,0,-Math.PI,-Math.PI,0,1));this.tileSize=new a.Point(256,256);this.coordLimits=[new a.Coordinate(0,-Infinity,0),new a.Coordinate(1,Infinity,0).zoomTo(18)];this.coordinate=new a.Coordinate(0.5,0.5,0);if(!g){g=new a.Point(this.parent.offsetWidth,this.parent.offsetHeight);this.autoSize=true;a.addEvent(window,"resize",this.windowResize())}else{this.autoSize=false;this.parent.style.width=Math.round(g.x)+"px";this.parent.style.height=Math.round(g.y)+"px"}this.dimensions=g;this.callbackManager=new a.CallbackManager(this,["zoomed","panned","centered","extentset","resized","drawn"]);if(h===undefined){this.eventHandlers=[a.MouseHandler().init(this),a.TouchHandler().init(this)]}else{this.eventHandlers=h;if(h instanceof Array){for(var c=0;c<h.length;c++){h[c].init(this)}}}};a.Map.prototype={parent:null,dimensions:null,projection:null,coordinate:null,tileSize:null,coordLimits:null,layers:null,callbackManager:null,eventHandlers:null,autoSize:null,toString:function(){return"Map(#"+this.parent.id+")"},addCallback:function(b,c){this.callbackManager.addCallback(b,c);return this},removeCallback:function(b,c){this.callbackManager.removeCallback(b,c);return this},dispatchCallback:function(c,b){this.callbackManager.dispatchCallback(c,b);return this},windowResize:function(){if(!this._windowResize){var b=this;this._windowResize=function(c){b.dimensions=new a.Point(b.parent.offsetWidth,b.parent.offsetHeight);b.draw();b.dispatchCallback("resized",[b.dimensions])}}return this._windowResize},setZoomRange:function(c,b){this.coordLimits[0]=this.coordLimits[0].zoomTo(c);this.coordLimits[1]=this.coordLimits[1].zoomTo(b)},zoomBy:function(b){this.coordinate=this.enforceLimits(this.coordinate.zoomBy(b));a.getFrame(this.getRedraw());this.dispatchCallback("zoomed",b);return this},zoomIn:function(){return this.zoomBy(1)},zoomOut:function(){return this.zoomBy(-1)},setZoom:function(b){return this.zoomBy(b-this.coordinate.zoom)},zoomByAbout:function(c,b){var e=this.pointLocation(b);this.coordinate=this.enforceLimits(this.coordinate.zoomBy(c));var d=this.locationPoint(e);this.dispatchCallback("zoomed",c);return this.panBy(b.x-d.x,b.y-d.y)},panBy:function(c,b){this.coordinate.column-=c/this.tileSize.x;this.coordinate.row-=b/this.tileSize.y;this.coordinate=this.enforceLimits(this.coordinate);a.getFrame(this.getRedraw());this.dispatchCallback("panned",[c,b]);return this},panLeft:function(){return this.panBy(100,0)},panRight:function(){return this.panBy(-100,0)},panDown:function(){return this.panBy(0,-100)},panUp:function(){return this.panBy(0,100)},setCenter:function(b){return this.setCenterZoom(b,this.coordinate.zoom)},setCenterZoom:function(b,c){this.coordinate=this.projection.locationCoordinate(b).zoomTo(parseFloat(c)||0);a.getFrame(this.getRedraw());this.dispatchCallback("centered",[b,c]);return this},extentCoordinate:function(p,q){if(p instanceof a.Extent){p=p.toArray()}var t,j;for(var k=0;k<p.length;k++){var l=this.projection.locationCoordinate(p[k]);if(t){t.row=Math.min(t.row,l.row);t.column=Math.min(t.column,l.column);t.zoom=Math.min(t.zoom,l.zoom);j.row=Math.max(j.row,l.row);j.column=Math.max(j.column,l.column);j.zoom=Math.max(j.zoom,l.zoom)}else{t=l.copy();j=l.copy()}}var h=this.dimensions.x+1;var g=this.dimensions.y+1;var m=(j.column-t.column)/(h/this.tileSize.x);var r=Math.log(m)/Math.log(2);var n=t.zoom-(q?r:Math.ceil(r));var o=(j.row-t.row)/(g/this.tileSize.y);var d=Math.log(o)/Math.log(2);var e=t.zoom-(q?d:Math.ceil(d));var b=Math.min(n,e);b=Math.min(b,this.coordLimits[1].zoom);b=Math.max(b,this.coordLimits[0].zoom);var c=(t.row+j.row)/2;var s=(t.column+j.column)/2;var f=t.zoom;return new a.Coordinate(c,s,f).zoomTo(b)},setExtent:function(b,c){this.coordinate=this.extentCoordinate(b,c);this.draw();this.dispatchCallback("extentset",b);return this},setSize:function(b){this.dimensions=new a.Point(b.x,b.y);this.parent.style.width=Math.round(this.dimensions.x)+"px";this.parent.style.height=Math.round(this.dimensions.y)+"px";if(this.autoSize){a.removeEvent(window,"resize",this.windowResize());this.autoSize=false}this.draw();this.dispatchCallback("resized",this.dimensions);return this},coordinatePoint:function(c){if(c.zoom!=this.coordinate.zoom){c=c.zoomTo(this.coordinate.zoom)}var b=new a.Point(this.dimensions.x/2,this.dimensions.y/2);b.x+=this.tileSize.x*(c.column-this.coordinate.column);b.y+=this.tileSize.y*(c.row-this.coordinate.row);return b},pointCoordinate:function(b){var c=this.coordinate.copy();c.column+=(b.x-this.dimensions.x/2)/this.tileSize.x;c.row+=(b.y-this.dimensions.y/2)/this.tileSize.y;return c},locationCoordinate:function(b){return this.projection.locationCoordinate(b)},coordinateLocation:function(b){return this.projection.coordinateLocation(b)},locationPoint:function(b){return this.coordinatePoint(this.locationCoordinate(b))},pointLocation:function(b){return this.coordinateLocation(this.pointCoordinate(b))},getExtent:function(){return new a.Extent(this.pointLocation(new a.Point(0,0)),this.pointLocation(this.dimensions))},extent:function(b,c){if(b){return this.setExtent(b,c)}else{return this.getExtent()}},getCenter:function(){return this.projection.coordinateLocation(this.coordinate)},center:function(b){if(b){return this.setCenter(b)}else{return this.getCenter()}},getZoom:function(){return this.coordinate.zoom},zoom:function(b){if(b!==undefined){return this.setZoom(b)}else{return this.getZoom()}},getLayers:function(){return this.layers.slice()},getLayerAt:function(b){return this.layers[b]},addLayer:function(b){this.layers.push(b);this.parent.appendChild(b.parent);b.map=this;return this},removeLayer:function(c){for(var b=0;b<this.layers.length;b++){if(c==this.layers[b]){this.removeLayerAt(b);break}}return this},setLayerAt:function(c,d){if(c<0||c>=this.layers.length){throw new Error("invalid index in setLayerAt(): "+c)}if(this.layers[c]!=d){if(c<this.layers.length){var b=this.layers[c];this.parent.insertBefore(d.parent,b.parent);b.destroy()}else{this.parent.appendChild(d.parent)}this.layers[c]=d;d.map=this;a.getFrame(this.getRedraw())}return this},insertLayerAt:function(c,d){if(c<0||c>this.layers.length){throw new Error("invalid index in insertLayerAt(): "+c)}if(c==this.layers.length){this.layers.push(d);this.parent.appendChild(d.parent)}else{var b=this.layers[c];this.parent.insertBefore(d.parent,b.parent);this.layers.splice(c,0,d)}d.map=this;a.getFrame(this.getRedraw());return this},removeLayerAt:function(c){if(c<0||c>=this.layers.length){throw new Error("invalid index in removeLayer(): "+c)}var b=this.layers[c];this.layers.splice(c,1);b.destroy();return this},swapLayersAt:function(c,b){if(c<0||c>=this.layers.length||b<0||b>=this.layers.length){throw new Error("invalid index in swapLayersAt(): "+index)}var f=this.layers[c],d=this.layers[b],e=document.createElement("div");this.parent.replaceChild(e,d.parent);this.parent.replaceChild(d.parent,f.parent);this.parent.replaceChild(f.parent,e);this.layers[c]=d;this.layers[b]=f;return this},enforceZoomLimits:function(e){var c=this.coordLimits;if(c){var d=c[0].zoom;var b=c[1].zoom;if(e.zoom<d){e=e.zoomTo(d)}else{if(e.zoom>b){e=e.zoomTo(b)}}}return e},enforcePanLimits:function(f){if(this.coordLimits){f=f.copy();var d=this.coordLimits[0].zoomTo(f.zoom);var b=this.coordLimits[1].zoomTo(f.zoom);var c=this.pointCoordinate(new a.Point(0,0)).zoomTo(f.zoom);var e=this.pointCoordinate(this.dimensions).zoomTo(f.zoom);if(b.row-d.row<e.row-c.row){f.row=(b.row+d.row)/2}else{if(c.row<d.row){f.row+=d.row-c.row}else{if(e.row>b.row){f.row-=e.row-b.row}}}if(b.column-d.column<e.column-c.column){f.column=(b.column+d.column)/2}else{if(c.column<d.column){f.column+=d.column-c.column}else{if(e.column>b.column){f.column-=e.column-b.column}}}}return f},enforceLimits:function(b){return this.enforcePanLimits(this.enforceZoomLimits(b))},draw:function(){this.coordinate=this.enforceLimits(this.coordinate);if(this.dimensions.x<=0||this.dimensions.y<=0){if(this.autoSize){var b=this.parent.offsetWidth,d=this.parent.offsetHeight;this.dimensions=new a.Point(b,d);if(b<=0||d<=0){return}}else{return}}for(var c=0;c<this.layers.length;c++){this.layers[c].draw()}this.dispatchCallback("drawn")},_redrawTimer:undefined,requestRedraw:function(){if(!this._redrawTimer){this._redrawTimer=setTimeout(this.getRedraw(),1000)}},_redraw:null,getRedraw:function(){if(!this._redraw){var b=this;this._redraw=function(){b.draw();b._redrawTimer=0}}return this._redraw},destroy:function(){for(var b=0;b<this.layers.length;b++){this.layers[b].destroy()}this.layers=[];this.projection=null;for(var c=0;c<this.eventHandlers.length;c++){this.eventHandlers[c].remove()}if(this.autoSize){a.removeEvent(window,"resize",this.windowResize())}}};a.mapByCenterZoom=function(d,f,b,e){var c=a.coerceLayer(f),g=new a.Map(d,c,false);g.setCenterZoom(b,e).draw();return g};a.mapByExtent=function(d,f,e,c){var b=a.coerceLayer(f),g=new a.Map(d,b,false);g.setExtent([e,c]).draw();return g};if(typeof module!=="undefined"&&module.exports){module.exports={Point:a.Point,Projection:a.Projection,MercatorProjection:a.MercatorProjection,LinearProjection:a.LinearProjection,Transformation:a.Transformation,Location:a.Location,MapProvider:a.MapProvider,Template:a.Template,Coordinate:a.Coordinate,deriveTransformation:a.deriveTransformation}}})(MM);
(function(root) {
var Map = {},
layers;
Map = function(el, l, callback) {
wax.tilejson(l.api, function(t) {
var handlers = [
easey.DragHandler(),
easey.DoubleClickHandler(),
easey.TouchHandler()
];
if ($.inArray('zoomwheel', l.features) >= 0) {
handlers.push(easey.MouseWheelHandler());
}
if ($.inArray('static', l.features) >= 0) {
handlers = null;
}
MM_map = new MM.Map(el, new wax.mm.connector(t), null, handlers);
MM_map.setCenterZoom({
lat: (l.center) ? l.center.lat : t.center[1],
lon: (l.center) ? l.center.lon : t.center[0]
}, (l.center) ? l.center.zoom : t.center[2]);
if (l.zoomRange) {
MM_map.setZoomRange(l.zoomRange[0], l.zoomRange[1]);
} else {
MM_map.setZoomRange(t.minzoom, t.maxzoom);
}
wax.mm.attribution(MM_map, t).appendTo(MM_map.parent);
for (var i = 0; i < l.features.length; i++) {
switch(l.features[i]) {
case 'zoompan':
wax.mm.zoomer(MM_map).appendTo(MM_map.parent);
break;
case 'zoombox':
wax.mm.zoombox(MM_map);
break;
case 'legend':
MM_map.legend = wax.mm.legend(MM_map, t).appendTo(MM_map.parent);
break;
case 'bwdetect':
wax.mm.bwdetect(MM_map);
break;
case 'share':
wax.mm.share(MM_map, t).appendTo($('body')[0]);
break;
case 'tooltips':
MM_map.interaction = wax.mm.interaction()
.map(MM_map)
.tilejson(t)
.on(wax.tooltip()
.parent(MM_map.parent)
.events()
);
break;
case 'movetips':
MM_map.interaction = wax.mm.interaction()
.map(MM_map)
.tilejson(t)
.on(wax.movetip()
.parent(MM_map.parent)
.events()
);
break;
}
}
Map.parseHash();
if (callback && typeof(callback) == 'function') callback();
});
return Map;
};
Map.layers = function(x) {
if (!arguments.length) return layers;
layers = x;
return Map;
};
Map.layerGroups = [];
Map.setOverlay = function(id) {
if (id) {
if (!layers[id]) throw new Error('overlay with id ' + id + ' not found');
var l = layers[id];
l.group = l.group || 0;
if (l.api) {
Map.layerGroups[l.group] = {
id: id,
api: l.api
};
}
}
if ((l && l.api) || (!l && Map.layerGroups.length > 0)) {
var compositedLayers = function() {
var layerIds = [];
$.each(Map.layerGroups, function(index, layer) {
if (layer && layer.api) {
layerIds.push(layer.api.match(/v\d\/(.*?).jsonp/)[1]);
$('[href="#' + layer.id + '"]').addClass('active');
}
});
return 'http://a.tiles.mapbox.com/v3/' + layerIds.join(',') + '.jsonp';
};
wax.tilejson(compositedLayers(), function(t) {
var level = (l && l.level === 'base') ? 0 : 1;
try {
MM_map.setLayerAt(level, new wax.mm.connector(t));
} catch (e) {
MM_map.insertLayerAt(level, new wax.mm.connector(t));
}
if (MM_map.interaction) MM_map.interaction.map(MM_map).tilejson(t);
if (MM_map.legend) {
MM_map.legend.content(t);
}
});
}
if (l && l.center) {
var lat = l.center.lat || MM_map.getCenter().lat,
lon = l.center.lon || MM_map.getCenter().lon,
zoom = l.center.zoom || MM_map.getZoom();
if (l.center.ease > 0) {
MM_map.easey = easey().map(MM_map)
.to(MM_map.locationCoordinate({ lat: lat, lon: lon })
.zoomTo(zoom)).run(l.center.ease);
} else {
MM_map.setCenterZoom({ lat: lat, lon: lon }, zoom);
}
}
};
Map.removeOverlay = function(id) {
if (!layers[id]) throw new Error('overlay with id ' + id + ' not found');
var l = layers[id];
l.group = l.group || 0;
delete Map.layerGroups[l.group];
if (cleanArray(Map.layerGroups).length > 0) {
Map.setOverlay();
} else {
var level = (l.level === 'base') ? 0 : 1;
MM_map.removeLayerAt(level);
if (MM_map.legend) MM_map.legend.content(' ');
if (MM_map.interaction) MM_map.interaction.remove();
}
};
Map.parseHash = function() {
var pattern = /(?:#([^\?]*))?(?:\?(.*))?$/,
components = window.location.href.match(pattern);
if (components && components[2] === 'embed') {
$('body').removeClass().addClass('embed');
window.location.replace(window.location.href.split('?')[0]);
}
if (components && components[1]) {
var hash = components[1];
if (hash.substr(0, 1) === '/') hash = hash.substring(1);
if (hash.substr(hash.length - 1, 1) === '/') hash = hash.substr(0, hash.length - 1);
ids = decodeURIComponent(hash).split('/');
$.each(ids, function(i, layer) {
if (layer !== '-' && layers[layer]) {
Map.layerGroups[i] = {
id: layer,
api: layers[layer].api
};
}
});
}
if (cleanArray(Map.layerGroups).length > 0) {
Map.setOverlay();
} else {
if (layers) {
$.each(layers, function(key, layer) {
if (layer.initial) Map.setOverlay(key);
});
}
}
};
Map.setHash = function() {
var hash = [];
$.each(Map.layerGroups, function(index, layer) {
var id = (layer && layer.id) ? layer.id : '-';
hash.push(encodeURIComponent(id));
});
var l = window.location,
baseUrl = l.href,
state = (hash.length > 0) ? '#/' + hash.join('/') : '';
if (baseUrl.indexOf('?') >= 0) baseUrl = baseUrl.split('?')[0];
if (baseUrl.indexOf('#') >= 0) baseUrl = baseUrl.split('#')[0];
l.replace(baseUrl + state);
// Update share urls
var webpage = l.href;
var embed = (l.hash) ? l.href + '?embed' : l.href + '#/?embed';
$('.wax-share textarea.embed').val(
'<iframe width="500" height="300" frameBorder="0" src="{embed}"></iframe>'
.replace('{embed}', embed));
$('.wax-share a.twitter').attr('href', 'http://twitter.com/intent/tweet?status='
+ encodeURIComponent(document.title + ' (' + webpage + ')'));
$('.wax-share a.facebook').attr('href', 'https://www.facebook.com/sharer.php?u='
+ encodeURIComponent(webpage) + '&t=' + encodeURIComponent(document.title));
};
root.Map = Map;
})(this);
// Bind the geocoder functionality to any div with the format
//
// <div data-control='geocode' id="search">
// <form class="geocode">
// <input placeholder='Search for an address' type="text">
// <input type='submit' />
// <div id='geocode-error'></div>
// </form>
// </div>
//
function bindGeocoder() {
$('[data-control="geocode"] form').submit(function(e) {
var m = $('[data-control="geocode"]').attr('data-map');
// If this doesn't explicitly name the layer it should affect,
// use the first layer in MB.maps
e.preventDefault();
geocode($('input[type=text]', this).val(), m,
$('[data-control="geocode"]').attr('data-callback')
);
});
var geocode = function(query, m, callback) {
query = encodeURIComponent(query);
$('form.geocode').addClass('loading');
reqwest({
url: 'http://open.mapquestapi.com/nominatim/v1/search?format=json&json_callback=callback&&limit=1&q=' + query,
type: 'jsonp',
jsonpCallback: 'callback',
success: function (r) {
r = r[0];
if (MM_map.geocodeLayer) {
MM_map.geocodeLayer.removeAllMarkers();
}
$('form.geocode').removeClass('loading');
if (r === undefined) {
$('#geocode-error').text('This address cannot be found.').fadeIn('fast');
} else {
$('#geocode-error').hide();
MM_map.setExtent([
{ lat: r.boundingbox[1], lon: r.boundingbox[2] },
{ lat: r.boundingbox[0], lon: r.boundingbox[3] }
]);
if (MM_map.getZoom() === MM_map.coordLimits[1].zoom) {
var point = { 'type': 'FeatureCollection',
'features': [{ 'type': 'Feature',
'geometry': { 'type': 'Point','coordinates': [r.lon, r.lat] },
'properties': {}
}]};
if (MM_map.geocodeLayer) {
MM_map.geocodeLayer.removeAllMarkers();
MM_map.geocodeLayer.geojson(point);
} else {
MM_map.geocodeLayer = mmg()
.geojson(point);
MM_map.addLayer(MM_map.geocodeLayer);
}
MM_map.setCenter({ lat: r.lat, lon: r.lon });
}
if (callback && typeof(callback) == 'string')
executeFunctionByName(callback, window);
}
}
});
var attribution = 'Search by <a href="http://developer.mapquest.com/web/products/open">MapQuest Open</a>';
if ($('.wax-attribution').html().indexOf(attribution) < 0) {
$('.wax-attribution').append(' - ' + attribution);
}
};
}
function cleanArray(actual){
var newArray = new Array();
for(var i = 0; i<actual.length; i++){
if (actual[i]){
newArray.push(actual[i]);
}
}
return newArray;
}
function executeFunctionByName(functionName, context, args) {
var args = Array.prototype.slice.call(arguments).splice(2);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for(var i = 0; i < namespaces.length; i++) {
context = context[namespaces[i]];
}
return context[func].apply(this, args);
}
$(function() {
$('body').on('click.map', '[data-control="layer"]', function(e) {
var $this = $(this),
id = $this.attr('href');
id = id.replace(/.*(?=#[^\s]+$)/, '').slice(1);
var m = $('[data-control="geocode"]').attr('data-map') || 'main';
e.preventDefault();
if($this.hasClass('active')) {
$('[data-control="layer"]').removeClass('active');
window[m].removeOverlay(id);
} else {
$('[data-control="layer"]').removeClass('active');
window[m].setOverlay(id);
}
Map.setHash();
});
bindGeocoder();
});
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License:none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin:0;
padding:0;
border:0;
font-size:100%;
font:inherit;
vertical-align:baseline;
outline-color: #41a900;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display:block;
}
body {
line-height:1;
}
ol, ul {
list-style:none;
}
blockquote, q {
quotes:none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content:'';
content:none;
}
table {
border-collapse:collapse;
border-spacing:0;
}
/* Typography */
body,
input,
textarea {
font:13px/16px helvetica, sans-serif;
-webkit-font-smoothing:antialiased;
color: white;
outline-color: #41a900;
}
pre,
code { font:normal 12px/20px monospace; }
h1, h2, h3, h4, h5, h6 {
font-weight:normal;
}
h1 {
line-height:1.75em;
font-size:1.75em;
}
h2 {
line-height:1.5em;
font-size:1.25em;
}
a {
color:#369;
text-decoration:none;
}
/* Layout */
body > div {
position:relative;
z-index:1;
}
.map {
position:absolute;
top:0;
right:0;
bottom:0;
left:0;
z-index:0;
background: #e8fdda;
}
h1 {
margin-bottom:10px;
}
#content {
position:absolute;
top:0;
right:0;
bottom:0;
width:329px;
background:rgb(0,0,0);
background:rgba(0,0,0, 0.75);
overflow-x:hidden;
overflow-y:auto;
padding:20px;
padding-bottom: 0;
}
.layers a {
display:block;
padding:5px;
margin:5px 0;
background:#eee;
max-width:300px;
}
.layers a:hover, .layers a:focus, .layers a.active {
background:#369;
color:white;
}
p {
margin-bottom:1em;
}
label {
font-weight:700;
}
#about p {
font-size:20px;
line-height:30px;
display:block;
}
#search {
position: absolute;
top: 10px;
left: 379px;
width: 231px;
}
form.geocode input[type=text] {
height:28px;
display:block;
border:1px solid black;
float:left;
background-color: rgb(0,0,0);
background-color: rgba(0,0,0, 0.75);
padding: 0 5px;
border-radius:3px;
-moz-border-radius:3px;
-webkit-border-radius:3px;
}
form.geocode input[type=submit] {
background:url(img/map_rev.png) no-repeat -121px -1px;
text-indent:-9999px;
width:30px;
height:30px;
display:block;
border: black 1px solid;
background-color: rgb(0,0,0);
background-color: rgba(0,0,0, 0.75);
border-radius:3px;
-moz-border-radius:3px;
-webkit-border-radius:3px;
box-shadow:rgba(0,0,0,0.1) 0px 1px 3px;
-moz-box-shadow:rgba(0,0,0,0.1) 0px 1px 3px;
-webkit-box-shadow:rgba(0,0,0,0.1) 0px 1px 3px;
margin:0 0 0 3px;
padding:11px;
float:left;
}
form.geocode input[type=submit]:active {
border-color:black;
background-color: rgb(50,50,50);
background-color: rgba(50,50,50, 0.75);
box-shadow:inset rgba(0,0,0,0.1) 0px 1px 3px;
-moz-box-shadow:inset rgba(0,0,0,0.1) 0px 1px 3px;
-webkit-box-shadow:inset rgba(0,0,0,0.1) 0px 1px 3px;
}
form.geocode.loading input[type=submit] {
background:url(img/ajax-loader_rev.gif) no-repeat 50% 50%;
border-color:black;
background-color: #646464;
box-shadow:inset rgba(0,0,0,0.1) 0px 1px 3px;
-moz-box-shadow:inset rgba(0,0,0,0.1) 0px 1px 3px;
-webkit-box-shadow:inset rgba(0,0,0,0.1) 0px 1px 3px;
}
#geocode-error {
display:none;
position: absolute;
top: 35px;
clear: both;
color: white;
font-size: 11px;
right: 15px;
text-align: right;
background: red;
width: auto;
padding: 5px;
border-radius: 3px;
font-weight: bold;
}
a.zoomer {
top:10px;
background-color:rgb(0,0,0);
background-color:rgba(0,0,0, 0.75);
background-image: url(img/map_rev.png);
border-color: black;
}
.zoomer:active {
border-color:black;
background-color:rgb(50,50,50);
background-color:rgba(50,50,50, 0.75);
box-shadow:inset rgba(0,0,0,0.1) 0px 1px 3px;
-moz-box-shadow:inset rgba(0,0,0,0.1) 0px 1px 3px;
-webkit-box-shadow:inset rgba(0,0,0,0.1) 0px 1px 3px;
}
.wax-attribution {
background: url(img/map_rev.png) no-repeat 0px -90px;
color: #333;
padding-left: 75px;
padding-top: 2px;
}
.wax-attribution a {
color: #333;
text-shadow: 1px 1px 5px silver;
}
.wax-tooltip {
left:auto;
right:330px;
top:60px;
}
.wax-legends {
left:auto;
right:330px;
width:290px;
}
.wax-share h3 {
margin:0px 0px 10px;
font-size:16px;
font-weight:normal;
}
.wax-share strong {
font-weight:700;
}
.wax-share small {
font-size:11px;
color:#999;
display:block;
margin-top:0.5em;
}
.share {
top:95px;
z-index:1000;
}
.mmg-default {
width: 20px;
height: 40px;
background: url(img/map_rev.png) -120px -30px;
left: -10px;
top: -30px;
}
.mmg {
width: 30px;
height: 70px;
top: -35px;
left: -15px;
z-index: 3;
position: absolute;
cursor: pointer;
overflow: hidden;
}
.mmg:hover, .mmg.active {
overflow: visible;
}
.mmg {
background: url(http://a.tiles.mapbox.com/v3/marker/pin-m+fff.png) no-repeat center center;
}
.mmg:after {
background: url(http://a.tiles.mapbox.com/v3/marker/pin-m+41a900.png) no-repeat center center;
content: ' ';
position: absolute;
width: 26px;
height: 66px;
top: -1px;
left: 2px;
background-size: 100%;
}
.mmg .overlay {
width: 148px;
font-size: 12px;
line-height: 18px;
padding: 10px;
border-radius: 3px;
color: #333;
position: absolute;
bottom: 80px;
left: -70px;
visibility: hidden;
opacity: 0;
border: 2px solid #41a900;
background: white;
z-index: 2;
box-shadow: 2px 2px 2px rgba(0,0,0,0.2);
cursor: auto;
}
.mmg.active .overlay {
background: #41a900;
}
.mmg.active .overlay:after {
border-top-color: #41a900;
}
.mmg .location .name {
display: block;
color: #41a900;
font-weight: bold;
font-size: 18px;
line-height: 2;
}
.mmg .foursquare {
float: left;
width: 100%;
}
.mmg .foursquare > div:first-child {
margin: 0 auto;
}
.mmg .foursquare .users, .mmg .foursquare .checkins {
width: 50%;
float: left;
text-align: center;
}
.mmg .foursquare .number, .mmg .foursquare .label {
color: white;
text-align: center;
display: block;
}
.mmg .foursquare .number {
font-size: 26px;
margin: 15px 0 5px 0;
}
.mmg .foursquare, .mmg.active .location {
visibility: hidden;
height: 0;
}
.mmg.active .foursquare, .mmg .location {
visibility: visible;
height: auto;
}
.mmg .overlay:after, .mmg .overlay:before {
top: 100%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.mmg .overlay:after {
border-top-color: #fff;
border-width: 10px;
left: 50%;
margin-left: -10px;
}
.mmg .overlay:before {
border-top-color: #41a900;
border-width: 13px;
left: 50%;
margin-left: -13px;
}
.mmg .user, .mmg .time {
color: #333;
position: absolute;
margin-top: 5px;
font-size: 11px;
}
.mmg .user {
left: 10px;
}
.mmg .time {
right: 10px;
}
.mmg:hover .overlay, .mmg.active .overlay {
visibility: visible;
opacity: 1;
}
.mmg:hover {
z-index: 10;
}
.mmg.active {
z-index: 9;
}
.mmg .cross-street {
display: block;
color: #999;
margin-bottom: 1em;
}
.mmg .city-state {
display: block;
font-size: 0.8em;
}
/* Modes */
/* Left */
.left #header .limiter {
width:480px;
}
.left #content {
left:0;
right:auto;
border-left:none;
}
.left .wax-attribution {
left: 379px;
bottom: 2px;
}
.left a.zoomin {
right:10px;
left: auto;
}
.left a.zoomout {
right:39px;
left: auto;
}
.left .share {
left:330px;
z-index:2;
}
.left .wax-tooltip {
right:10px;
}
.left .wax-legends {
right:10px;
}
/* Hero */
.hero .map {
top:50px;
bottom:auto;
height:400px;
}
.hero #content {
top:450px;
left:0;
right:0;
bottom:auto;
border-left:none;
border-right:none;
border-top:1px solid #ccc;
width:auto;
}
.hero #content .limiter {
width:920px;
margin:0px auto;
position:relative;
}
.hero a.zoomer {
top:10px;
}
.hero .wax-tooltip {
top:10px;
right:10px;
}
.hero .wax-legends {
right:10px;
}
.hero .share {
top:45px;
}
.hero .layers {
height:36px;
}
.hero .layer {
width:200px;
float:left;
margin-right:20px;
text-align:center;
}
/* embed */
.embed .map {
position:absolute;
top:0;
right:0;
bottom:0;
left:0;
background:white;
z-index:1000;
}
.embed #header, .embed #content {
position:absolute;
top:0;
left:0;
z-index:10001;
visibility:hidden;
overflow:hidden;
}
.embed a.zoomer {
top:10px;
}
.embed .wax-tooltip {
top:10px;
right:10px;
}
.embed .wax-legends {
right:10px;
}
.embed .share {
top:45px;
}
.embed .layers {
position:absolute;
top:90px;
left:0;
z-index:1001;
visibility:visible;
}
.embed .layer {
width:100px;
text-align:center;
border:1px solid #ccc;
}
#layout {
z-index:10;
position:absolute;
top:10px;
right:10px;
}
#layout a {
margin-left:10px;
}
/* Animation */
.map-tile-loaded {
-webkit-animation-name:fade-in;
-moz-animation-name:fade-in;
-ms-animation-name:fade-in;
-o-animation-name:fade-in;
-webkit-animation-timing-function:linear;
-moz-animation-timing-function:linear;
-ms-animation-timing-function:linear;
-o-animation-timing-function:linear;
-webkit-animation-duration:0.2s;
-moz-animation-duration:0.2s;
-ms-animation-duration:0.2s;
-o-animation-duration:0.2s;
}
@-webkit-keyframes fade-in { from { opacity:0; } to { opacity:1; } }
@-moz-keyframes fade-in { from { opacity:0; } to { opacity:1; } }
@-ms-keyframes fade-in { from { opacity:0; } to { opacity:1; } }
@-o-keyframes fade-in { from { opacity:0; } to { opacity:1; } }
/* #Content */
#content a {
color: white;
text-decoration: underline;
}
h2 {
margin-bottom: 1em;
}
h3 {
clear: both;
float: left;
}
.venue {
position: relative;
clear: both;
float: left;
left: 35px;
top: -21px;
right: 0;
width: 284px;
padding: 5px;
}
.venue.active {
background: #41a900;
}
#content .location {
position: relative;
left: 0;
width: 177px;
float: left;
}
#content .location em {
font-style: italic;
}
#content .phone {
position: relative;
left: 20px;
float: left;
}
.hidden {
display: none;
}
a#showall {
position: absolute;
top: 15px;
right: 20px;
background: url(img/map_rev.png) no-repeat 86px -2px;
padding: 5px 10px;
background-color: black;
padding-right: 30px;
border-radius: 5px;
text-decoration: none;
}
#no-venues {
font-size: 18px;
line-height: 28px;
font-weight: 100;
padding: 20px;
}
#no-venues strong {
color: #41a900;
font-weight: bold;
}
#fsq-attribution {
position: absolute;
right: 0;
bottom: 5px;
height: 15px;
}
// Underscore.js 1.3.3
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore is freely distributable under the MIT license.
// Portions of Underscore are inspired or borrowed from Prototype,
// Oliver Steele's Functional, and John Resig's Micro-Templating.
// For all details and documentation:
// http://documentcloud.github.com/underscore
(function(){function r(a,c,d){if(a===c)return 0!==a||1/a==1/c;if(null==a||null==c)return a===c;a._chain&&(a=a._wrapped);c._chain&&(c=c._wrapped);if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return!1;switch(e){case "[object String]":return a==""+c;case "[object Number]":return a!=+a?c!=+c:0==a?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==
c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if("object"!=typeof a||"object"!=typeof c)return!1;for(var f=d.length;f--;)if(d[f]==a)return!0;d.push(a);var f=0,g=!0;if("[object Array]"==e){if(f=a.length,g=f==c.length)for(;f--&&(g=f in a==f in c&&r(a[f],c[f],d)););}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return!1;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&r(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,h)&&!f--)break;
g=!f}}d.pop();return g}var s=this,I=s._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,J=k.unshift,l=p.toString,K=p.hasOwnProperty,y=k.forEach,z=k.map,A=k.reduce,B=k.reduceRight,C=k.filter,D=k.every,E=k.some,q=k.indexOf,F=k.lastIndexOf,p=Array.isArray,L=Object.keys,t=Function.prototype.bind,b=function(a){return new m(a)};"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(exports=module.exports=b),exports._=b):s._=b;b.VERSION="1.3.3";var j=b.each=b.forEach=function(a,
c,d){if(a!=null)if(y&&a.forEach===y)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++){if(e in a&&c.call(d,a[e],e,a)===o)break}else for(e in a)if(b.has(a,e)&&c.call(d,a[e],e,a)===o)break};b.map=b.collect=function(a,c,b){var e=[];if(a==null)return e;if(z&&a.map===z)return a.map(c,b);j(a,function(a,g,h){e[e.length]=c.call(b,a,g,h)});if(a.length===+a.length)e.length=a.length;return e};b.reduce=b.foldl=b.inject=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(A&&
a.reduce===A){e&&(c=b.bind(c,e));return f?a.reduce(c,d):a.reduce(c)}j(a,function(a,b,i){if(f)d=c.call(e,d,a,b,i);else{d=a;f=true}});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(B&&a.reduceRight===B){e&&(c=b.bind(c,e));return f?a.reduceRight(c,d):a.reduceRight(c)}var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=function(a,
c,b){var e;G(a,function(a,g,h){if(c.call(b,a,g,h)){e=a;return true}});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(C&&a.filter===C)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(D&&a.every===D)return a.every(c,b);j(a,function(a,g,h){if(!(e=e&&c.call(b,
a,g,h)))return o});return!!e};var G=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(E&&a.some===E)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;if(q&&a.indexOf===q)return a.indexOf(c)!=-1;return b=G(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck=
function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b<e.computed&&
(e={value:a,computed:b})});return e.value};b.shuffle=function(a){var b=[],d;j(a,function(a,f){d=Math.floor(Math.random()*(f+1));b[f]=b[d];b[d]=a});return b};b.sortBy=function(a,c,d){var e=b.isFunction(c)?c:function(a){return a[c]};return b.pluck(b.map(a,function(a,b,c){return{value:a,criteria:e.call(d,a,b,c)}}).sort(function(a,b){var c=a.criteria,d=b.criteria;return c===void 0?1:d===void 0?-1:c<d?-1:c>d?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};
j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?e=g+1:f=g}return e};b.toArray=function(a){return!a?[]:b.isArray(a)||b.isArguments(a)?i.call(a):a.toArray&&b.isFunction(a.toArray)?a.toArray():b.values(a)};b.size=function(a){return b.isArray(a)?a.length:b.keys(a).length};b.first=b.head=b.take=function(a,b,d){return b!=null&&!d?i.call(a,0,b):a[0]};b.initial=function(a,b,d){return i.call(a,
0,a.length-(b==null||d?1:b))};b.last=function(a,b,d){return b!=null&&!d?i.call(a,Math.max(a.length-b,0)):a[a.length-1]};b.rest=b.tail=function(a,b,d){return i.call(a,b==null||d?1:b)};b.compact=function(a){return b.filter(a,function(a){return!!a})};b.flatten=function(a,c){return b.reduce(a,function(a,e){if(b.isArray(e))return a.concat(c?e:b.flatten(e));a[a.length]=e;return a},[])};b.without=function(a){return b.difference(a,i.call(arguments,1))};b.uniq=b.unique=function(a,c,d){var d=d?b.map(a,d):a,
e=[];a.length<3&&(c=true);b.reduce(d,function(d,g,h){if(c?b.last(d)!==g||!d.length:!b.include(d,g)){d.push(g);e.push(a[h])}return d},[]);return e};b.union=function(){return b.uniq(b.flatten(arguments,true))};b.intersection=b.intersect=function(a){var c=i.call(arguments,1);return b.filter(b.uniq(a),function(a){return b.every(c,function(c){return b.indexOf(c,a)>=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1),true);return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=
i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e<c;e++)d[e]=b.pluck(a,""+e);return d};b.indexOf=function(a,c,d){if(a==null)return-1;var e;if(d){d=b.sortedIndex(a,c);return a[d]===c?d:-1}if(q&&a.indexOf===q)return a.indexOf(c);d=0;for(e=a.length;d<e;d++)if(d in a&&a[d]===c)return d;return-1};b.lastIndexOf=function(a,b){if(a==null)return-1;if(F&&a.lastIndexOf===F)return a.lastIndexOf(b);for(var d=a.length;d--;)if(d in a&&a[d]===b)return d;return-1};b.range=function(a,b,d){if(arguments.length<=
1){b=a||0;a=0}for(var d=arguments[2]||1,e=Math.max(Math.ceil((b-a)/d),0),f=0,g=Array(e);f<e;){g[f++]=a;a=a+d}return g};var H=function(){};b.bind=function(a,c){var d,e;if(a.bind===t&&t)return t.apply(a,i.call(arguments,1));if(!b.isFunction(a))throw new TypeError;e=i.call(arguments,2);return d=function(){if(!(this instanceof d))return a.apply(c,e.concat(i.call(arguments)));H.prototype=a.prototype;var b=new H,g=a.apply(b,e.concat(i.call(arguments)));return Object(g)===g?g:b}};b.bindAll=function(a){var c=
i.call(arguments,1);c.length==0&&(c=b.functions(a));j(c,function(c){a[c]=b.bind(a[c],a)});return a};b.memoize=function(a,c){var d={};c||(c=b.identity);return function(){var e=c.apply(this,arguments);return b.has(d,e)?d[e]:d[e]=a.apply(this,arguments)}};b.delay=function(a,b){var d=i.call(arguments,2);return setTimeout(function(){return a.apply(null,d)},b)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(i.call(arguments,1)))};b.throttle=function(a,c){var d,e,f,g,h,i,j=b.debounce(function(){h=
g=false},c);return function(){d=this;e=arguments;f||(f=setTimeout(function(){f=null;h&&a.apply(d,e);j()},c));g?h=true:i=a.apply(d,e);j();g=true;return i}};b.debounce=function(a,b,d){var e;return function(){var f=this,g=arguments;d&&!e&&a.apply(f,g);clearTimeout(e);e=setTimeout(function(){e=null;d||a.apply(f,g)},b)}};b.once=function(a){var b=false,d;return function(){if(b)return d;b=true;return d=a.apply(this,arguments)}};b.wrap=function(a,b){return function(){var d=[a].concat(i.call(arguments,0));
return b.apply(this,d)}};b.compose=function(){var a=arguments;return function(){for(var b=arguments,d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=L||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&
c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.pick=function(a){var c={};j(b.flatten(i.call(arguments,1)),function(b){b in a&&(c[b]=a[b])});return c};b.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return r(a,b,[])};b.isEmpty=
function(a){if(a==null)return true;if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};b.isArguments=function(a){return l.call(a)=="[object Arguments]"};b.isArguments(arguments)||(b.isArguments=function(a){return!(!a||!b.has(a,"callee"))});b.isFunction=function(a){return l.call(a)=="[object Function]"};
b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isFinite=function(a){return b.isNumber(a)&&isFinite(a)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,
b){return K.call(a,b)};b.noConflict=function(){s._=I;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};b.escape=function(a){return(""+a).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;").replace(/\//g,"&#x2F;")};b.result=function(a,c){if(a==null)return null;var d=a[c];return b.isFunction(d)?d.call(a):d};b.mixin=function(a){j(b.functions(a),function(c){M(c,b[c]=a[c])})};var N=0;b.uniqueId=
function(a){var b=N++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var u=/.^/,n={"\\":"\\","'":"'",r:"\r",n:"\n",t:"\t",u2028:"\u2028",u2029:"\u2029"},v;for(v in n)n[n[v]]=v;var O=/\\|'|\r|\n|\t|\u2028|\u2029/g,P=/\\(\\|'|r|n|t|u2028|u2029)/g,w=function(a){return a.replace(P,function(a,b){return n[b]})};b.template=function(a,c,d){d=b.defaults(d||{},b.templateSettings);a="__p+='"+a.replace(O,function(a){return"\\"+n[a]}).replace(d.escape||
u,function(a,b){return"'+\n_.escape("+w(b)+")+\n'"}).replace(d.interpolate||u,function(a,b){return"'+\n("+w(b)+")+\n'"}).replace(d.evaluate||u,function(a,b){return"';\n"+w(b)+"\n;__p+='"})+"';\n";d.variable||(a="with(obj||{}){\n"+a+"}\n");var a="var __p='';var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n"+a+"return __p;\n",e=new Function(d.variable||"obj","_",a);if(c)return e(c,b);c=function(a){return e.call(this,a,b)};c.source="function("+(d.variable||"obj")+"){\n"+a+"}";return c};
b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var x=function(a,c){return c?b(a).chain():a},M=function(a,c){m.prototype[a]=function(){var a=i.call(arguments);J.call(a,this._wrapped);return x(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return x(d,
this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return x(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=true;return this};m.prototype.value=function(){return this._wrapped}}).call(this);
// Override movetips positioning
var wax = wax || {};
wax.movetip = wax.movetip || {};
wax.movetip = function() {
var popped = false,
t = {},
_tooltipOffset,
_contextOffset,
tooltip,
parent;
function moveTooltip(e) {
var eo = wax.u.eventoffset(e);
// faux-positioning
if ((eo.y - _contextOffset.top) <
(_tooltipOffset.height + 5) &&
(_contextOffset.height > _tooltipOffset.height)) {
eo.y += _tooltipOffset.height;
tooltip.className += ' flip-y';
}
tooltip.style.left = eo.x + 'px';
tooltip.style.top = eo.y - _tooltipOffset.height - 5 + 'px';
}
// Get the active tooltip for a layer or create a new one if no tooltip exists.
// Hide any tooltips on layers underneath this one.
function getTooltip(feature) {
var tooltip = document.createElement('div'),
inner = document.createElement('div'),
tip = document.createElement('div');
inner.innerHTML = feature;
inner.className = 'inner';
tip.className = 'tip';
tooltip.className = 'wax-tooltip wax-tooltip-0';
tooltip.appendChild(inner);
tooltip.appendChild(tip);
return tooltip;
}
// Hide a given tooltip.
function hide() {
if (tooltip) {
tooltip.parentNode.removeChild(tooltip);
tooltip = null;
}
}
function on(o) {
var content;
if (popped) return;
if ((o.e.type === 'mousemove' || o.e.type === 'touchend' || !o.e.type)) {
content = o.formatter({ format: 'teaser' }, o.data);
if (!content) return;
hide();
parent.style.cursor = 'pointer';
tooltip = document.body.appendChild(getTooltip(content));
}
if (tooltip) {
_tooltipOffset = wax.u.offset(tooltip);
_contextOffset = wax.u.offset(parent);
moveTooltip(o.e);
}
}
function off() {
parent.style.cursor = 'default';
if (!popped) hide();
}
t.parent = function(x) {
if (!arguments.length) return parent;
parent = x;
return t;
};
t.events = function() {
return {
on: on,
off: off
};
};
return t;
};
// Wax share addon
wax = wax || {};
wax.g = wax.g || {};
wax.mm = wax.mm || {};
wax.g.share =
wax.mm.share = function(map, tilejson) {
tilejson = tilejson || {};
var l = window.location;
tilejson.webpage = l.href;
tilejson.embed = (l.hash) ? l.href + '?embed' : l.href + '#/?embed';
var link = document.createElement('a');
var close = document.createElement('a');
var embed = document.createElement('textarea');
var share = document.createElement('div');
var popup = document.createElement('div');
var elements = [link, close, embed, share, popup];
if (typeof com !== 'undefined') {
var mm = com.modestmaps;
for (var i = 0; i < elements.length; i++) {
mm.addEvent(elements[i], 'mousedown', function(e) { mm.cancelEvent(e); });
mm.addEvent(elements[i], 'dblclick', function(e) { mm.cancelEvent(e); });
}
}
link.innerHTML = 'Share +';
link.href = '#';
link.className = 'share';
link.onclick = link.ontouchstart = function() {
popup.style.display = popup.style.display === 'block' ? 'none' : 'block';
$('body').toggleClass('sharing');
return false;
};
close.innerHTML = 'Close';
close.href = '#';
close.className = 'close';
close.onclick = close.ontouchstart = function() {
popup.style.display = popup.style.display === 'block' ? 'none' : 'block';
$('body').toggleClass('sharing');
return false;
};
embed.className = 'embed';
embed.rows = 4;
embed.setAttribute('readonly', 'readonly');
embed.value = '<iframe width="500" height="300" frameBorder="0" src="{{embed}}"></iframe>'
.replace('{{embed}}', tilejson.embed);
embed.onclick = function() {
embed.focus();
embed.select();
return false;
};
var twitter = 'http://twitter.com/intent/tweet?status='
+ encodeURIComponent(document.title + ' (' + tilejson.webpage + ')');
var facebook = 'https://www.facebook.com/sharer.php?u='
+ encodeURIComponent(tilejson.webpage)
+ '&t=' + encodeURIComponent(document.title);
share.innerHTML = ('<h3>Share this map</h3>'
+ '<p><a class="facebook" target="_blank" href="{{facebook}}">Facebook</a>'
+ '<a class="twitter" target="_blank" href="{{twitter}}">Twitter</a></p>')
.replace('{{twitter}}', twitter)
.replace('{{facebook}}', facebook);
share.innerHTML += '<strong>Get the embed code</strong><br />'
share.innerHTML += '<small>Copy and paste this HTML into your website or blog.</small>';
share.appendChild(embed);
share.appendChild(close);
popup.className = 'wax-share';
popup.style.display = 'none';
popup.appendChild(share);
return {
appendTo: function(elem) {
wax.u.$(elem).appendChild(link);
wax.u.$(elem).appendChild(popup);
return this;
}
};
};
/* wax - 6.0.1 - 1.0.4-557-g1eb9e9e */
!function (name, context, definition) {
if (typeof module !== 'undefined') module.exports = definition(name, context);
else if (typeof define === 'function' && typeof define.amd === 'object') define(definition);
else context[name] = definition(name, context);
}('bean', this, function (name, context) {
var win = window
, old = context[name]
, overOut = /over|out/
, namespaceRegex = /[^\.]*(?=\..*)\.|.*/
, nameRegex = /\..*/
, addEvent = 'addEventListener'
, attachEvent = 'attachEvent'
, removeEvent = 'removeEventListener'
, detachEvent = 'detachEvent'
, doc = document || {}
, root = doc.documentElement || {}
, W3C_MODEL = root[addEvent]
, eventSupport = W3C_MODEL ? addEvent : attachEvent
, slice = Array.prototype.slice
, mouseTypeRegex = /click|mouse(?!(.*wheel|scroll))|menu|drag|drop/i
, mouseWheelTypeRegex = /mouse.*(wheel|scroll)/i
, textTypeRegex = /^text/i
, touchTypeRegex = /^touch|^gesture/i
, ONE = { one: 1 } // singleton for quick matching making add() do one()
, nativeEvents = (function (hash, events, i) {
for (i = 0; i < events.length; i++)
hash[events[i]] = 1
return hash
})({}, (
'click dblclick mouseup mousedown contextmenu ' + // mouse buttons
'mousewheel mousemultiwheel DOMMouseScroll ' + // mouse wheel
'mouseover mouseout mousemove selectstart selectend ' + // mouse movement
'keydown keypress keyup ' + // keyboard
'orientationchange ' + // mobile
'focus blur change reset select submit ' + // form elements
'load unload beforeunload resize move DOMContentLoaded readystatechange ' + // window
'error abort scroll ' + // misc
(W3C_MODEL ? // element.fireEvent('onXYZ'... is not forgiving if we try to fire an event
// that doesn't actually exist, so make sure we only do these on newer browsers
'show ' + // mouse buttons
'input invalid ' + // form elements
'touchstart touchmove touchend touchcancel ' + // touch
'gesturestart gesturechange gestureend ' + // gesture
'message readystatechange pageshow pagehide popstate ' + // window
'hashchange offline online ' + // window
'afterprint beforeprint ' + // printing
'dragstart dragenter dragover dragleave drag drop dragend ' + // dnd
'loadstart progress suspend emptied stalled loadmetadata ' + // media
'loadeddata canplay canplaythrough playing waiting seeking ' + // media
'seeked ended durationchange timeupdate play pause ratechange ' + // media
'volumechange cuechange ' + // media
'checking noupdate downloading cached updateready obsolete ' + // appcache
'' : '')
).split(' ')
)
, customEvents = (function () {
function isDescendant(parent, node) {
while ((node = node.parentNode) !== null) {
if (node === parent) return true
}
return false
}
function check(event) {
var related = event.relatedTarget
if (!related) return related === null
return (related !== this && related.prefix !== 'xul' && !/document/.test(this.toString()) && !isDescendant(this, related))
}
return {
mouseenter: { base: 'mouseover', condition: check }
, mouseleave: { base: 'mouseout', condition: check }
, mousewheel: { base: /Firefox/.test(navigator.userAgent) ? 'DOMMouseScroll' : 'mousewheel' }
}
})()
, fixEvent = (function () {
var commonProps = 'altKey attrChange attrName bubbles cancelable ctrlKey currentTarget detail eventPhase getModifierState isTrusted metaKey relatedNode relatedTarget shiftKey srcElement target timeStamp type view which'.split(' ')
, mouseProps = commonProps.concat('button buttons clientX clientY dataTransfer fromElement offsetX offsetY pageX pageY screenX screenY toElement'.split(' '))
, mouseWheelProps = mouseProps.concat('wheelDelta wheelDeltaX wheelDeltaY wheelDeltaZ axis'.split(' ')) // 'axis' is FF specific
, keyProps = commonProps.concat('char charCode key keyCode keyIdentifier keyLocation'.split(' '))
, textProps = commonProps.concat(['data'])
, touchProps = commonProps.concat('touches targetTouches changedTouches scale rotation'.split(' '))
, preventDefault = 'preventDefault'
, createPreventDefault = function (event) {
return function () {
if (event[preventDefault])
event[preventDefault]()
else
event.returnValue = false
}
}
, stopPropagation = 'stopPropagation'
, createStopPropagation = function (event) {
return function () {
if (event[stopPropagation])
event[stopPropagation]()
else
event.cancelBubble = true
}
}
, createStop = function (synEvent) {
return function () {
synEvent[preventDefault]()
synEvent[stopPropagation]()
synEvent.stopped = true
}
}
, copyProps = function (event, result, props) {
var i, p
for (i = props.length; i--;) {
p = props[i]
if (!(p in result) && p in event) result[p] = event[p]
}
}
return function (event, isNative) {
var result = { originalEvent: event, isNative: isNative }
if (!event)
return result
var props
, type = event.type
, target = event.target || event.srcElement
result[preventDefault] = createPreventDefault(event)
result[stopPropagation] = createStopPropagation(event)
result.stop = createStop(result)
result.target = target && target.nodeType === 3 ? target.parentNode : target
if (isNative) { // we only need basic augmentation on custom events, the rest is too expensive
if (type.indexOf('key') !== -1) {
props = keyProps
result.keyCode = event.which || event.keyCode
} else if (mouseTypeRegex.test(type)) {
props = mouseProps
result.rightClick = event.which === 3 || event.button === 2
result.pos = { x: 0, y: 0 }
if (event.pageX || event.pageY) {
result.clientX = event.pageX
result.clientY = event.pageY
} else if (event.clientX || event.clientY) {
result.clientX = event.clientX + doc.body.scrollLeft + root.scrollLeft
result.clientY = event.clientY + doc.body.scrollTop + root.scrollTop
}
if (overOut.test(type))
result.relatedTarget = event.relatedTarget || event[(type === 'mouseover' ? 'from' : 'to') + 'Element']
} else if (touchTypeRegex.test(type)) {
props = touchProps
} else if (mouseWheelTypeRegex.test(type)) {
props = mouseWheelProps
} else if (textTypeRegex.test(type)) {
props = textProps
}
copyProps(event, result, props || commonProps)
}
return result
}
})()
// if we're in old IE we can't do onpropertychange on doc or win so we use doc.documentElement for both
, targetElement = function (element, isNative) {
return !W3C_MODEL && !isNative && (element === doc || element === win) ? root : element
}
// we use one of these per listener, of any type
, RegEntry = (function () {
function entry(element, type, handler, original, namespaces) {
this.element = element
this.type = type
this.handler = handler
this.original = original
this.namespaces = namespaces
this.custom = customEvents[type]
this.isNative = nativeEvents[type] && element[eventSupport]
this.eventType = W3C_MODEL || this.isNative ? type : 'propertychange'
this.customType = !W3C_MODEL && !this.isNative && type
this.target = targetElement(element, this.isNative)
this.eventSupport = this.target[eventSupport]
}
entry.prototype = {
// given a list of namespaces, is our entry in any of them?
inNamespaces: function (checkNamespaces) {
var i, j
if (!checkNamespaces)
return true
if (!this.namespaces)
return false
for (i = checkNamespaces.length; i--;) {
for (j = this.namespaces.length; j--;) {
if (checkNamespaces[i] === this.namespaces[j])
return true
}
}
return false
}
// match by element, original fn (opt), handler fn (opt)
, matches: function (checkElement, checkOriginal, checkHandler) {
return this.element === checkElement &&
(!checkOriginal || this.original === checkOriginal) &&
(!checkHandler || this.handler === checkHandler)
}
}
return entry
})()
, registry = (function () {
// our map stores arrays by event type, just because it's better than storing
// everything in a single array. uses '$' as a prefix for the keys for safety
var map = {}
// generic functional search of our registry for matching listeners,
// `fn` returns false to break out of the loop
, forAll = function (element, type, original, handler, fn) {
if (!type || type === '*') {
// search the whole registry
for (var t in map) {
if (t.charAt(0) === '$')
forAll(element, t.substr(1), original, handler, fn)
}
} else {
var i = 0, l, list = map['$' + type], all = element === '*'
if (!list)
return
for (l = list.length; i < l; i++) {
if (all || list[i].matches(element, original, handler))
if (!fn(list[i], list, i, type))
return
}
}
}
, has = function (element, type, original) {
// we're not using forAll here simply because it's a bit slower and this
// needs to be fast
var i, list = map['$' + type]
if (list) {
for (i = list.length; i--;) {
if (list[i].matches(element, original, null))
return true
}
}
return false
}
, get = function (element, type, original) {
var entries = []
forAll(element, type, original, null, function (entry) { return entries.push(entry) })
return entries
}
, put = function (entry) {
(map['$' + entry.type] || (map['$' + entry.type] = [])).push(entry)
return entry
}
, del = function (entry) {
forAll(entry.element, entry.type, null, entry.handler, function (entry, list, i) {
list.splice(i, 1)
if (list.length === 0)
delete map['$' + entry.type]
return false
})
}
// dump all entries, used for onunload
, entries = function () {
var t, entries = []
for (t in map) {
if (t.charAt(0) === '$')
entries = entries.concat(map[t])
}
return entries
}
return { has: has, get: get, put: put, del: del, entries: entries }
})()
// add and remove listeners to DOM elements
, listener = W3C_MODEL ? function (element, type, fn, add) {
element[add ? addEvent : removeEvent](type, fn, false)
} : function (element, type, fn, add, custom) {
if (custom && add && element['_on' + custom] === null)
element['_on' + custom] = 0
element[add ? attachEvent : detachEvent]('on' + type, fn)
}
, nativeHandler = function (element, fn, args) {
return function (event) {
event = fixEvent(event || ((this.ownerDocument || this.document || this).parentWindow || win).event, true)
return fn.apply(element, [event].concat(args))
}
}
, customHandler = function (element, fn, type, condition, args, isNative) {
return function (event) {
if (condition ? condition.apply(this, arguments) : W3C_MODEL ? true : event && event.propertyName === '_on' + type || !event) {
if (event)
event = fixEvent(event || ((this.ownerDocument || this.document || this).parentWindow || win).event, isNative)
fn.apply(element, event && (!args || args.length === 0) ? arguments : slice.call(arguments, event ? 0 : 1).concat(args))
}
}
}
, once = function (rm, element, type, fn, originalFn) {
// wrap the handler in a handler that does a remove as well
return function () {
rm(element, type, originalFn)
fn.apply(this, arguments)
}
}
, removeListener = function (element, orgType, handler, namespaces) {
var i, l, entry
, type = (orgType && orgType.replace(nameRegex, ''))
, handlers = registry.get(element, type, handler)
for (i = 0, l = handlers.length; i < l; i++) {
if (handlers[i].inNamespaces(namespaces)) {
if ((entry = handlers[i]).eventSupport)
listener(entry.target, entry.eventType, entry.handler, false, entry.type)
// TODO: this is problematic, we have a registry.get() and registry.del() that
// both do registry searches so we waste cycles doing this. Needs to be rolled into
// a single registry.forAll(fn) that removes while finding, but the catch is that
// we'll be splicing the arrays that we're iterating over. Needs extra tests to
// make sure we don't screw it up. @rvagg
registry.del(entry)
}
}
}
, addListener = function (element, orgType, fn, originalFn, args) {
var entry
, type = orgType.replace(nameRegex, '')
, namespaces = orgType.replace(namespaceRegex, '').split('.')
if (registry.has(element, type, fn))
return element // no dupe
if (type === 'unload')
fn = once(removeListener, element, type, fn, originalFn) // self clean-up
if (customEvents[type]) {
if (customEvents[type].condition)
fn = customHandler(element, fn, type, customEvents[type].condition, true)
type = customEvents[type].base || type
}
entry = registry.put(new RegEntry(element, type, fn, originalFn, namespaces[0] && namespaces))
entry.handler = entry.isNative ?
nativeHandler(element, entry.handler, args) :
customHandler(element, entry.handler, type, false, args, false)
if (entry.eventSupport)
listener(entry.target, entry.eventType, entry.handler, true, entry.customType)
}
, del = function (selector, fn, $) {
return function (e) {
var target, i, array = typeof selector === 'string' ? $(selector, this) : selector
for (target = e.target; target && target !== this; target = target.parentNode) {
for (i = array.length; i--;) {
if (array[i] === target) {
return fn.apply(target, arguments)
}
}
}
}
}
, remove = function (element, typeSpec, fn) {
var k, m, type, namespaces, i
, rm = removeListener
, isString = typeSpec && typeof typeSpec === 'string'
if (isString && typeSpec.indexOf(' ') > 0) {
// remove(el, 't1 t2 t3', fn) or remove(el, 't1 t2 t3')
typeSpec = typeSpec.split(' ')
for (i = typeSpec.length; i--;)
remove(element, typeSpec[i], fn)
return element
}
type = isString && typeSpec.replace(nameRegex, '')
if (type && customEvents[type])
type = customEvents[type].type
if (!typeSpec || isString) {
// remove(el) or remove(el, t1.ns) or remove(el, .ns) or remove(el, .ns1.ns2.ns3)
if (namespaces = isString && typeSpec.replace(namespaceRegex, ''))
namespaces = namespaces.split('.')
rm(element, type, fn, namespaces)
} else if (typeof typeSpec === 'function') {
// remove(el, fn)
rm(element, null, typeSpec)
} else {
// remove(el, { t1: fn1, t2, fn2 })
for (k in typeSpec) {
if (typeSpec.hasOwnProperty(k))
remove(element, k, typeSpec[k])
}
}
return element
}
, add = function (element, events, fn, delfn, $) {
var type, types, i, args
, originalFn = fn
, isDel = fn && typeof fn === 'string'
if (events && !fn && typeof events === 'object') {
for (type in events) {
if (events.hasOwnProperty(type))
add.apply(this, [ element, type, events[type] ])
}
} else {
args = arguments.length > 3 ? slice.call(arguments, 3) : []
types = (isDel ? fn : events).split(' ')
isDel && (fn = del(events, (originalFn = delfn), $)) && (args = slice.call(args, 1))
// special case for one()
this === ONE && (fn = once(remove, element, events, fn, originalFn))
for (i = types.length; i--;) addListener(element, types[i], fn, originalFn, args)
}
return element
}
, one = function () {
return add.apply(ONE, arguments)
}
, fireListener = W3C_MODEL ? function (isNative, type, element) {
var evt = doc.createEvent(isNative ? 'HTMLEvents' : 'UIEvents')
evt[isNative ? 'initEvent' : 'initUIEvent'](type, true, true, win, 1)
element.dispatchEvent(evt)
} : function (isNative, type, element) {
element = targetElement(element, isNative)
// if not-native then we're using onpropertychange so we just increment a custom property
isNative ? element.fireEvent('on' + type, doc.createEventObject()) : element['_on' + type]++
}
, fire = function (element, type, args) {
var i, j, l, names, handlers
, types = type.split(' ')
for (i = types.length; i--;) {
type = types[i].replace(nameRegex, '')
if (names = types[i].replace(namespaceRegex, ''))
names = names.split('.')
if (!names && !args && element[eventSupport]) {
fireListener(nativeEvents[type], type, element)
} else {
// non-native event, either because of a namespace, arguments or a non DOM element
// iterate over all listeners and manually 'fire'
handlers = registry.get(element, type)
args = [false].concat(args)
for (j = 0, l = handlers.length; j < l; j++) {
if (handlers[j].inNamespaces(names))
handlers[j].handler.apply(element, args)
}
}
}
return element
}
, clone = function (element, from, type) {
var i = 0
, handlers = registry.get(from, type)
, l = handlers.length
for (;i < l; i++)
handlers[i].original && add(element, handlers[i].type, handlers[i].original)
return element
}
, bean = {
add: add
, one: one
, remove: remove
, clone: clone
, fire: fire
, noConflict: function () {
context[name] = old
return this
}
}
if (win[attachEvent]) {
// for IE, clean up on unload to avoid leaks
var cleanup = function () {
var i, entries = registry.entries()
for (i in entries) {
if (entries[i].type && entries[i].type !== 'unload')
remove(entries[i].element, entries[i].type)
}
win[detachEvent]('onunload', cleanup)
win.CollectGarbage && win.CollectGarbage()
}
win[attachEvent]('onunload', cleanup)
}
return bean
})
// Copyright Google Inc.
// Licensed under the Apache Licence Version 2.0
// Autogenerated at Tue Oct 11 13:36:46 EDT 2011
// @provides html4
var html4 = {};
html4.atype = {
NONE: 0,
URI: 1,
URI_FRAGMENT: 11,
SCRIPT: 2,
STYLE: 3,
ID: 4,
IDREF: 5,
IDREFS: 6,
GLOBAL_NAME: 7,
LOCAL_NAME: 8,
CLASSES: 9,
FRAME_TARGET: 10
};
html4.ATTRIBS = {
'*::class': 9,
'*::dir': 0,
'*::id': 4,
'*::lang': 0,
'*::onclick': 2,
'*::ondblclick': 2,
'*::onkeydown': 2,
'*::onkeypress': 2,
'*::onkeyup': 2,
'*::onload': 2,
'*::onmousedown': 2,
'*::onmousemove': 2,
'*::onmouseout': 2,
'*::onmouseover': 2,
'*::onmouseup': 2,
'*::style': 3,
'*::title': 0,
'a::accesskey': 0,
'a::coords': 0,
'a::href': 1,
'a::hreflang': 0,
'a::name': 7,
'a::onblur': 2,
'a::onfocus': 2,
'a::rel': 0,
'a::rev': 0,
'a::shape': 0,
'a::tabindex': 0,
'a::target': 10,
'a::type': 0,
'area::accesskey': 0,
'area::alt': 0,
'area::coords': 0,
'area::href': 1,
'area::nohref': 0,
'area::onblur': 2,
'area::onfocus': 2,
'area::shape': 0,
'area::tabindex': 0,
'area::target': 10,
'bdo::dir': 0,
'blockquote::cite': 1,
'br::clear': 0,
'button::accesskey': 0,
'button::disabled': 0,
'button::name': 8,
'button::onblur': 2,
'button::onfocus': 2,
'button::tabindex': 0,
'button::type': 0,
'button::value': 0,
'canvas::height': 0,
'canvas::width': 0,
'caption::align': 0,
'col::align': 0,
'col::char': 0,
'col::charoff': 0,
'col::span': 0,
'col::valign': 0,
'col::width': 0,
'colgroup::align': 0,
'colgroup::char': 0,
'colgroup::charoff': 0,
'colgroup::span': 0,
'colgroup::valign': 0,
'colgroup::width': 0,
'del::cite': 1,
'del::datetime': 0,
'dir::compact': 0,
'div::align': 0,
'dl::compact': 0,
'font::color': 0,
'font::face': 0,
'font::size': 0,
'form::accept': 0,
'form::action': 1,
'form::autocomplete': 0,
'form::enctype': 0,
'form::method': 0,
'form::name': 7,
'form::onreset': 2,
'form::onsubmit': 2,
'form::target': 10,
'h1::align': 0,
'h2::align': 0,
'h3::align': 0,
'h4::align': 0,
'h5::align': 0,
'h6::align': 0,
'hr::align': 0,
'hr::noshade': 0,
'hr::size': 0,
'hr::width': 0,
'iframe::align': 0,
'iframe::frameborder': 0,
'iframe::height': 0,
'iframe::marginheight': 0,
'iframe::marginwidth': 0,
'iframe::width': 0,
'img::align': 0,
'img::alt': 0,
'img::border': 0,
'img::height': 0,
'img::hspace': 0,
'img::ismap': 0,
'img::name': 7,
'img::src': 1,
'img::usemap': 11,
'img::vspace': 0,
'img::width': 0,
'input::accept': 0,
'input::accesskey': 0,
'input::align': 0,
'input::alt': 0,
'input::autocomplete': 0,
'input::checked': 0,
'input::disabled': 0,
'input::ismap': 0,
'input::maxlength': 0,
'input::name': 8,
'input::onblur': 2,
'input::onchange': 2,
'input::onfocus': 2,
'input::onselect': 2,
'input::readonly': 0,
'input::size': 0,
'input::src': 1,
'input::tabindex': 0,
'input::type': 0,
'input::usemap': 11,
'input::value': 0,
'ins::cite': 1,
'ins::datetime': 0,
'label::accesskey': 0,
'label::for': 5,
'label::onblur': 2,
'label::onfocus': 2,
'legend::accesskey': 0,
'legend::align': 0,
'li::type': 0,
'li::value': 0,
'map::name': 7,
'menu::compact': 0,
'ol::compact': 0,
'ol::start': 0,
'ol::type': 0,
'optgroup::disabled': 0,
'optgroup::label': 0,
'option::disabled': 0,
'option::label': 0,
'option::selected': 0,
'option::value': 0,
'p::align': 0,
'pre::width': 0,
'q::cite': 1,
'select::disabled': 0,
'select::multiple': 0,
'select::name': 8,
'select::onblur': 2,
'select::onchange': 2,
'select::onfocus': 2,
'select::size': 0,
'select::tabindex': 0,
'table::align': 0,
'table::bgcolor': 0,
'table::border': 0,
'table::cellpadding': 0,
'table::cellspacing': 0,
'table::frame': 0,
'table::rules': 0,
'table::summary': 0,
'table::width': 0,
'tbody::align': 0,
'tbody::char': 0,
'tbody::charoff': 0,
'tbody::valign': 0,
'td::abbr': 0,
'td::align': 0,
'td::axis': 0,
'td::bgcolor': 0,
'td::char': 0,
'td::charoff': 0,
'td::colspan': 0,
'td::headers': 6,
'td::height': 0,
'td::nowrap': 0,
'td::rowspan': 0,
'td::scope': 0,
'td::valign': 0,
'td::width': 0,
'textarea::accesskey': 0,
'textarea::cols': 0,
'textarea::disabled': 0,
'textarea::name': 8,
'textarea::onblur': 2,
'textarea::onchange': 2,
'textarea::onfocus': 2,
'textarea::onselect': 2,
'textarea::readonly': 0,
'textarea::rows': 0,
'textarea::tabindex': 0,
'tfoot::align': 0,
'tfoot::char': 0,
'tfoot::charoff': 0,
'tfoot::valign': 0,
'th::abbr': 0,
'th::align': 0,
'th::axis': 0,
'th::bgcolor': 0,
'th::char': 0,
'th::charoff': 0,
'th::colspan': 0,
'th::headers': 6,
'th::height': 0,
'th::nowrap': 0,
'th::rowspan': 0,
'th::scope': 0,
'th::valign': 0,
'th::width': 0,
'thead::align': 0,
'thead::char': 0,
'thead::charoff': 0,
'thead::valign': 0,
'tr::align': 0,
'tr::bgcolor': 0,
'tr::char': 0,
'tr::charoff': 0,
'tr::valign': 0,
'ul::compact': 0,
'ul::type': 0
};
html4.eflags = {
OPTIONAL_ENDTAG: 1,
EMPTY: 2,
CDATA: 4,
RCDATA: 8,
UNSAFE: 16,
FOLDABLE: 32,
SCRIPT: 64,
STYLE: 128
};
html4.ELEMENTS = {
'a': 0,
'abbr': 0,
'acronym': 0,
'address': 0,
'applet': 16,
'area': 2,
'b': 0,
'base': 18,
'basefont': 18,
'bdo': 0,
'big': 0,
'blockquote': 0,
'body': 49,
'br': 2,
'button': 0,
'canvas': 0,
'caption': 0,
'center': 0,
'cite': 0,
'code': 0,
'col': 2,
'colgroup': 1,
'dd': 1,
'del': 0,
'dfn': 0,
'dir': 0,
'div': 0,
'dl': 0,
'dt': 1,
'em': 0,
'fieldset': 0,
'font': 0,
'form': 0,
'frame': 18,
'frameset': 16,
'h1': 0,
'h2': 0,
'h3': 0,
'h4': 0,
'h5': 0,
'h6': 0,
'head': 49,
'hr': 2,
'html': 49,
'i': 0,
'iframe': 4,
'img': 2,
'input': 2,
'ins': 0,
'isindex': 18,
'kbd': 0,
'label': 0,
'legend': 0,
'li': 1,
'link': 18,
'map': 0,
'menu': 0,
'meta': 18,
'nobr': 0,
'noembed': 4,
'noframes': 20,
'noscript': 20,
'object': 16,
'ol': 0,
'optgroup': 0,
'option': 1,
'p': 1,
'param': 18,
'pre': 0,
'q': 0,
's': 0,
'samp': 0,
'script': 84,
'select': 0,
'small': 0,
'span': 0,
'strike': 0,
'strong': 0,
'style': 148,
'sub': 0,
'sup': 0,
'table': 0,
'tbody': 1,
'td': 1,
'textarea': 8,
'tfoot': 1,
'th': 1,
'thead': 1,
'title': 24,
'tr': 1,
'tt': 0,
'u': 0,
'ul': 0,
'var': 0
};
html4.ueffects = {
NOT_LOADED: 0,
SAME_DOCUMENT: 1,
NEW_DOCUMENT: 2
};
html4.URIEFFECTS = {
'a::href': 2,
'area::href': 2,
'blockquote::cite': 0,
'body::background': 1,
'del::cite': 0,
'form::action': 2,
'img::src': 1,
'input::src': 1,
'ins::cite': 0,
'q::cite': 0
};
html4.ltypes = {
UNSANDBOXED: 2,
SANDBOXED: 1,
DATA: 0
};
html4.LOADERTYPES = {
'a::href': 2,
'area::href': 2,
'blockquote::cite': 2,
'body::background': 1,
'del::cite': 2,
'form::action': 2,
'img::src': 1,
'input::src': 1,
'ins::cite': 2,
'q::cite': 2
};;
// Copyright (C) 2006 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview
* An HTML sanitizer that can satisfy a variety of security policies.
*
* <p>
* The HTML sanitizer is built around a SAX parser and HTML element and
* attributes schemas.
*
* @author mikesamuel@gmail.com
* @requires html4
* @overrides window
* @provides html, html_sanitize
*/
/**
* @namespace
*/
var html = (function (html4) {
var lcase;
// The below may not be true on browsers in the Turkish locale.
if ('script' === 'SCRIPT'.toLowerCase()) {
lcase = function (s) { return s.toLowerCase(); };
} else {
/**
* {@updoc
* $ lcase('SCRIPT')
* # 'script'
* $ lcase('script')
* # 'script'
* }
*/
lcase = function (s) {
return s.replace(
/[A-Z]/g,
function (ch) {
return String.fromCharCode(ch.charCodeAt(0) | 32);
});
};
}
var ENTITIES = {
lt : '<',
gt : '>',
amp : '&',
nbsp : '\240',
quot : '"',
apos : '\''
};
// Schemes on which to defer to uripolicy. Urls with other schemes are denied
var WHITELISTED_SCHEMES = /^(?:https?|mailto|data)$/i;
var decimalEscapeRe = /^#(\d+)$/;
var hexEscapeRe = /^#x([0-9A-Fa-f]+)$/;
/**
* Decodes an HTML entity.
*
* {@updoc
* $ lookupEntity('lt')
* # '<'
* $ lookupEntity('GT')
* # '>'
* $ lookupEntity('amp')
* # '&'
* $ lookupEntity('nbsp')
* # '\xA0'
* $ lookupEntity('apos')
* # "'"
* $ lookupEntity('quot')
* # '"'
* $ lookupEntity('#xa')
* # '\n'
* $ lookupEntity('#10')
* # '\n'
* $ lookupEntity('#x0a')
* # '\n'
* $ lookupEntity('#010')
* # '\n'
* $ lookupEntity('#x00A')
* # '\n'
* $ lookupEntity('Pi') // Known failure
* # '\u03A0'
* $ lookupEntity('pi') // Known failure
* # '\u03C0'
* }
*
* @param name the content between the '&' and the ';'.
* @return a single unicode code-point as a string.
*/
function lookupEntity(name) {
name = lcase(name); // TODO: &pi; is different from &Pi;
if (ENTITIES.hasOwnProperty(name)) { return ENTITIES[name]; }
var m = name.match(decimalEscapeRe);
if (m) {
return String.fromCharCode(parseInt(m[1], 10));
} else if (!!(m = name.match(hexEscapeRe))) {
return String.fromCharCode(parseInt(m[1], 16));
}
return '';
}
function decodeOneEntity(_, name) {
return lookupEntity(name);
}
var nulRe = /\0/g;
function stripNULs(s) {
return s.replace(nulRe, '');
}
var entityRe = /&(#\d+|#x[0-9A-Fa-f]+|\w+);/g;
/**
* The plain text of a chunk of HTML CDATA which possibly containing.
*
* {@updoc
* $ unescapeEntities('')
* # ''
* $ unescapeEntities('hello World!')
* # 'hello World!'
* $ unescapeEntities('1 &lt; 2 &amp;&AMP; 4 &gt; 3&#10;')
* # '1 < 2 && 4 > 3\n'
* $ unescapeEntities('&lt;&lt <- unfinished entity&gt;')
* # '<&lt <- unfinished entity>'
* $ unescapeEntities('/foo?bar=baz&copy=true') // & often unescaped in URLS
* # '/foo?bar=baz&copy=true'
* $ unescapeEntities('pi=&pi;&#x3c0;, Pi=&Pi;\u03A0') // FIXME: known failure
* # 'pi=\u03C0\u03c0, Pi=\u03A0\u03A0'
* }
*
* @param s a chunk of HTML CDATA. It must not start or end inside an HTML
* entity.
*/
function unescapeEntities(s) {
return s.replace(entityRe, decodeOneEntity);
}
var ampRe = /&/g;
var looseAmpRe = /&([^a-z#]|#(?:[^0-9x]|x(?:[^0-9a-f]|$)|$)|$)/gi;
var ltRe = /</g;
var gtRe = />/g;
var quotRe = /\"/g;
var eqRe = /\=/g; // Backslash required on JScript.net
/**
* Escapes HTML special characters in attribute values as HTML entities.
*
* {@updoc
* $ escapeAttrib('')
* # ''
* $ escapeAttrib('"<<&==&>>"') // Do not just escape the first occurrence.
* # '&#34;&lt;&lt;&amp;&#61;&#61;&amp;&gt;&gt;&#34;'
* $ escapeAttrib('Hello <World>!')
* # 'Hello &lt;World&gt;!'
* }
*/
function escapeAttrib(s) {
// Escaping '=' defangs many UTF-7 and SGML short-tag attacks.
return s.replace(ampRe, '&amp;').replace(ltRe, '&lt;').replace(gtRe, '&gt;')
.replace(quotRe, '&#34;').replace(eqRe, '&#61;');
}
/**
* Escape entities in RCDATA that can be escaped without changing the meaning.
* {@updoc
* $ normalizeRCData('1 < 2 &&amp; 3 > 4 &amp;& 5 &lt; 7&8')
* # '1 &lt; 2 &amp;&amp; 3 &gt; 4 &amp;&amp; 5 &lt; 7&amp;8'
* }
*/
function normalizeRCData(rcdata) {
return rcdata
.replace(looseAmpRe, '&amp;$1')
.replace(ltRe, '&lt;')
.replace(gtRe, '&gt;');
}
// TODO(mikesamuel): validate sanitizer regexs against the HTML5 grammar at
// http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html
// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html
/** token definitions. */
var INSIDE_TAG_TOKEN = new RegExp(
// Don't capture space.
'^\\s*(?:'
// Capture an attribute name in group 1, and value in group 3.
// We capture the fact that there was an attribute in group 2, since
// interpreters are inconsistent in whether a group that matches nothing
// is null, undefined, or the empty string.
+ ('(?:'
+ '([a-z][a-z-]*)' // attribute name
+ ('(' // optionally followed
+ '\\s*=\\s*'
+ ('('
// A double quoted string.
+ '\"[^\"]*\"'
// A single quoted string.
+ '|\'[^\']*\''
// The positive lookahead is used to make sure that in
// <foo bar= baz=boo>, the value for bar is blank, not "baz=boo".
+ '|(?=[a-z][a-z-]*\\s*=)'
// An unquoted value that is not an attribute name.
// We know it is not an attribute name because the previous
// zero-width match would've eliminated that possibility.
+ '|[^>\"\'\\s]*'
+ ')'
)
+ ')'
) + '?'
+ ')'
)
// End of tag captured in group 3.
+ '|(\/?>)'
// Don't capture cruft
+ '|[\\s\\S][^a-z\\s>]*)',
'i');
var OUTSIDE_TAG_TOKEN = new RegExp(
'^(?:'
// Entity captured in group 1.
+ '&(\\#[0-9]+|\\#[x][0-9a-f]+|\\w+);'
// Comment, doctypes, and processing instructions not captured.
+ '|<\!--[\\s\\S]*?--\>|<!\\w[^>]*>|<\\?[^>*]*>'
// '/' captured in group 2 for close tags, and name captured in group 3.
+ '|<(\/)?([a-z][a-z0-9]*)'
// Text captured in group 4.
+ '|([^<&>]+)'
// Cruft captured in group 5.
+ '|([<&>]))',
'i');
/**
* Given a SAX-like event handler, produce a function that feeds those
* events and a parameter to the event handler.
*
* The event handler has the form:{@code
* {
* // Name is an upper-case HTML tag name. Attribs is an array of
* // alternating upper-case attribute names, and attribute values. The
* // attribs array is reused by the parser. Param is the value passed to
* // the saxParser.
* startTag: function (name, attribs, param) { ... },
* endTag: function (name, param) { ... },
* pcdata: function (text, param) { ... },
* rcdata: function (text, param) { ... },
* cdata: function (text, param) { ... },
* startDoc: function (param) { ... },
* endDoc: function (param) { ... }
* }}
*
* @param {Object} handler a record containing event handlers.
* @return {Function} that takes a chunk of html and a parameter.
* The parameter is passed on to the handler methods.
*/
function makeSaxParser(handler) {
return function parse(htmlText, param) {
htmlText = String(htmlText);
var htmlLower = null;
var inTag = false; // True iff we're currently processing a tag.
var attribs = []; // Accumulates attribute names and values.
var tagName = void 0; // The name of the tag currently being processed.
var eflags = void 0; // The element flags for the current tag.
var openTag = void 0; // True if the current tag is an open tag.
if (handler.startDoc) { handler.startDoc(param); }
while (htmlText) {
var m = htmlText.match(inTag ? INSIDE_TAG_TOKEN : OUTSIDE_TAG_TOKEN);
htmlText = htmlText.substring(m[0].length);
if (inTag) {
if (m[1]) { // attribute
// setAttribute with uppercase names doesn't work on IE6.
var attribName = lcase(m[1]);
var decodedValue;
if (m[2]) {
var encodedValue = m[3];
switch (encodedValue.charCodeAt(0)) { // Strip quotes
case 34: case 39:
encodedValue = encodedValue.substring(
1, encodedValue.length - 1);
break;
}
decodedValue = unescapeEntities(stripNULs(encodedValue));
} else {
// Use name as value for valueless attribs, so
// <input type=checkbox checked>
// gets attributes ['type', 'checkbox', 'checked', 'checked']
decodedValue = attribName;
}
attribs.push(attribName, decodedValue);
} else if (m[4]) {
if (eflags !== void 0) { // False if not in whitelist.
if (openTag) {
if (handler.startTag) {
handler.startTag(tagName, attribs, param);
}
} else {
if (handler.endTag) {
handler.endTag(tagName, param);
}
}
}
if (openTag
&& (eflags & (html4.eflags.CDATA | html4.eflags.RCDATA))) {
if (htmlLower === null) {
htmlLower = lcase(htmlText);
} else {
htmlLower = htmlLower.substring(
htmlLower.length - htmlText.length);
}
var dataEnd = htmlLower.indexOf('</' + tagName);
if (dataEnd < 0) { dataEnd = htmlText.length; }
if (dataEnd) {
if (eflags & html4.eflags.CDATA) {
if (handler.cdata) {
handler.cdata(htmlText.substring(0, dataEnd), param);
}
} else if (handler.rcdata) {
handler.rcdata(
normalizeRCData(htmlText.substring(0, dataEnd)), param);
}
htmlText = htmlText.substring(dataEnd);
}
}
tagName = eflags = openTag = void 0;
attribs.length = 0;
inTag = false;
}
} else {
if (m[1]) { // Entity
if (handler.pcdata) { handler.pcdata(m[0], param); }
} else if (m[3]) { // Tag
openTag = !m[2];
inTag = true;
tagName = lcase(m[3]);
eflags = html4.ELEMENTS.hasOwnProperty(tagName)
? html4.ELEMENTS[tagName] : void 0;
} else if (m[4]) { // Text
if (handler.pcdata) { handler.pcdata(m[4], param); }
} else if (m[5]) { // Cruft
if (handler.pcdata) {
var ch = m[5];
handler.pcdata(
ch === '<' ? '&lt;' : ch === '>' ? '&gt;' : '&amp;',
param);
}
}
}
}
if (handler.endDoc) { handler.endDoc(param); }
};
}
/**
* Returns a function that strips unsafe tags and attributes from html.
* @param {Function} sanitizeAttributes
* maps from (tagName, attribs[]) to null or a sanitized attribute array.
* The attribs array can be arbitrarily modified, but the same array
* instance is reused, so should not be held.
* @return {Function} from html to sanitized html
*/
function makeHtmlSanitizer(sanitizeAttributes) {
var stack;
var ignoring;
return makeSaxParser({
startDoc: function (_) {
stack = [];
ignoring = false;
},
startTag: function (tagName, attribs, out) {
if (ignoring) { return; }
if (!html4.ELEMENTS.hasOwnProperty(tagName)) { return; }
var eflags = html4.ELEMENTS[tagName];
if (eflags & html4.eflags.FOLDABLE) {
return;
} else if (eflags & html4.eflags.UNSAFE) {
ignoring = !(eflags & html4.eflags.EMPTY);
return;
}
attribs = sanitizeAttributes(tagName, attribs);
// TODO(mikesamuel): relying on sanitizeAttributes not to
// insert unsafe attribute names.
if (attribs) {
if (!(eflags & html4.eflags.EMPTY)) {
stack.push(tagName);
}
out.push('<', tagName);
for (var i = 0, n = attribs.length; i < n; i += 2) {
var attribName = attribs[i],
value = attribs[i + 1];
if (value !== null && value !== void 0) {
out.push(' ', attribName, '="', escapeAttrib(value), '"');
}
}
out.push('>');
}
},
endTag: function (tagName, out) {
if (ignoring) {
ignoring = false;
return;
}
if (!html4.ELEMENTS.hasOwnProperty(tagName)) { return; }
var eflags = html4.ELEMENTS[tagName];
if (!(eflags & (html4.eflags.UNSAFE | html4.eflags.EMPTY
| html4.eflags.FOLDABLE))) {
var index;
if (eflags & html4.eflags.OPTIONAL_ENDTAG) {
for (index = stack.length; --index >= 0;) {
var stackEl = stack[index];
if (stackEl === tagName) { break; }
if (!(html4.ELEMENTS[stackEl]
& html4.eflags.OPTIONAL_ENDTAG)) {
// Don't pop non optional end tags looking for a match.
return;
}
}
} else {
for (index = stack.length; --index >= 0;) {
if (stack[index] === tagName) { break; }
}
}
if (index < 0) { return; } // Not opened.
for (var i = stack.length; --i > index;) {
var stackEl = stack[i];
if (!(html4.ELEMENTS[stackEl]
& html4.eflags.OPTIONAL_ENDTAG)) {
out.push('</', stackEl, '>');
}
}
stack.length = index;
out.push('</', tagName, '>');
}
},
pcdata: function (text, out) {
if (!ignoring) { out.push(text); }
},
rcdata: function (text, out) {
if (!ignoring) { out.push(text); }
},
cdata: function (text, out) {
if (!ignoring) { out.push(text); }
},
endDoc: function (out) {
for (var i = stack.length; --i >= 0;) {
out.push('</', stack[i], '>');
}
stack.length = 0;
}
});
}
// From RFC3986
var URI_SCHEME_RE = new RegExp(
"^" +
"(?:" +
"([^:\/?#]+)" + // scheme
":)?"
);
/**
* Strips unsafe tags and attributes from html.
* @param {string} htmlText to sanitize
* @param {Function} opt_uriPolicy -- a transform to apply to uri/url
* attribute values. If no opt_uriPolicy is provided, no uris
* are allowed ie. the default uriPolicy rewrites all uris to null
* @param {Function} opt_nmTokenPolicy : string -> string? -- a transform to
* apply to names, ids, and classes. If no opt_nmTokenPolicy is provided,
* all names, ids and classes are passed through ie. the default
* nmTokenPolicy is an identity transform
* @return {string} html
*/
function sanitize(htmlText, opt_uriPolicy, opt_nmTokenPolicy) {
var out = [];
makeHtmlSanitizer(
function sanitizeAttribs(tagName, attribs) {
for (var i = 0; i < attribs.length; i += 2) {
var attribName = attribs[i];
var value = attribs[i + 1];
var atype = null, attribKey;
if ((attribKey = tagName + '::' + attribName,
html4.ATTRIBS.hasOwnProperty(attribKey))
|| (attribKey = '*::' + attribName,
html4.ATTRIBS.hasOwnProperty(attribKey))) {
atype = html4.ATTRIBS[attribKey];
}
if (atype !== null) {
switch (atype) {
case html4.atype.NONE: break;
case html4.atype.SCRIPT:
case html4.atype.STYLE:
value = null;
break;
case html4.atype.ID:
case html4.atype.IDREF:
case html4.atype.IDREFS:
case html4.atype.GLOBAL_NAME:
case html4.atype.LOCAL_NAME:
case html4.atype.CLASSES:
value = opt_nmTokenPolicy ? opt_nmTokenPolicy(value) : value;
break;
case html4.atype.URI:
var parsedUri = ('' + value).match(URI_SCHEME_RE);
if (!parsedUri) {
value = null;
} else if (!parsedUri[1] ||
WHITELISTED_SCHEMES.test(parsedUri[1])) {
value = opt_uriPolicy && opt_uriPolicy(value);
} else {
value = null;
}
break;
case html4.atype.URI_FRAGMENT:
if (value && '#' === value.charAt(0)) {
value = opt_nmTokenPolicy ? opt_nmTokenPolicy(value) : value;
if (value) { value = '#' + value; }
} else {
value = null;
}
break;
default:
value = null;
break;
}
} else {
value = null;
}
attribs[i + 1] = value;
}
return attribs;
})(htmlText, out);
return out.join('');
}
return {
escapeAttrib: escapeAttrib,
makeHtmlSanitizer: makeHtmlSanitizer,
makeSaxParser: makeSaxParser,
normalizeRCData: normalizeRCData,
sanitize: sanitize,
unescapeEntities: unescapeEntities
};
})(html4);
var html_sanitize = html.sanitize;
// Exports for closure compiler. Note this file is also cajoled
// for domado and run in an environment without 'window'
if (typeof window !== 'undefined') {
window['html'] = html;
window['html_sanitize'] = html_sanitize;
}
// Loosen restrictions of Caja's
// html-sanitizer to allow for styling
html4.ATTRIBS['*::style'] = 0;
html4.ELEMENTS['style'] = 0;
/*
mustache.js — Logic-less templates in JavaScript
See http://mustache.github.com/ for more info.
*/
var Mustache = function() {
var regexCache = {};
var Renderer = function() {};
Renderer.prototype = {
otag: "{{",
ctag: "}}",
pragmas: {},
buffer: [],
pragmas_implemented: {
"IMPLICIT-ITERATOR": true
},
context: {},
render: function(template, context, partials, in_recursion) {
// reset buffer & set context
if(!in_recursion) {
this.context = context;
this.buffer = []; // TODO: make this non-lazy
}
// fail fast
if(!this.includes("", template)) {
if(in_recursion) {
return template;
} else {
this.send(template);
return;
}
}
// get the pragmas together
template = this.render_pragmas(template);
// render the template
var html = this.render_section(template, context, partials);
// render_section did not find any sections, we still need to render the tags
if (html === false) {
html = this.render_tags(template, context, partials, in_recursion);
}
if (in_recursion) {
return html;
} else {
this.sendLines(html);
}
},
/*
Sends parsed lines
*/
send: function(line) {
if(line !== "") {
this.buffer.push(line);
}
},
sendLines: function(text) {
if (text) {
var lines = text.split("\n");
for (var i = 0; i < lines.length; i++) {
this.send(lines[i]);
}
}
},
/*
Looks for %PRAGMAS
*/
render_pragmas: function(template) {
// no pragmas
if(!this.includes("%", template)) {
return template;
}
var that = this;
var regex = this.getCachedRegex("render_pragmas", function(otag, ctag) {
return new RegExp(otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" + ctag, "g");
});
return template.replace(regex, function(match, pragma, options) {
if(!that.pragmas_implemented[pragma]) {
throw({message:
"This implementation of mustache doesn't understand the '" +
pragma + "' pragma"});
}
that.pragmas[pragma] = {};
if(options) {
var opts = options.split("=");
that.pragmas[pragma][opts[0]] = opts[1];
}
return "";
// ignore unknown pragmas silently
});
},
/*
Tries to find a partial in the curent scope and render it
*/
render_partial: function(name, context, partials) {
name = this.trim(name);
if(!partials || partials[name] === undefined) {
throw({message: "unknown_partial '" + name + "'"});
}
if(typeof(context[name]) != "object") {
return this.render(partials[name], context, partials, true);
}
return this.render(partials[name], context[name], partials, true);
},
/*
Renders inverted (^) and normal (#) sections
*/
render_section: function(template, context, partials) {
if(!this.includes("#", template) && !this.includes("^", template)) {
// did not render anything, there were no sections
return false;
}
var that = this;
var regex = this.getCachedRegex("render_section", function(otag, ctag) {
// This regex matches _the first_ section ({{#foo}}{{/foo}}), and captures the remainder
return new RegExp(
"^([\\s\\S]*?)" + // all the crap at the beginning that is not {{*}} ($1)
otag + // {{
"(\\^|\\#)\\s*(.+)\\s*" + // #foo (# == $2, foo == $3)
ctag + // }}
"\n*([\\s\\S]*?)" + // between the tag ($2). leading newlines are dropped
otag + // {{
"\\/\\s*\\3\\s*" + // /foo (backreference to the opening tag).
ctag + // }}
"\\s*([\\s\\S]*)$", // everything else in the string ($4). leading whitespace is dropped.
"g");
});
// for each {{#foo}}{{/foo}} section do...
return template.replace(regex, function(match, before, type, name, content, after) {
// before contains only tags, no sections
var renderedBefore = before ? that.render_tags(before, context, partials, true) : "",
// after may contain both sections and tags, so use full rendering function
renderedAfter = after ? that.render(after, context, partials, true) : "",
// will be computed below
renderedContent,
value = that.find(name, context);
if (type === "^") { // inverted section
if (!value || that.is_array(value) && value.length === 0) {
// false or empty list, render it
renderedContent = that.render(content, context, partials, true);
} else {
renderedContent = "";
}
} else if (type === "#") { // normal section
if (that.is_array(value)) { // Enumerable, Let's loop!
renderedContent = that.map(value, function(row) {
return that.render(content, that.create_context(row), partials, true);
}).join("");
} else if (that.is_object(value)) { // Object, Use it as subcontext!
renderedContent = that.render(content, that.create_context(value),
partials, true);
} else if (typeof value === "function") {
// higher order section
renderedContent = value.call(context, content, function(text) {
return that.render(text, context, partials, true);
});
} else if (value) { // boolean section
renderedContent = that.render(content, context, partials, true);
} else {
renderedContent = "";
}
}
return renderedBefore + renderedContent + renderedAfter;
});
},
/*
Replace {{foo}} and friends with values from our view
*/
render_tags: function(template, context, partials, in_recursion) {
// tit for tat
var that = this;
var new_regex = function() {
return that.getCachedRegex("render_tags", function(otag, ctag) {
return new RegExp(otag + "(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?" + ctag + "+", "g");
});
};
var regex = new_regex();
var tag_replace_callback = function(match, operator, name) {
switch(operator) {
case "!": // ignore comments
return "";
case "=": // set new delimiters, rebuild the replace regexp
that.set_delimiters(name);
regex = new_regex();
return "";
case ">": // render partial
return that.render_partial(name, context, partials);
case "{": // the triple mustache is unescaped
return that.find(name, context);
default: // escape the value
return that.escape(that.find(name, context));
}
};
var lines = template.split("\n");
for(var i = 0; i < lines.length; i++) {
lines[i] = lines[i].replace(regex, tag_replace_callback, this);
if(!in_recursion) {
this.send(lines[i]);
}
}
if(in_recursion) {
return lines.join("\n");
}
},
set_delimiters: function(delimiters) {
var dels = delimiters.split(" ");
this.otag = this.escape_regex(dels[0]);
this.ctag = this.escape_regex(dels[1]);
},
escape_regex: function(text) {
// thank you Simon Willison
if(!arguments.callee.sRE) {
var specials = [
'/', '.', '*', '+', '?', '|',
'(', ')', '[', ']', '{', '}', '\\'
];
arguments.callee.sRE = new RegExp(
'(\\' + specials.join('|\\') + ')', 'g'
);
}
return text.replace(arguments.callee.sRE, '\\$1');
},
/*
find `name` in current `context`. That is find me a value
from the view object
*/
find: function(name, context) {
name = this.trim(name);
// Checks whether a value is thruthy or false or 0
function is_kinda_truthy(bool) {
return bool === false || bool === 0 || bool;
}
var value;
if(is_kinda_truthy(context[name])) {
value = context[name];
} else if(is_kinda_truthy(this.context[name])) {
value = this.context[name];
}
if(typeof value === "function") {
return value.apply(context);
}
if(value !== undefined) {
return value;
}
// silently ignore unkown variables
return "";
},
// Utility methods
/* includes tag */
includes: function(needle, haystack) {
return haystack.indexOf(this.otag + needle) != -1;
},
/*
Does away with nasty characters
*/
escape: function(s) {
s = String(s === null ? "" : s);
return s.replace(/&(?!\w+;)|["'<>\\]/g, function(s) {
switch(s) {
case "&": return "&amp;";
case '"': return '&quot;';
case "'": return '&#39;';
case "<": return "&lt;";
case ">": return "&gt;";
default: return s;
}
});
},
// by @langalex, support for arrays of strings
create_context: function(_context) {
if(this.is_object(_context)) {
return _context;
} else {
var iterator = ".";
if(this.pragmas["IMPLICIT-ITERATOR"]) {
iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator;
}
var ctx = {};
ctx[iterator] = _context;
return ctx;
}
},
is_object: function(a) {
return a && typeof a == "object";
},
is_array: function(a) {
return Object.prototype.toString.call(a) === '[object Array]';
},
/*
Gets rid of leading and trailing whitespace
*/
trim: function(s) {
return s.replace(/^\s*|\s*$/g, "");
},
/*
Why, why, why? Because IE. Cry, cry cry.
*/
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;
}
},
getCachedRegex: function(name, generator) {
var byOtag = regexCache[this.otag];
if (!byOtag) {
byOtag = regexCache[this.otag] = {};
}
var byCtag = byOtag[this.ctag];
if (!byCtag) {
byCtag = byOtag[this.ctag] = {};
}
var regex = byCtag[name];
if (!regex) {
regex = byCtag[name] = generator(this.otag, this.ctag);
}
return regex;
}
};
return({
name: "mustache.js",
version: "0.4.0-dev",
/*
Turns a template and view into HTML
*/
to_html: function(template, view, partials, send_fun) {
var renderer = new Renderer();
if(send_fun) {
renderer.send = send_fun;
}
renderer.render(template, view || {}, partials);
if(!send_fun) {
return renderer.buffer.join("\n");
}
}
});
}();
/*!
* Reqwest! A general purpose XHR connection manager
* copyright Dustin Diaz 2011
* https://github.com/ded/reqwest
* license MIT
*/
!function(context,win){function serial(a){var b=a.name;if(a.disabled||!b)return"";b=enc(b);switch(a.tagName.toLowerCase()){case"input":switch(a.type){case"reset":case"button":case"image":case"file":return"";case"checkbox":case"radio":return a.checked?b+"="+(a.value?enc(a.value):!0)+"&":"";default:return b+"="+(a.value?enc(a.value):"")+"&"}break;case"textarea":return b+"="+enc(a.value)+"&";case"select":return b+"="+enc(a.options[a.selectedIndex].value)+"&"}return""}function enc(a){return encodeURIComponent(a)}function reqwest(a,b){return new Reqwest(a,b)}function init(o,fn){function error(a){o.error&&o.error(a),complete(a)}function success(resp){o.timeout&&clearTimeout(self.timeout)&&(self.timeout=null);var r=resp.responseText;if(r)switch(type){case"json":resp=win.JSON?win.JSON.parse(r):eval("("+r+")");break;case"js":resp=eval(r);break;case"html":resp=r}fn(resp),o.success&&o.success(resp),complete(resp)}function complete(a){o.complete&&o.complete(a)}this.url=typeof o=="string"?o:o.url,this.timeout=null;var type=o.type||setType(this.url),self=this;fn=fn||function(){},o.timeout&&(this.timeout=setTimeout(function(){self.abort(),error()},o.timeout)),this.request=getRequest(o,success,error)}function setType(a){if(/\.json$/.test(a))return"json";if(/\.jsonp$/.test(a))return"jsonp";if(/\.js$/.test(a))return"js";if(/\.html?$/.test(a))return"html";if(/\.xml$/.test(a))return"xml";return"js"}function Reqwest(a,b){this.o=a,this.fn=b,init.apply(this,arguments)}function getRequest(a,b,c){if(a.type!="jsonp"){var f=xhr();f.open(a.method||"GET",typeof a=="string"?a:a.url,!0),setHeaders(f,a),f.onreadystatechange=handleReadyState(f,b,c),a.before&&a.before(f),f.send(a.data||null);return f}var d=doc.createElement("script"),e=0;win[getCallbackName(a)]=generalCallback,d.type="text/javascript",d.src=a.url,d.async=!0,d.onload=d.onreadystatechange=function(){if(d[readyState]&&d[readyState]!=="complete"&&d[readyState]!=="loaded"||e)return!1;d.onload=d.onreadystatechange=null,a.success&&a.success(lastValue),lastValue=undefined,head.removeChild(d),e=1},head.appendChild(d)}function generalCallback(a){lastValue=a}function getCallbackName(a){var b=a.jsonpCallback||"callback";if(a.url.slice(-(b.length+2))==b+"=?"){var c="reqwest_"+uniqid++;a.url=a.url.substr(0,a.url.length-1)+c;return c}var d=new RegExp(b+"=([\\w]+)");return a.url.match(d)[1]}function setHeaders(a,b){var c=b.headers||{};c.Accept=c.Accept||"text/javascript, text/html, application/xml, text/xml, */*",b.crossOrigin||(c["X-Requested-With"]=c["X-Requested-With"]||"XMLHttpRequest"),c[contentType]=c[contentType]||"application/x-www-form-urlencoded";for(var d in c)c.hasOwnProperty(d)&&a.setRequestHeader(d,c[d],!1)}function handleReadyState(a,b,c){return function(){a&&a[readyState]==4&&(twoHundo.test(a.status)?b(a):c(a))}}var twoHundo=/^20\d$/,doc=document,byTag="getElementsByTagName",readyState="readyState",contentType="Content-Type",head=doc[byTag]("head")[0],uniqid=0,lastValue,xhr="XMLHttpRequest"in win?function(){return new XMLHttpRequest}:function(){return new ActiveXObject("Microsoft.XMLHTTP")};Reqwest.prototype={abort:function(){this.request.abort()},retry:function(){init.call(this,this.o,this.fn)}},reqwest.serialize=function(a){var b=[a[byTag]("input"),a[byTag]("select"),a[byTag]("textarea")],c=[],d,e;for(d=0,l=b.length;d<l;++d)for(e=0,l2=b[d].length;e<l2;++e)c.push(serial(b[d][e]));return c.join("").replace(/&$/,"")},reqwest.serializeArray=function(a){for(var b=this.serialize(a).split("&"),c=0,d=b.length,e=[],f;c<d;c++)b[c]&&(f=b[c].split("="))&&e.push({name:f[0],value:f[1]});return e};var old=context.reqwest;reqwest.noConflict=function(){context.reqwest=old;return this},typeof module!="undefined"?module.exports=reqwest:context.reqwest=reqwest}(this,window);wax = wax || {};
// Attribution
// -----------
wax.attribution = function() {
var container,
a = {};
function urlX(url) {
// Data URIs are subject to a bug in Firefox
// https://bugzilla.mozilla.org/show_bug.cgi?id=255107
// which let them be a vector. But WebKit does 'the right thing'
// or at least 'something' about this situation, so we'll tolerate
// them.
if (/^(https?:\/\/|data:image)/.test(url)) {
return url;
}
}
function idX(id) {
return id;
}
a.content = function(x) {
if (typeof x === 'undefined') return container.innerHTML;
container.innerHTML = html_sanitize(x, urlX, idX);
return this;
};
a.element = function() {
return container;
};
a.init = function() {
container = document.createElement('div');
container.className = 'wax-attribution';
return this;
};
return a.init();
};
wax = wax || {};
// Attribution
// -----------
wax.bwdetect = function(options, callback) {
var detector = {},
threshold = options.threshold || 400,
// test image: 30.29KB
testImage = 'http://a.tiles.mapbox.com/mapbox/1.0.0/blue-marble-topo-bathy-jul/0/0/0.png?preventcache=' + (+new Date()),
// High-bandwidth assumed
// 1: high bandwidth (.png, .jpg)
// 0: low bandwidth (.png128, .jpg70)
bw = 1,
// Alternative versions
auto = options.auto === undefined ? true : options.auto;
function bwTest() {
wax.bw = -1;
var im = new Image();
im.src = testImage;
var first = true;
var timeout = setTimeout(function() {
if (first && wax.bw == -1) {
detector.bw(0);
first = false;
}
}, threshold);
im.onload = function() {
if (first && wax.bw == -1) {
clearTimeout(timeout);
detector.bw(1);
first = false;
}
};
}
detector.bw = function(x) {
if (!arguments.length) return bw;
var oldBw = bw;
if (wax.bwlisteners && wax.bwlisteners.length) (function () {
listeners = wax.bwlisteners;
wax.bwlisteners = [];
for (i = 0; i < listeners; i++) {
listeners[i](x);
}
})();
wax.bw = x;
if (bw != (bw = x)) callback(x);
};
detector.add = function() {
if (auto) bwTest();
return this;
};
if (wax.bw == -1) {
wax.bwlisteners = wax.bwlisteners || [];
wax.bwlisteners.push(detector.bw);
} else if (wax.bw !== undefined) {
detector.bw(wax.bw);
} else {
detector.add();
}
return detector;
};
// Formatter
// ---------
//
// This code is no longer the recommended code path for Wax -
// see `template.js`, a safe implementation of Mustache templates.
wax.formatter = function(x) {
var formatter = {},
f;
// Prevent against just any input being used.
if (x && typeof x === 'string') {
try {
// Ugly, dangerous use of eval.
eval('f = ' + x);
} catch (e) {
if (console) console.log(e);
}
} else if (x && typeof x === 'function') {
f = x;
} else {
f = function() {};
}
function urlX(url) {
if (/^(https?:\/\/|data:image)/.test(url)) {
return url;
}
}
function idX(id) {
return id;
}
// Wrap the given formatter function in order to
// catch exceptions that it may throw.
formatter.format = function(options, data) {
try {
return html_sanitize(f(options, data), urlX, idX);
} catch (e) {
if (console) console.log(e);
}
};
return formatter;
};
// GridInstance
// ------------
// GridInstances are queryable, fully-formed
// objects for acquiring features from events.
//
// This code ignores format of 1.1-1.2
wax.gi = function(grid_tile, options) {
options = options || {};
// resolution is the grid-elements-per-pixel ratio of gridded data.
// The size of a tile element. For now we expect tiles to be squares.
var instance = {},
resolution = options.resolution || 4,
tileSize = options.tileSize || 256;
// Resolve the UTF-8 encoding stored in grids to simple
// number values.
// See the [utfgrid spec](https://github.com/mapbox/utfgrid-spec)
// for details.
function resolveCode(key) {
if (key >= 93) key--;
if (key >= 35) key--;
key -= 32;
return key;
}
instance.grid_tile = function() {
return grid_tile;
};
instance.getKey = function(x, y) {
if (!(grid_tile && grid_tile.grid)) return;
if ((y < 0) || (x < 0)) return;
if ((Math.floor(y) >= tileSize) ||
(Math.floor(x) >= tileSize)) return;
// Find the key in the grid. The above calls should ensure that
// the grid's array is large enough to make this work.
return resolveCode(grid_tile.grid[
Math.floor((y) / resolution)
].charCodeAt(
Math.floor((x) / resolution)
));
};
// Lower-level than tileFeature - has nothing to do
// with the DOM. Takes a px offset from 0, 0 of a grid.
instance.gridFeature = function(x, y) {
// Find the key in the grid. The above calls should ensure that
// the grid's array is large enough to make this work.
var key = this.getKey(x, y),
keys = grid_tile.keys;
if (keys &&
keys[key] &&
grid_tile.data[keys[key]]) {
return grid_tile.data[keys[key]];
}
};
// Get a feature:
// * `x` and `y`: the screen coordinates of an event
// * `tile_element`: a DOM element of a tile, from which we can get an offset.
instance.tileFeature = function(x, y, tile_element) {
if (!grid_tile) return;
// IE problem here - though recoverable, for whatever reason
var offset = wax.u.offset(tile_element);
feature = this.gridFeature(x - offset.left, y - offset.top);
return feature;
};
return instance;
};
// GridManager
// -----------
// Generally one GridManager will be used per map.
//
// It takes one options object, which current accepts a single option:
// `resolution` determines the number of pixels per grid element in the grid.
// The default is 4.
wax.gm = function() {
var resolution = 4,
grid_tiles = {},
manager = {},
tilejson,
formatter;
var gridUrl = function(url) {
return url.replace(/(\.png|\.jpg|\.jpeg)(\d*)/, '.grid.json');
};
function templatedGridUrl(template) {
if (typeof template === 'string') template = [template];
return function templatedGridFinder(url) {
if (!url) return;
var rx = new RegExp('/(\\d+)\\/(\\d+)\\/(\\d+)\\.[\\w\\._]+');
var xyz = rx.exec(url);
if (!xyz) return;
return template[parseInt(xyz[2], 10) % template.length]
.replace('{z}', xyz[1])
.replace('{x}', xyz[2])
.replace('{y}', xyz[3]);
};
}
manager.formatter = function(x) {
if (!arguments.length) return formatter;
formatter = wax.formatter(x);
return manager;
};
manager.template = function(x) {
if (!arguments.length) return formatter;
formatter = wax.template(x);
return manager;
};
manager.gridUrl = function(x) {
if (!arguments.length) return gridUrl;
gridUrl = typeof x === 'function' ?
x : templatedGridUrl(x);
return manager;
};
manager.getGrid = function(url, callback) {
var gurl = gridUrl(url);
if (!formatter || !gurl) return callback(null, null);
wax.request.get(gurl, function(err, t) {
if (err) return callback(err, null);
callback(null, wax.gi(t, {
formatter: formatter,
resolution: resolution
}));
});
return manager;
};
manager.tilejson = function(x) {
if (!arguments.length) return tilejson;
// prefer templates over formatters
if (x.template) {
manager.template(x.template);
} else if (x.formatter) {
manager.formatter(x.formatter);
}
if (x.grids) manager.gridUrl(x.grids);
if (x.resolution) resolution = x.resolution;
tilejson = x;
return manager;
};
return manager;
};
wax = wax || {};
// Hash
// ----
wax.hash = function(options) {
options = options || {};
function getState() {
return location.hash.substring(1);
}
function pushState(state) {
var l = window.location;
l.replace(l.toString().replace(l.hash, '#' + state));
}
var s0, // old hash
hash = {},
lat = 90 - 1e-8; // allowable latitude range
function parseHash(s) {
var args = s.split('/');
for (var i = 0; i < args.length; i++) {
args[i] = Number(args[i]);
if (isNaN(args[i])) return true;
}
if (args.length < 3) {
// replace bogus hash
return true;
} else if (args.length == 3) {
options.setCenterZoom(args);
}
}
function move() {
var s1 = options.getCenterZoom();
if (s0 !== s1) {
s0 = s1;
// don't recenter the map!
pushState(s0);
}
}
function stateChange(state) {
// ignore spurious hashchange events
if (state === s0) return;
if (parseHash(s0 = state)) {
// replace bogus hash
move();
}
}
var _move = wax.u.throttle(move, 500);
hash.add = function() {
stateChange(getState());
options.bindChange(_move);
return this;
};
hash.remove = function() {
options.unbindChange(_move);
return this;
};
return hash.add();
};
wax = wax || {};
wax.interaction = function() {
var gm = wax.gm(),
interaction = {},
_downLock = false,
_clickTimeout = false,
// Active feature
// Down event
_d,
// Touch tolerance
tol = 4,
grid,
attach,
detach,
parent,
map,
tileGrid;
var defaultEvents = {
mousemove: onMove,
touchstart: onDown,
mousedown: onDown
};
var touchEnds = {
touchend: onUp,
touchmove: onUp,
touchcancel: touchCancel
};
// Abstract getTile method. Depends on a tilegrid with
// grid[ [x, y, tile] ] structure.
function getTile(e) {
var g = grid();
for (var i = 0; i < g.length; i++) {
if ((g[i][0] < e.y) &&
((g[i][0] + 256) > e.y) &&
(g[i][1] < e.x) &&
((g[i][1] + 256) > e.x)) return g[i][2];
}
return false;
}
// Clear the double-click timeout to prevent double-clicks from
// triggering popups.
function killTimeout() {
if (_clickTimeout) {
window.clearTimeout(_clickTimeout);
_clickTimeout = null;
return true;
} else {
return false;
}
}
function onMove(e) {
// If the user is actually dragging the map, exit early
// to avoid performance hits.
if (_downLock) return;
var pos = wax.u.eventoffset(e),
tile = getTile(pos),
feature;
if (tile) gm.getGrid(tile.src, function(err, g) {
if (err || !g) return;
feature = g.tileFeature(pos.x, pos.y, tile);
if (feature) {
bean.fire(interaction, 'on', {
parent: parent(),
data: feature,
formatter: gm.formatter().format,
e: e
});
} else {
bean.fire(interaction, 'off');
}
});
}
// A handler for 'down' events - which means `mousedown` and `touchstart`
function onDown(e) {
// Ignore double-clicks by ignoring clicks within 300ms of
// each other.
if (killTimeout()) { return; }
// Prevent interaction offset calculations happening while
// the user is dragging the map.
//
// Store this event so that we can compare it to the
// up event
_downLock = true;
_d = wax.u.eventoffset(e);
if (e.type === 'mousedown') {
bean.add(document.body, 'mouseup', onUp);
// Only track single-touches. Double-touches will not affect this
// control
} else if (e.type === 'touchstart' && e.touches.length === 1) {
// Don't make the user click close if they hit another tooltip
bean.fire(interaction, 'off');
// Touch moves invalidate touches
bean.add(parent(), touchEnds);
}
}
function touchCancel() {
bean.remove(parent(), touchEnds);
_downLock = false;
}
function onUp(e) {
var evt = {},
pos = wax.u.eventoffset(e);
_downLock = false;
// TODO: refine
for (var key in e) {
evt[key] = e[key];
}
bean.remove(document.body, 'mouseup', onUp);
bean.remove(parent(), touchEnds);
if (e.type === 'touchend') {
// If this was a touch and it survived, there's no need to avoid a double-tap
// but also wax.u.eventoffset will have failed, since this touch
// event doesn't have coordinates
click(e, _d);
} else if (Math.round(pos.y / tol) === Math.round(_d.y / tol) &&
Math.round(pos.x / tol) === Math.round(_d.x / tol)) {
// Contain the event data in a closure.
_clickTimeout = window.setTimeout(
function() {
_clickTimeout = null;
click(evt, pos);
}, 300);
}
return onUp;
}
// Handle a click event. Takes a second
function click(e, pos) {
var tile = getTile(pos);
if (tile) gm.getGrid(tile.src, function(err, g) {
if (err || !g) return;
var feature = g.tileFeature(pos.x, pos.y, tile);
if (!feature) return;
bean.fire(interaction, 'on', {
parent: parent(),
data: feature,
formatter: gm.formatter().format,
e: e
});
});
}
// set an attach function that should be
// called when maps are set
interaction.attach = function(x) {
if (!arguments.length) return attach;
attach = x;
return interaction;
};
interaction.detach = function(x) {
if (!arguments.length) return detach;
detach = x;
return interaction;
};
// Attach listeners to the map
interaction.map = function(x) {
if (!arguments.length) return map;
map = x;
if (attach) attach(map);
bean.add(parent(), defaultEvents);
bean.add(parent(), 'touchstart', onDown);
return interaction;
};
// set a grid getter for this control
interaction.grid = function(x) {
if (!arguments.length) return grid;
grid = x;
return interaction;
};
// detach this and its events from the map cleanly
interaction.remove = function(x) {
if (detach) detach(map);
bean.remove(parent(), defaultEvents);
bean.fire(interaction, 'remove');
return interaction;
};
// get or set a tilejson chunk of json
interaction.tilejson = function(x) {
if (!arguments.length) return gm.tilejson();
gm.tilejson(x);
return interaction;
};
// return the formatter, which has an exposed .format
// function
interaction.formatter = function() {
return gm.formatter();
};
// ev can be 'on', 'off', fn is the handler
interaction.on = function(ev, fn) {
bean.add(interaction, ev, fn);
return interaction;
};
// ev can be 'on', 'off', fn is the handler
interaction.off = function(ev, fn) {
bean.remove(interaction, ev, fn);
return interaction;
};
// parent should be a function that returns
// the parent element of the map
interaction.parent = function(x) {
parent = x;
return interaction;
};
return interaction;
};
// Wax Legend
// ----------
// Wax header
var wax = wax || {};
wax.legend = function() {
var element,
legend = {},
container;
function urlX(url) {
// Data URIs are subject to a bug in Firefox
// https://bugzilla.mozilla.org/show_bug.cgi?id=255107
// which let them be a vector. But WebKit does 'the right thing'
// or at least 'something' about this situation, so we'll tolerate
// them.
if (/^(https?:\/\/|data:image)/.test(url)) {
return url;
}
}
function idX(id) {
return id;
}
legend.element = function() {
return container;
};
legend.content = function(content) {
if (!arguments.length) return element.innerHTML;
if (content) {
element.innerHTML = html_sanitize(content, urlX, idX);
element.style.display = 'block';
} else {
element.innerHTML = '';
element.style.display = 'none';
}
return legend;
};
legend.add = function() {
container = document.createElement('div');
container.className = 'wax-legends';
element = container.appendChild(document.createElement('div'));
element.className = 'wax-legend';
element.style.display = 'none';
return legend;
};
return legend.add();
};
var wax = wax || {};
wax.movetip = {};
wax.movetip = function() {
var popped = false,
t = {},
_tooltipOffset,
_contextOffset,
tooltip,
parent;
function moveTooltip(e) {
var eo = wax.u.eventoffset(e);
// faux-positioning
if ((_tooltipOffset.height + eo.y) >
(_contextOffset.top + _contextOffset.height) &&
(_contextOffset.height > _tooltipOffset.height)) {
eo.y -= _tooltipOffset.height;
tooltip.className += ' flip-y';
}
// faux-positioning
if ((_tooltipOffset.width + eo.x) >
(_contextOffset.left + _contextOffset.width)) {
eo.x -= _tooltipOffset.width;
tooltip.className += ' flip-x';
}
tooltip.style.left = eo.x + 'px';
tooltip.style.top = eo.y + 'px';
}
// Get the active tooltip for a layer or create a new one if no tooltip exists.
// Hide any tooltips on layers underneath this one.
function getTooltip(feature) {
var tooltip = document.createElement('div');
tooltip.className = 'wax-tooltip wax-tooltip-0';
tooltip.innerHTML = feature;
return tooltip;
}
// Hide a given tooltip.
function hide() {
if (tooltip) {
tooltip.parentNode.removeChild(tooltip);
tooltip = null;
}
}
function on(o) {
var content;
if (popped) return;
if ((o.e.type === 'mousemove' || !o.e.type)) {
content = o.formatter({ format: 'teaser' }, o.data);
if (!content) return;
hide();
parent.style.cursor = 'pointer';
tooltip = document.body.appendChild(getTooltip(content));
} else {
content = o.formatter({ format: 'teaser' }, o.data);
if (!content) return;
hide();
var tt = document.body.appendChild(getTooltip(content));
tt.className += ' wax-popup';
var close = tt.appendChild(document.createElement('a'));
close.href = '#close';
close.className = 'close';
close.innerHTML = 'Close';
popped = true;
tooltip = tt;
_tooltipOffset = wax.u.offset(tooltip);
_contextOffset = wax.u.offset(parent);
moveTooltip(o.e);
bean.add(close, 'click touchend', function closeClick(e) {
e.stop();
hide();
popped = false;
});
}
if (tooltip) {
_tooltipOffset = wax.u.offset(tooltip);
_contextOffset = wax.u.offset(parent);
moveTooltip(o.e);
}
}
function off() {
parent.style.cursor = 'default';
if (!popped) hide();
}
t.parent = function(x) {
if (!arguments.length) return parent;
parent = x;
return t;
};
t.events = function() {
return {
on: on,
off: off
};
};
return t;
};
// Wax GridUtil
// ------------
// Wax header
var wax = wax || {};
// Request
// -------
// Request data cache. `callback(data)` where `data` is the response data.
wax.request = {
cache: {},
locks: {},
promises: {},
get: function(url, callback) {
// Cache hit.
if (this.cache[url]) {
return callback(this.cache[url][0], this.cache[url][1]);
// Cache miss.
} else {
this.promises[url] = this.promises[url] || [];
this.promises[url].push(callback);
// Lock hit.
if (this.locks[url]) return;
// Request.
var that = this;
this.locks[url] = true;
reqwest({
url: url + (~url.indexOf('?') ? '&' : '?') + 'callback=grid',
type: 'jsonp',
jsonpCallback: 'callback',
success: function(data) {
that.locks[url] = false;
that.cache[url] = [null, data];
for (var i = 0; i < that.promises[url].length; i++) {
that.promises[url][i](that.cache[url][0], that.cache[url][1]);
}
},
error: function(err) {
that.locks[url] = false;
that.cache[url] = [err, null];
for (var i = 0; i < that.promises[url].length; i++) {
that.promises[url][i](that.cache[url][0], that.cache[url][1]);
}
}
});
}
}
};
// Templating
// ---------
wax.template = function(x) {
var template = {};
function urlX(url) {
// Data URIs are subject to a bug in Firefox
// https://bugzilla.mozilla.org/show_bug.cgi?id=255107
// which let them be a vector. But WebKit does 'the right thing'
// or at least 'something' about this situation, so we'll tolerate
// them.
if (/^(https?:\/\/|data:image)/.test(url)) {
return url;
}
}
function idX(id) {
return id;
}
// Clone the data object such that the '__[format]__' key is only
// set for this instance of templating.
template.format = function(options, data) {
var clone = {};
for (var key in data) {
clone[key] = data[key];
}
if (options.format) {
clone['__' + options.format + '__'] = true;
}
return html_sanitize(Mustache.to_html(x, clone), urlX, idX);
};
return template;
};
if (!wax) var wax = {};
// A wrapper for reqwest jsonp to easily load TileJSON from a URL.
wax.tilejson = function(url, callback) {
reqwest({
url: url + (~url.indexOf('?') ? '&' : '?') + 'callback=grid',
type: 'jsonp',
jsonpCallback: 'callback',
success: callback,
error: callback
});
};
var wax = wax || {};
wax.tooltip = {};
wax.tooltip = function() {
var popped = false,
animate = false,
t = {},
tooltips = [],
_currentContent,
transitionEvent,
parent;
if (document.body.style['-webkit-transition'] !== undefined) {
transitionEvent = 'webkitTransitionEnd';
} else if (document.body.style.MozTransition !== undefined) {
transitionEvent = 'transitionend';
}
// Get the active tooltip for a layer or create a new one if no tooltip exists.
// Hide any tooltips on layers underneath this one.
function getTooltip(feature) {
var tooltip = document.createElement('div');
tooltip.className = 'wax-tooltip wax-tooltip-0';
tooltip.innerHTML = feature;
return tooltip;
}
function remove() {
if (this.parentNode) this.parentNode.removeChild(this);
}
// Hide a given tooltip.
function hide() {
var _ct;
while (_ct = tooltips.pop()) {
if (animate && transitionEvent) {
// This code assumes that transform-supporting browsers
// also support proper events. IE9 does both.
bean.add(_ct, transitionEvent, remove);
_ct.className += ' wax-fade';
} else {
if (_ct.parentNode) _ct.parentNode.removeChild(_ct);
}
}
}
function on(o) {
var content;
if ((o.e.type === 'mousemove' || !o.e.type) && !popped) {
content = o.content || o.formatter({ format: 'teaser' }, o.data);
if (!content || content == _currentContent) return;
hide();
parent.style.cursor = 'pointer';
tooltips.push(parent.appendChild(getTooltip(content)));
_currentContent = content;
} else {
content = o.content || o.formatter({ format: 'full' }, o.data);
if (!content) {
if (o.e.type && o.e.type.match(/touch/)) {
// fallback possible
content = o.content || o.formatter({ format: 'teaser' }, o.data);
}
// but if that fails, return just the same.
if (!content) return;
}
hide();
parent.style.cursor = 'pointer';
var tt = parent.appendChild(getTooltip(content));
tt.className += ' wax-popup';
var close = tt.appendChild(document.createElement('a'));
close.href = '#close';
close.className = 'close';
close.innerHTML = 'Close';
popped = true;
tooltips.push(tt);
bean.add(close, 'click touchend', function closeClick(e) {
e.stop();
hide();
popped = false;
});
}
}
function off() {
parent.style.cursor = 'default';
_currentContent = null;
if (!popped) hide();
}
t.parent = function(x) {
if (!arguments.length) return parent;
parent = x;
return t;
};
t.animate = function(x) {
if (!arguments.length) return animate;
animate = x;
return t;
};
t.events = function() {
return {
on: on,
off: off
};
};
return t;
};
var wax = wax || {};
// Utils are extracted from other libraries or
// written from scratch to plug holes in browser compatibility.
wax.u = {
// From Bonzo
offset: function(el) {
// TODO: window margins
//
// Okay, so fall back to styles if offsetWidth and height are botched
// by Firefox.
var width = el.offsetWidth || parseInt(el.style.width, 10),
height = el.offsetHeight || parseInt(el.style.height, 10),
doc_body = document.body,
top = 0,
left = 0;
var calculateOffset = function(el) {
if (el === doc_body || el === document.documentElement) return;
top += el.offsetTop;
left += el.offsetLeft;
var style = el.style.transform ||
el.style.WebkitTransform ||
el.style.OTransform ||
el.style.MozTransform ||
el.style.msTransform;
if (style) {
if (match = style.match(/translate\((.+)px, (.+)px\)/)) {
top += parseInt(match[2], 10);
left += parseInt(match[1], 10);
} else if (match = style.match(/translate3d\((.+)px, (.+)px, (.+)px\)/)) {
top += parseInt(match[2], 10);
left += parseInt(match[1], 10);
} else if (match = style.match(/matrix3d\(([\-\d,\s]+)\)/)) {
var pts = match[1].split(',');
top += parseInt(pts[13], 10);
left += parseInt(pts[12], 10);
} else if (match = style.match(/matrix\(.+, .+, .+, .+, (.+), (.+)\)/)) {
top += parseInt(match[2], 10);
left += parseInt(match[1], 10);
}
}
};
calculateOffset(el);
try {
while (el = el.offsetParent) { calculateOffset(el); }
} catch(e) {
// Hello, internet explorer.
}
// Offsets from the body
top += doc_body.offsetTop;
left += doc_body.offsetLeft;
// Offsets from the HTML element
top += doc_body.parentNode.offsetTop;
left += doc_body.parentNode.offsetLeft;
// Firefox and other weirdos. Similar technique to jQuery's
// `doesNotIncludeMarginInBodyOffset`.
var htmlComputed = document.defaultView ?
window.getComputedStyle(doc_body.parentNode, null) :
doc_body.parentNode.currentStyle;
if (doc_body.parentNode.offsetTop !==
parseInt(htmlComputed.marginTop, 10) &&
!isNaN(parseInt(htmlComputed.marginTop, 10))) {
top += parseInt(htmlComputed.marginTop, 10);
left += parseInt(htmlComputed.marginLeft, 10);
}
return {
top: top,
left: left,
height: height,
width: width
};
},
'$': function(x) {
return (typeof x === 'string') ?
document.getElementById(x) :
x;
},
// IE doesn't have indexOf
indexOf: function(array, item) {
var nativeIndexOf = Array.prototype.indexOf;
if (array === null) return -1;
var i, l;
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
for (i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
return -1;
},
// From underscore: reimplement the ECMA5 `Object.keys()` method
keys: Object.keys || function(obj) {
var ho = Object.prototype.hasOwnProperty;
if (obj !== Object(obj)) throw new TypeError('Invalid object');
var keys = [];
for (var key in obj) if (ho.call(obj, key)) keys[keys.length] = key;
return keys;
},
// From quirksmode: normalize the offset of an event from the top-left
// of the page.
eventoffset: function(e) {
var posx = 0;
var posy = 0;
if (!e) { e = window.event; }
if (e.pageX || e.pageY) {
// Good browsers
return {
x: e.pageX,
y: e.pageY
};
} else if (e.clientX || e.clientY) {
// Internet Explorer
var doc = document.documentElement, body = document.body;
var htmlComputed = document.body.parentNode.currentStyle;
var topMargin = parseInt(htmlComputed.marginTop, 10) || 0;
var leftMargin = parseInt(htmlComputed.marginLeft, 10) || 0;
return {
x: e.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
(doc && doc.clientLeft || body && body.clientLeft || 0) + leftMargin,
y: e.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) -
(doc && doc.clientTop || body && body.clientTop || 0) + topMargin
};
} else if (e.touches && e.touches.length === 1) {
// Touch browsers
return {
x: e.touches[0].pageX,
y: e.touches[0].pageY
};
}
},
// Ripped from underscore.js
// Internal function used to implement `_.throttle` and `_.debounce`.
limit: function(func, wait, debounce) {
var timeout;
return function() {
var context = this, args = arguments;
var throttler = function() {
timeout = null;
func.apply(context, args);
};
if (debounce) clearTimeout(timeout);
if (debounce || !timeout) timeout = setTimeout(throttler, wait);
};
},
// Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time.
throttle: function(func, wait) {
return this.limit(func, wait, false);
}
};
wax = wax || {};
wax.mm = wax.mm || {};
// Attribution
// -----------
// Attribution wrapper for Modest Maps.
wax.mm.attribution = function(map, tilejson) {
tilejson = tilejson || {};
var a, // internal attribution control
attribution = {};
attribution.element = function() {
return a.element();
};
attribution.appendTo = function(elem) {
wax.u.$(elem).appendChild(a.element());
return this;
};
attribution.init = function() {
a = wax.attribution();
a.content(tilejson.attribution);
a.element().className = 'wax-attribution wax-mm';
return this;
};
return attribution.init();
};
wax = wax || {};
wax.mm = wax.mm || {};
// Box Selector
// ------------
wax.mm.boxselector = function(map, tilejson, opts) {
var corner = null,
nearCorner = null,
callback = ((typeof opts === 'function') ?
opts :
opts.callback),
boxDiv,
style,
borderWidth = 0,
horizontal = false, // Whether the resize is horizontal
vertical = false,
edge = 5, // Distance from border sensitive to resizing
addEvent = MM.addEvent,
removeEvent = MM.removeEvent,
box,
boxselector = {};
function getMousePoint(e) {
// start with just the mouse (x, y)
var point = new MM.Point(e.clientX, e.clientY);
// correct for scrolled document
point.x += document.body.scrollLeft + document.documentElement.scrollLeft;
point.y += document.body.scrollTop + document.documentElement.scrollTop;
// correct for nested offsets in DOM
for (var node = map.parent; node; node = node.offsetParent) {
point.x -= node.offsetLeft;
point.y -= node.offsetTop;
}
return point;
}
function mouseDown(e) {
if (!e.shiftKey) return;
corner = nearCorner = getMousePoint(e);
horizontal = vertical = true;
style.left = corner.x + 'px';
style.top = corner.y + 'px';
style.width = style.height = 0;
addEvent(document, 'mousemove', mouseMove);
addEvent(document, 'mouseup', mouseUp);
map.parent.style.cursor = 'crosshair';
return MM.cancelEvent(e);
}
// Resize existing box
function mouseDownResize(e) {
var point = getMousePoint(e),
TL = {
x: parseInt(boxDiv.offsetLeft, 10),
y: parseInt(boxDiv.offsetTop, 10)
},
BR = {
x: TL.x + parseInt(boxDiv.offsetWidth, 10),
y: TL.y + parseInt(boxDiv.offsetHeight, 10)
};
// Determine whether resize is horizontal, vertical or both
horizontal = point.x - TL.x <= edge || BR.x - point.x <= edge;
vertical = point.y - TL.y <= edge || BR.y - point.y <= edge;
if (vertical || horizontal) {
corner = {
x: (point.x - TL.x < BR.x - point.x) ? BR.x : TL.x,
y: (point.y - TL.y < BR.y - point.y) ? BR.y : TL.y
};
nearCorner = {
x: (point.x - TL.x < BR.x - point.x) ? TL.x : BR.x,
y: (point.y - TL.y < BR.y - point.y) ? TL.y : BR.y
};
addEvent(document, 'mousemove', mouseMove);
addEvent(document, 'mouseup', mouseUp);
return MM.cancelEvent(e);
}
}
function mouseMove(e) {
var point = getMousePoint(e);
style.display = 'block';
if (horizontal) {
style.left = (point.x < corner.x ? point.x : corner.x) + 'px';
style.width = Math.abs(point.x - corner.x) - 2 * borderWidth + 'px';
}
if (vertical) {
style.top = (point.y < corner.y ? point.y : corner.y) + 'px';
style.height = Math.abs(point.y - corner.y) - 2 * borderWidth + 'px';
}
changeCursor(point, map.parent);
return MM.cancelEvent(e);
}
function mouseUp(e) {
var point = getMousePoint(e),
l1 = map.pointLocation( new MM.Point(
horizontal ? point.x : nearCorner.x,
vertical? point.y : nearCorner.y
));
l2 = map.pointLocation(corner);
// Format coordinates like mm.map.getExtent().
boxselector.extent([
new MM.Location(
Math.max(l1.lat, l2.lat),
Math.min(l1.lon, l2.lon)),
new MM.Location(
Math.min(l1.lat, l2.lat),
Math.max(l1.lon, l2.lon))
]);
removeEvent(document, 'mousemove', mouseMove);
removeEvent(document, 'mouseup', mouseUp);
map.parent.style.cursor = 'auto';
}
function mouseMoveCursor(e) {
changeCursor(getMousePoint(e), boxDiv);
}
// Set resize cursor if mouse is on edge
function changeCursor(point, elem) {
var TL = {
x: parseInt(boxDiv.offsetLeft, 10),
y: parseInt(boxDiv.offsetTop, 10)
},
BR = {
x: TL.x + parseInt(boxDiv.offsetWidth, 10),
y: TL.y + parseInt(boxDiv.offsetHeight, 10)
};
// Build cursor style string
var prefix = '';
if (point.y - TL.y <= edge) prefix = 'n';
else if (BR.y - point.y <= edge) prefix = 's';
if (point.x - TL.x <= edge) prefix += 'w';
else if (BR.x - point.x <= edge) prefix += 'e';
if (prefix !== '') prefix += '-resize';
elem.style.cursor = prefix;
}
function drawbox(map, e) {
if (!boxDiv || !box) return;
var br = map.locationPoint(box[1]),
tl = map.locationPoint(box[0]),
style = boxDiv.style;
style.display = 'block';
style.height = 'auto';
style.width = 'auto';
style.left = Math.max(0, tl.x) + 'px';
style.top = Math.max(0, tl.y) + 'px';
style.right = Math.max(0, map.dimensions.x - br.x) + 'px';
style.bottom = Math.max(0, map.dimensions.y - br.y) + 'px';
}
boxselector.extent = function(x, silent) {
if (!x) return box;
box = [
new MM.Location(
Math.max(x[0].lat, x[1].lat),
Math.min(x[0].lon, x[1].lon)),
new MM.Location(
Math.min(x[0].lat, x[1].lat),
Math.max(x[0].lon, x[1].lon))
];
drawbox(map);
if (!silent) callback(box);
};
boxselector.add = function(map) {
boxDiv = boxDiv || document.createElement('div');
boxDiv.id = map.parent.id + '-boxselector-box';
boxDiv.className = 'boxselector-box';
map.parent.appendChild(boxDiv);
style = boxDiv.style;
borderWidth = parseInt(window.getComputedStyle(boxDiv).borderWidth, 10);
addEvent(map.parent, 'mousedown', mouseDown);
addEvent(boxDiv, 'mousedown', mouseDownResize);
addEvent(map.parent, 'mousemove', mouseMoveCursor);
map.addCallback('drawn', drawbox);
return this;
};
boxselector.remove = function() {
map.parent.removeChild(boxDiv);
removeEvent(map.parent, 'mousedown', mouseDown);
removeEvent(boxDiv, 'mousedown', mouseDownResize);
removeEvent(map.parent, 'mousemove', mouseMoveCursor);
map.removeCallback('drawn', drawbox);
};
return boxselector.add(map);
};
wax = wax || {};
wax.mm = wax.mm || {};
wax._ = {};
// Bandwidth Detection
// ------------------
wax.mm.bwdetect = function(map, options) {
options = options || {};
var lowpng = options.png || '.png128',
lowjpg = options.jpg || '.jpg70',
bw = false;
wax._.bw_png = lowpng;
wax._.bw_jpg = lowjpg;
return wax.bwdetect(options, function(x) {
wax._.bw = !x;
for (var i = 0; i < map.layers.length; i++) {
if (map.getLayerAt(i).provider instanceof wax.mm.connector) {
map.getLayerAt(i).setProvider(map.getLayerAt(i).provider);
}
}
});
};
wax = wax || {};
wax.mm = wax.mm || {};
// Fullscreen
// ----------
// A simple fullscreen control for Modest Maps
// Add zoom links, which can be styled as buttons, to a `modestmaps.Map`
// control. This function can be used chaining-style with other
// chaining-style controls.
wax.mm.fullscreen = function(map) {
// true: fullscreen
// false: minimized
var fullscreened = false,
fullscreen = {},
a,
body = document.body,
smallSize;
function click(e) {
if (e) e.stop();
if (fullscreened) {
fullscreen.original();
} else {
fullscreen.full();
}
}
function ss(w, h) {
map.dimensions = new MM.Point(w, h);
map.parent.style.width = Math.round(map.dimensions.x) + 'px';
map.parent.style.height = Math.round(map.dimensions.y) + 'px';
map.dispatchCallback('resized', map.dimensions);
}
// Modest Maps demands an absolute height & width, and doesn't auto-correct
// for changes, so here we save the original size of the element and
// restore to that size on exit from fullscreen.
fullscreen.add = function(map) {
a = document.createElement('a');
a.className = 'wax-fullscreen';
a.href = '#fullscreen';
a.innerHTML = 'fullscreen';
bean.add(a, 'click', click);
return this;
};
fullscreen.full = function() {
if (fullscreened) { return; } else { fullscreened = true; }
smallSize = [map.parent.offsetWidth, map.parent.offsetHeight];
map.parent.className += ' wax-fullscreen-map';
body.className += ' wax-fullscreen-view';
ss(map.parent.offsetWidth, map.parent.offsetHeight);
};
fullscreen.original = function() {
if (!fullscreened) { return; } else { fullscreened = false; }
map.parent.className = map.parent.className.replace(' wax-fullscreen-map', '');
body.className = body.className.replace(' wax-fullscreen-view', '');
ss(smallSize[0], smallSize[1]);
};
fullscreen.appendTo = function(elem) {
wax.u.$(elem).appendChild(a);
return this;
};
return fullscreen.add(map);
};
wax = wax || {};
wax.mm = wax.mm || {};
wax.mm.hash = function(map) {
return wax.hash({
getCenterZoom: function() {
var center = map.getCenter(),
zoom = map.getZoom(),
precision = Math.max(
0,
Math.ceil(Math.log(zoom) / Math.LN2));
return [zoom.toFixed(2),
center.lat.toFixed(precision),
center.lon.toFixed(precision)
].join('/');
},
setCenterZoom: function setCenterZoom(args) {
map.setCenterZoom(
new MM.Location(args[1], args[2]),
args[0]);
},
bindChange: function(fn) {
map.addCallback('drawn', fn);
},
unbindChange: function(fn) {
map.removeCallback('drawn', fn);
}
});
};
wax = wax || {};
wax.mm = wax.mm || {};
wax.mm.interaction = function() {
var dirty = false,
_grid,
map,
clearingEvents = ['zoomed', 'panned', 'centered',
'extentset', 'resized', 'drawn'];
function grid() {
var zoomLayer = map.getLayerAt(0)
.levels[Math.round(map.getZoom())];
if (!dirty && _grid !== undefined && _grid.length) {
return _grid;
} else {
_grid = (function(t) {
var o = [];
for (var key in t) {
if (t[key].parentNode === zoomLayer) {
var offset = wax.u.offset(t[key]);
o.push([
offset.top,
offset.left,
t[key]
]);
}
}
return o;
})(map.getLayerAt(0).tiles);
return _grid;
}
}
function setdirty() { dirty = true; }
function attach(x) {
if (!arguments.length) return map;
map = x;
for (var i = 0; i < clearingEvents.length; i++) {
map.addCallback(clearingEvents[i], setdirty);
}
}
function detach(x) {
for (var i = 0; i < clearingEvents.length; i++) {
map.removeCallback(clearingEvents[i], setdirty);
}
}
return wax.interaction()
.attach(attach)
.detach(detach)
.parent(function() {
return map.parent;
})
.grid(grid);
};
wax = wax || {};
wax.mm = wax.mm || {};
// LatLng
// ------
// Show the current cursor position in
// lat/long
wax.mm.latlngtooltip = function(map) {
var tt, // tooltip
_down = false,
latlng = {};
function getMousePoint(e) {
// start with just the mouse (x, y)
var point = new MM.Point(e.clientX, e.clientY);
// correct for scrolled document
point.x += document.body.scrollLeft + document.documentElement.scrollLeft;
point.y += document.body.scrollTop + document.documentElement.scrollTop;
// correct for nested offsets in DOM
for (var node = map.parent; node; node = node.offsetParent) {
point.x -= node.offsetLeft;
point.y -= node.offsetTop;
}
return point;
}
function onDown(e) {
console.log('here');
_down = true;
}
function onUp(e) {
_down = false;
}
function onMove(e) {
if (!e.shiftKey || _down) {
if (tt.parentNode === map.parent) {
map.parent.removeChild(tt);
}
return;
}
var pt = getMousePoint(e),
ll = map.pointLocation(pt),
fmt = ll.lat.toFixed(2) + ', ' + ll.lon.toFixed(2);
tt.innerHTML = fmt;
pt.scale = pt.width = pt.height = 1;
pt.x += 10;
MM.moveElement(tt, pt);
map.parent.appendChild(tt);
}
latlng.add = function() {
MM.addEvent(map.parent, 'mousemove', onMove);
MM.addEvent(map.parent, 'mousedown', onDown);
MM.addEvent(map.parent, 'mouseup', onUp);
tt = document.createElement('div');
tt.className = 'wax-latlngtooltip';
return this;
};
latlng.remove = function() {
MM.removeEvent(map.parent, 'mousemove', onMove);
MM.removeEvent(map.parent, 'mousedown', onDown);
MM.removeEvent(map.parent, 'mouseup', onUp);
return this;
};
return latlng.add();
};
wax = wax || {};
wax.mm = wax.mm || {};
// Legend Control
// --------------
// The Modest Maps version of this control is a very, very
// light wrapper around the `/lib` code for legends.
wax.mm.legend = function(map, tilejson) {
tilejson = tilejson || {};
var l, // parent legend
legend = {};
legend.add = function() {
l = wax.legend()
.content(tilejson.legend || '');
return this;
};
legend.content = function(x) {
if (x) l.content(x.legend || '');
};
legend.element = function() {
return l.element();
};
legend.appendTo = function(elem) {
wax.u.$(elem).appendChild(l.element());
return this;
};
return legend.add();
};
wax = wax || {};
wax.mm = wax.mm || {};
// Point Selector
// --------------
//
// This takes an object of options:
//
// * `callback`: a function called with an array of `com.modestmaps.Location`
// objects when the map is edited
//
// It also exposes a public API function: `addLocation`, which adds a point
// to the map as if added by the user.
wax.mm.pointselector = function(map, tilejson, opts) {
var mouseDownPoint = null,
mouseUpPoint = null,
tolerance = 5,
overlayDiv,
pointselector = {},
locations = [];
var callback = (typeof opts === 'function') ?
opts :
opts.callback;
// Create a `com.modestmaps.Point` from a screen event, like a click.
function makePoint(e) {
var coords = wax.u.eventoffset(e);
var point = new MM.Point(coords.x, coords.y);
// correct for scrolled document
// and for the document
var body = {
x: parseFloat(MM.getStyle(document.documentElement, 'margin-left')),
y: parseFloat(MM.getStyle(document.documentElement, 'margin-top'))
};
if (!isNaN(body.x)) point.x -= body.x;
if (!isNaN(body.y)) point.y -= body.y;
// TODO: use wax.util.offset
// correct for nested offsets in DOM
for (var node = map.parent; node; node = node.offsetParent) {
point.x -= node.offsetLeft;
point.y -= node.offsetTop;
}
return point;
}
// Currently locations in this control contain circular references to elements.
// These can't be JSON encoded, so here's a utility to clean the data that's
// spit back.
function cleanLocations(locations) {
var o = [];
for (var i = 0; i < locations.length; i++) {
o.push(new MM.Location(locations[i].lat, locations[i].lon));
}
return o;
}
// Attach this control to a map by registering callbacks
// and adding the overlay
// Redraw the points when the map is moved, so that they stay in the
// correct geographic locations.
function drawPoints() {
var offset = new MM.Point(0, 0);
for (var i = 0; i < locations.length; i++) {
var point = map.locationPoint(locations[i]);
if (!locations[i].pointDiv) {
locations[i].pointDiv = document.createElement('div');
locations[i].pointDiv.className = 'wax-point-div';
locations[i].pointDiv.style.position = 'absolute';
locations[i].pointDiv.style.display = 'block';
// TODO: avoid circular reference
locations[i].pointDiv.location = locations[i];
// Create this closure once per point
bean.add(locations[i].pointDiv, 'mouseup',
(function selectPointWrap(e) {
var l = locations[i];
return function(e) {
MM.removeEvent(map.parent, 'mouseup', mouseUp);
pointselector.deleteLocation(l, e);
};
})());
map.parent.appendChild(locations[i].pointDiv);
}
locations[i].pointDiv.style.left = point.x + 'px';
locations[i].pointDiv.style.top = point.y + 'px';
}
}
function mouseDown(e) {
mouseDownPoint = makePoint(e);
bean.add(map.parent, 'mouseup', mouseUp);
}
// Remove the awful circular reference from locations.
// TODO: This function should be made unnecessary by not having it.
function mouseUp(e) {
if (!mouseDownPoint) return;
mouseUpPoint = makePoint(e);
if (MM.Point.distance(mouseDownPoint, mouseUpPoint) < tolerance) {
pointselector.addLocation(map.pointLocation(mouseDownPoint));
callback(cleanLocations(locations));
}
mouseDownPoint = null;
}
// API for programmatically adding points to the map - this
// calls the callback for ever point added, so it can be symmetrical.
// Useful for initializing the map when it's a part of a form.
pointselector.addLocation = function(location) {
locations.push(location);
drawPoints();
callback(cleanLocations(locations));
};
pointselector.locations = function(x) {
return locations;
};
pointselector.add = function(map) {
bean.add(map.parent, 'mousedown', mouseDown);
map.addCallback('drawn', drawPoints);
return this;
};
pointselector.remove = function(map) {
bean.remove(map.parent, 'mousedown', mouseDown);
map.removeCallback('drawn', drawPoints);
for (var i = locations.length - 1; i > -1; i--) {
pointselector.deleteLocation(locations[i]);
}
return this;
};
pointselector.deleteLocation = function(location, e) {
if (!e || confirm('Delete this point?')) {
location.pointDiv.parentNode.removeChild(location.pointDiv);
locations.splice(wax.u.indexOf(locations, location), 1);
callback(cleanLocations(locations));
}
};
return pointselector.add(map);
};
wax = wax || {};
wax.mm = wax.mm || {};
// ZoomBox
// -------
// An OL-style ZoomBox control, from the Modest Maps example.
wax.mm.zoombox = function(map) {
// TODO: respond to resize
var zoombox = {},
drawing = false,
box,
mouseDownPoint = null;
function getMousePoint(e) {
// start with just the mouse (x, y)
var point = new MM.Point(e.clientX, e.clientY);
// correct for scrolled document
point.x += document.body.scrollLeft + document.documentElement.scrollLeft;
point.y += document.body.scrollTop + document.documentElement.scrollTop;
// correct for nested offsets in DOM
for (var node = map.parent; node; node = node.offsetParent) {
point.x -= node.offsetLeft;
point.y -= node.offsetTop;
}
return point;
}
function mouseUp(e) {
if (!drawing) return;
drawing = false;
var point = getMousePoint(e);
var l1 = map.pointLocation(point),
l2 = map.pointLocation(mouseDownPoint);
map.setExtent([l1, l2]);
box.style.display = 'none';
MM.removeEvent(map.parent, 'mousemove', mouseMove);
MM.removeEvent(map.parent, 'mouseup', mouseUp);
map.parent.style.cursor = 'auto';
}
function mouseDown(e) {
if (!(e.shiftKey && !this.drawing)) return;
drawing = true;
mouseDownPoint = getMousePoint(e);
box.style.left = mouseDownPoint.x + 'px';
box.style.top = mouseDownPoint.y + 'px';
MM.addEvent(map.parent, 'mousemove', mouseMove);
MM.addEvent(map.parent, 'mouseup', mouseUp);
map.parent.style.cursor = 'crosshair';
return MM.cancelEvent(e);
}
function mouseMove(e) {
if (!drawing) return;
var point = getMousePoint(e);
box.style.display = 'block';
if (point.x < mouseDownPoint.x) {
box.style.left = point.x + 'px';
} else {
box.style.left = mouseDownPoint.x + 'px';
}
box.style.width = Math.abs(point.x - mouseDownPoint.x) + 'px';
if (point.y < mouseDownPoint.y) {
box.style.top = point.y + 'px';
} else {
box.style.top = mouseDownPoint.y + 'px';
}
box.style.height = Math.abs(point.y - mouseDownPoint.y) + 'px';
return MM.cancelEvent(e);
}
zoombox.add = function(map) {
// Use a flag to determine whether the zoombox is currently being
// drawn. Necessary only for IE because `mousedown` is triggered
// twice.
box = box || document.createElement('div');
box.id = map.parent.id + '-zoombox-box';
box.className = 'zoombox-box';
map.parent.appendChild(box);
MM.addEvent(map.parent, 'mousedown', mouseDown);
return this;
};
zoombox.remove = function() {
map.parent.removeChild(box);
MM.removeEvent(map.parent, 'mousedown', mouseDown);
};
return zoombox.add(map);
};
wax = wax || {};
wax.mm = wax.mm || {};
// Zoomer
// ------
// Add zoom links, which can be styled as buttons, to a `modestmaps.Map`
// control. This function can be used chaining-style with other
// chaining-style controls.
wax.mm.zoomer = function(map) {
var zoomin = document.createElement('a');
zoomin.innerHTML = '+';
zoomin.href = '#';
zoomin.className = 'zoomer zoomin';
bean.add(zoomin, 'mousedown dblclick', function(e) {
e.stop();
});
bean.add(zoomin, 'click', function(e) {
e.stop();
map.zoomIn();
}, false);
var zoomout = document.createElement('a');
zoomout.innerHTML = '-';
zoomout.href = '#';
zoomout.className = 'zoomer zoomout';
bean.add(zoomout, 'mousedown dblclick', function(e) {
e.stop();
});
bean.add(zoomout, 'click', function(e) {
e.stop();
map.zoomOut();
});
var zoomer = {
add: function(map) {
map.addCallback('drawn', function(map, e) {
if (map.coordinate.zoom === map.coordLimits[0].zoom) {
zoomout.className = 'zoomer zoomout zoomdisabled';
} else if (map.coordinate.zoom === map.coordLimits[1].zoom) {
zoomin.className = 'zoomer zoomin zoomdisabled';
} else {
zoomin.className = 'zoomer zoomin';
zoomout.className = 'zoomer zoomout';
}
});
return this;
},
appendTo: function(elem) {
wax.u.$(elem).appendChild(zoomin);
wax.u.$(elem).appendChild(zoomout);
return this;
}
};
return zoomer.add(map);
};
var wax = wax || {};
wax.mm = wax.mm || {};
// A layer connector for Modest Maps conformant to TileJSON
// https://github.com/mapbox/tilejson
wax.mm._provider = function(options) {
this.options = {
tiles: options.tiles,
scheme: options.scheme || 'xyz',
minzoom: options.minzoom || 0,
maxzoom: options.maxzoom || 22,
bounds: options.bounds || [-180, -90, 180, 90]
};
};
wax.mm._provider.prototype = {
outerLimits: function() {
return [
this.locationCoordinate(
new MM.Location(
this.options.bounds[0],
this.options.bounds[1])).zoomTo(this.options.minzoom),
this.locationCoordinate(
new MM.Location(
this.options.bounds[2],
this.options.bounds[3])).zoomTo(this.options.maxzoom)
];
},
getTile: function(c) {
if (!(coord = this.sourceCoordinate(c))) return null;
if (coord.zoom < this.options.minzoom || coord.zoom > this.options.maxzoom) return null;
coord.row = (this.options.scheme === 'tms') ?
Math.pow(2, coord.zoom) - coord.row - 1 :
coord.row;
var u = this.options.tiles[parseInt(Math.pow(2, coord.zoom) * coord.row + coord.column, 10) %
this.options.tiles.length]
.replace('{z}', coord.zoom.toFixed(0))
.replace('{x}', coord.column.toFixed(0))
.replace('{y}', coord.row.toFixed(0));
if (wax._ && wax._.bw) {
u = u.replace('.png', wax._.bw_png)
.replace('.jpg', wax._.bw_jpg);
}
return u;
}
};
if (MM) {
MM.extend(wax.mm._provider, MM.MapProvider);
}
wax.mm.connector = function(options) {
var x = new wax.mm._provider(options);
return new MM.Layer(x);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment