Pen Settings



CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource


Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource


Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.


Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.


                <!DOCTYPE html>

  <meta charset="utf-8" />
  <title>TravelTime Tiles</title>
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
  <script src=""></script>
  <link href="" rel="stylesheet" />

  <div id="legend">
    <div class="instrct">
        <li>You can click on route line to add additional points</li>
        <li>You can select transport mode and it will be displayed if it is available</li>
        <li>You can drag location markers (origin/destination) points</li>
        <li>You can enable range search and specify search range in seconds within 12 hours</li>
      Transport mode:
      <input type="radio" name="transportMode" onchange="refreshLines()" value="cycling">Cycling<br>
      <input type="radio" name="transportMode" onchange="refreshLines()" value="driving">Driving<br>
      <input type="radio" name="transportMode" onchange="refreshLines()" checked="checked"
        value="public_transport">Public transport<br>
      <input type="radio" name="transportMode" onchange="refreshLines()" value="walking">Walking<br>
      <input type="radio" name="transportMode" onchange="refreshLines()" value="coach">Coach<br>
      <input type="radio" name="transportMode" onchange="refreshLines()" value="train">Train<br>
      <input type="radio" name="transportMode" onchange="refreshLines()" value="ferry">Ferry<br>
      <input type="radio" name="transportMode" onchange="refreshLines()" value="driving+ferry">Driving + ferry<br>
      <input type="radio" name="transportMode" onchange="refreshLines()" value="cycling+ferry">Cycling + ferry<br>
      <input type="radio" name="transportMode" onchange="refreshLines()" value="cycling+public_transport">Cycling +
      public transport<br>
      Range search
      <input type="checkbox" name="rangeEnable" id="rangeCheckbox" onchange="refreshLines()">Enable range search<br>
      <input type="number" id="rangeValue" min="1" max"43200" onchange="refreshLines()" value="1"> Second(s)
      Transport navigation legend:
      <span style="background-color: #fc5c65;"> </span> Bus
      <span style="background-color: #2bcbba;"> </span> Walk
      <span style="background-color: #778ca3;"> </span> Other
      <span style="background-color: #3867d6;"> </span> Rail
      <span style="background-color: #a55eea;"> </span> Underground
      <span style="background-color: #45aaf2;"> </span> Car
      @ Travel time platform | OpenStreetMap
  <div id="map"></div>



                body {
  margin: 0;
  padding: 0;

#map {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;

.mapboxgl-popup {
  max-width: 400px;
  font: 12px/20px "Helvetica Neue", Arial, Helvetica, sans-serif;

#legend {
  position: fixed;
  bottom: 10px;
  left: 10px;
  z-index: 900;
  background-color: white;
  padding: 10px;
  margin: 10px;
  height: Calc(100% - 60px);
  overflow-y: auto;

#legend div > span {
  width: 20px;
  height: 20px;
  display: inline-block;

.instrct {
  max-width: 350px;

.instrct ul {
  padding-inline-start: 15px;

#rangeValue {
  width: 80px;


                var busColor = "#fc5c65";
var walkColor = "#2bcbba";
var otherColor = "#778ca3";
var railColor = "#3867d6";
var undergroundColor = "#a55eea";
var carColor = "#45aaf2";

function getTransportMode() {
  return document.querySelector('input[name="transportMode"]:checked').value;

function loadData(start, end, pairName) {
  var rangeEnabled = document.querySelector('#rangeCheckbox').checked;
  var rangeValue = document.querySelector('#rangeValue').value;
  pairName || (pairName = "not_set");
  map.getLayer(pairName) && map.removeLayer(pairName);
  var requestData = JSON.stringify({
    locations: [
        id: "Start",
        coords: start
        id: "End",
        coords: end
    departure_searches: [
        id: "departure search example",
        departure_location_id: "Start",
        arrival_location_ids: ["End"],
        transportation: {
          type: getTransportMode()
        departure_time: new Date().toISOString(),
        properties: ["travel_time", "distance", "route"],
        range: {
          enabled: rangeEnabled,
          max_results: 1,
          width: parseInt(rangeValue)
  var xhr = new XMLHttpRequest();
  xhr.addEventListener("readystatechange", function() {
    if (this.readyState === 4) {
      parseAndLoadLines(JSON.parse(this.response), pairName);
  });"POST", "");
  xhr.setRequestHeader("Content-Type", "application/json");
  xhr.setRequestHeader("Accept", "application/json");
  xhr.setRequestHeader("X-Application-Id", "APP ID HERE");
  xhr.setRequestHeader("X-Api-Key", "API KEY HERE");
var map = new mapboxgl.Map({
  container: "map",
  style: {
'version': 8,
'sources': {
'raster-tiles': {
'type': 'raster',
'tiles': [
'{z}/{x}/{y}.png?key=APP ID HERE'
'tileSize': 256,
'Map tiles by <a target="_top" rel="noopener" href="">Stamen Design</a>, under <a target="_top" rel="noopener" href="">CC BY 3.0</a>. Data by <a target="_top" rel="noopener" href="">OpenStreetMap</a>, under <a target="_top" rel="noopener" href="">CC BY SA</a>'
'layers': [
'id': 'simple-tiles',
'type': 'raster',
'source': 'raster-tiles',
'minzoom': 0,
'maxzoom': 22
  center: [13.352798436541264, 52.51307448201544],
  zoom: 15,
  attributionControl: false

map.on("load", function() {

for (let index = 0; index < 10; index++) {
  map.on("click", "pair_" + index, function(e) {
    var marker = addMarker(e.lngLat.lng,;
    var name = "pair_" + index;
    var aMarker = pairs[index][0];
    var bMarker = pairs[index][1];
    pairs.splice(index + 1, 0, [marker, aMarker]);
    pairs[index] = [bMarker, marker];

function addMarker(lng, lat) {
  var marker = new mapboxgl.Marker({
    draggable: true
    .setLngLat([lng, lat])
  marker.on("dragend", e => refreshLines());
  return marker;

var markers = [
  addMarker(13.339723415070296, 52.515636259501576),
  addMarker(13.36456681231744, 52.51768082692038)
var pairs = [[markers[0], markers[1]]];

function refreshLines() {
  for (var pairI in pairs) {
      "pair_" + pairI

function parseAndLoadLines(response, pairName) {
  var parsed = apiResponseToLineStrings(response);
  loadLines(parsed, pairName);

function apiResponseToLineStrings(response) {
  var location = response.results[0].locations[0];
  if (!location) {
    var mode = getTransportMode();
    alert(`No route available for transport mode: '${mode}'`);
  var id =;
  var properties =[0];
  var travelTime = properties.travel_time;
  var route = properties.route;
  var lineStrings = => {
    var coords = part.coords;
    var coordsAsArrays = => {
      return [coord.lng,];
    var mode = part.mode;
    return {
      type: "Feature",
      properties: {
        color: modeToColor(mode),
        mode: mode
      geometry: {
        type: "LineString",
        coordinates: coordsAsArrays
  return {
    type: "FeatureCollection",
    features: lineStrings

function loadLines(parsed, pairName) {
  map.getSource(pairName) && map.removeSource(pairName);
  map.addSource(pairName, {
    type: "geojson",
    data: parsed
    id: pairName,
    type: "line",
    source: pairName,
    layout: {
      "line-join": "round",
      "line-cap": "round"
    paint: {
      "line-color": ["get", "color"],
      "line-width": 9
  map.on("mouseenter", "LineString", function() {
    map.getCanvas().style.cursor = "pointer";
  map.on("mouseleave", "LineString", function() {
    map.getCanvas().style.cursor = "";

function modeToColor(mode) {
  switch (mode) {
    case "walk":
      return walkColor;
    case "bus":
    case "coach":
      return busColor;
    case "rail_overground":
    case "train":
    case "rail_national":
    case "rail_dlr":
      return railColor;
    case "rail_underground":
      return undergroundColor;
    case "car":
    case "parking":
      return carColor;
      return otherColor;