commit
84d81a7827
9 changed files with 412 additions and 54 deletions
|
|
@ -54,7 +54,11 @@ Copyright 2012 Jacob Toye; [MIT License](https://github.com/Leaflet/Leaflet.draw
|
||||||
Copyright (c) 2013 Stefano Cudini; [MIT License](https://github.com/stefanocudini/leaflet-search/blob/master/LICENSE.txt)
|
Copyright (c) 2013 Stefano Cudini; [MIT License](https://github.com/stefanocudini/leaflet-search/blob/master/LICENSE.txt)
|
||||||
* [leaflet-plugins](https://github.com/shramov/leaflet-plugins)
|
* [leaflet-plugins](https://github.com/shramov/leaflet-plugins)
|
||||||
Copyright (c) 2011-2012, Pavel Shramov; [2-clause BSD License](https://github.com/shramov/leaflet-plugins/blob/master/LICENSE)
|
Copyright (c) 2011-2012, Pavel Shramov; [2-clause BSD License](https://github.com/shramov/leaflet-plugins/blob/master/LICENSE)
|
||||||
* [normalize.css](https://github.com/necolas/normalize.css)
|
|
||||||
Copyright (c) Nicolas Gallagher and Jonathan Neal; [MIT License](https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
|
||||||
* [Async.js](https://github.com/caolan/async)
|
* [Async.js](https://github.com/caolan/async)
|
||||||
Copyright (c) 2010-2014 Caolan McMahon; [MIT License](https://github.com/caolan/async/blob/master/LICENSE)
|
Copyright (c) 2010-2014 Caolan McMahon; [MIT License](https://github.com/caolan/async/blob/master/LICENSE)
|
||||||
|
* [Bootstrap](http://getbootstrap.com/)
|
||||||
|
Copyright (c) 2011-2014 Twitter, Inc; [MIT License](https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||||
|
* [jQuery](https://github.com/jquery/jquery)
|
||||||
|
Copyright 2005, 2014 jQuery Foundation and other contributors; [MIT License](https://github.com/jquery/jquery/blob/master/LICENSE.txt)
|
||||||
|
* [DataTables](https://github.com/DataTables/DataTables)
|
||||||
|
Copyright (C) 2008-2014, SpryMedia Ltd.; [MIT License](http://www.datatables.net/license/mit)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
"bower_components"
|
"bower_components"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"normalize-css": "*",
|
|
||||||
"leaflet-search": "*",
|
"leaflet-search": "*",
|
||||||
"leaflet-plugins": "*",
|
"leaflet-plugins": "*",
|
||||||
"leaflet-routing": "nrenner/leaflet-routing#styles",
|
"leaflet-routing": "nrenner/leaflet-routing#styles",
|
||||||
|
|
|
||||||
113
css/style.css
113
css/style.css
|
|
@ -15,11 +15,6 @@ html, body, #map {
|
||||||
div.elevation {
|
div.elevation {
|
||||||
margin-bottom: -2px !important;
|
margin-bottom: -2px !important;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
.info, div.elevation {
|
|
||||||
display:table-row;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
@ -44,8 +39,6 @@ div.elevation {
|
||||||
}
|
}
|
||||||
.title {
|
.title {
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
/* normalize height, for absolute Profile control positioning */
|
|
||||||
height: 17px;
|
|
||||||
}
|
}
|
||||||
.title-name {
|
.title-name {
|
||||||
font-size: larger;
|
font-size: larger;
|
||||||
|
|
@ -75,8 +68,6 @@ div.elevation {
|
||||||
|
|
||||||
select {
|
select {
|
||||||
max-width: 176px;
|
max-width: 176px;
|
||||||
/* normalize height, for absolute Profile control positioning */
|
|
||||||
height: 24px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
|
|
@ -121,32 +112,56 @@ td {
|
||||||
|
|
||||||
.leaflet-leftpane .leaflet-control {
|
.leaflet-leftpane .leaflet-control {
|
||||||
margin: 3px 5px;
|
margin: 3px 5px;
|
||||||
width: 370px;
|
width: 386px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Profile Control */
|
/* Profile Control */
|
||||||
|
|
||||||
.leaflet-leftpane .leaflet-control:last-child {
|
/* flexbox layout: maximize textarea and data table (nested container/box path) */
|
||||||
position: absolute;
|
.flex_container,
|
||||||
top: 461px;
|
.leaflet-leftpane,
|
||||||
bottom: 0px;
|
.leaflet-leftpane .leaflet-control:last-child,
|
||||||
|
#tabs_div,
|
||||||
|
.tab-content,
|
||||||
|
.tab-pane.active,
|
||||||
|
#profile_upload,
|
||||||
|
#datatable_wrapper,
|
||||||
|
.dataTables_scroll,
|
||||||
|
.dataTables_scrollBody {
|
||||||
|
display: -webkit-flex;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
-webkit-flex-direction: column;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
#profile_upload input {
|
.flex_box_none,
|
||||||
position: absolute;
|
.leaflet-leftpane .leaflet-control,
|
||||||
top: 6px;
|
#tab,
|
||||||
right: 8px;
|
.dataTables_scrollHead {
|
||||||
|
-webkit-flex: none;
|
||||||
|
flex: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* http://snook.ca/archives/html_and_css/absolute-position-textarea */
|
.flex_box,
|
||||||
#textarea_container {
|
.leaflet-leftpane .leaflet-control:last-child,
|
||||||
position: absolute;
|
#tabs_div,
|
||||||
top: 32px;
|
.tab-content,
|
||||||
bottom: 6px;
|
.tab-pane.active,
|
||||||
left: 8px;
|
#profile_upload,
|
||||||
right: 8px;
|
textarea,
|
||||||
|
#datatable_wrapper,
|
||||||
|
.dataTables_scroll,
|
||||||
|
.dataTables_scrollBody,
|
||||||
|
#datatable {
|
||||||
|
-webkit-flex: auto;
|
||||||
|
flex: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#profile_buttons {
|
||||||
|
padding-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
@ -162,6 +177,11 @@ textarea:focus {
|
||||||
background-color: rgba(255,255,255,255);
|
background-color: rgba(255,255,255,255);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* track messages (data tab) */
|
||||||
|
#tab_data {
|
||||||
|
font-size: x-small;
|
||||||
|
}
|
||||||
|
|
||||||
/* dashed line animation, derived from Chris Coyier and others
|
/* dashed line animation, derived from Chris Coyier and others
|
||||||
http://css-tricks.com/svg-line-animation-works/
|
http://css-tricks.com/svg-line-animation-works/
|
||||||
*/
|
*/
|
||||||
|
|
@ -185,3 +205,44 @@ textarea:focus {
|
||||||
stroke-dashoffset: 0;
|
stroke-dashoffset: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bootstrap
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* override Bootstrap label for Leaflet layer switcher */
|
||||||
|
.leaflet-control-layers label {
|
||||||
|
max-width: none;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
font-weight: normal;
|
||||||
|
/* normalize label height
|
||||||
|
| Firefox | Chrome |
|
||||||
|
Leaflet only | 21 | 20 |
|
||||||
|
Bootstrap | 23 | 22 |*/
|
||||||
|
height: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* smaller tab height */
|
||||||
|
.nav > li > a {
|
||||||
|
padding: 2px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DataTables
|
||||||
|
*/
|
||||||
|
|
||||||
|
table.dataTable.mini thead th,
|
||||||
|
table.dataTable.mini thead td {
|
||||||
|
padding: 3px 13px 3px 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.dataTable.mini tbody th,
|
||||||
|
table.dataTable.mini tbody td {
|
||||||
|
padding: 2px 2px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
table.dataTable thead .sorting_asc,
|
||||||
|
table.dataTable thead .sorting_desc,
|
||||||
|
table.dataTable thead .sorting {
|
||||||
|
background-position: center right -3px;
|
||||||
|
}
|
||||||
|
|
|
||||||
42
index.html
42
index.html
|
|
@ -2,6 +2,8 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>BRouter web client</title>
|
<title>BRouter web client</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
|
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
|
||||||
|
|
@ -12,7 +14,9 @@
|
||||||
<link rel="stylesheet" href="bower_components/Leaflet.Elevation/dist/Leaflet.Elevation-0.0.2.css" />
|
<link rel="stylesheet" href="bower_components/Leaflet.Elevation/dist/Leaflet.Elevation-0.0.2.css" />
|
||||||
<link rel="stylesheet" href="bower_components/leaflet-search/dist/leaflet-search.min.css" />
|
<link rel="stylesheet" href="bower_components/leaflet-search/dist/leaflet-search.min.css" />
|
||||||
<link rel="stylesheet" href="css/leaflet-routing.css" />
|
<link rel="stylesheet" href="css/leaflet-routing.css" />
|
||||||
<link rel="stylesheet" href="bower_components/normalize-css/normalize.css" />
|
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
|
||||||
|
<link rel="stylesheet" type="text/css" href="http://cdn.datatables.net/1.10.2/css/jquery.dataTables.css">
|
||||||
<link rel="stylesheet" href="css/style.css" />
|
<link rel="stylesheet" href="css/style.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -47,15 +51,28 @@
|
||||||
</td></tr>
|
</td></tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div id="profile_div" class="hidden">
|
<div id="tabs_div" class="hidden">
|
||||||
<form id="profile_upload" name="profile_upload">
|
|
||||||
<button id="clear">Clear</button>
|
<ul id="tab" class="nav nav-tabs" role="tablist">
|
||||||
<a href="http://brouter.de/brouter/costfunctions.html" target="_blank">Help</a>
|
<li class="active"><a href="#tab_profile" role="tab">Profile</a></li>
|
||||||
<input type="submit" value="Upload" />
|
<li><a href="#tab_data" role="tab">Data</a></li>
|
||||||
<div id="textarea_container">
|
</ul>
|
||||||
<textarea type="text" name="profile" spellcheck="false" wrap="off" maxlength="100000" placeholder="... paste your custom routing profile here ..."></textarea>
|
|
||||||
|
<div class="tab-content">
|
||||||
|
<div class="tab-pane active" id="tab_profile">
|
||||||
|
<form id="profile_upload" name="profile_upload">
|
||||||
|
<textarea type="text" name="profile" spellcheck="false" wrap="off" maxlength="100000" placeholder="... paste your custom routing profile here ..."></textarea>
|
||||||
|
<div id="profile_buttons">
|
||||||
|
<button id="upload" type="button" class="btn btn-default btn-xs" data-uploading-text="Uploading..."><span class="glyphicon glyphicon-upload"></span> Upload</button>
|
||||||
|
<button id="clear" type="button" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-ban-circle"></span> Clear</button>
|
||||||
|
<a href="http://brouter.de/brouter/costfunctions.html" target="_blank" class="btn-xs">Help</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
<div class="tab-pane" id="tab_data">
|
||||||
|
<table id="datatable" class="table mini cell-border hover stripe"></table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet-src.js"></script>
|
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet-src.js"></script>
|
||||||
|
|
@ -80,6 +97,11 @@
|
||||||
<script src="bower_components/Leaflet.Elevation/src/L.Control.Elevation.js"></script>
|
<script src="bower_components/Leaflet.Elevation/src/L.Control.Elevation.js"></script>
|
||||||
<script src="bower_components/async/lib/async.js"></script>
|
<script src="bower_components/async/lib/async.js"></script>
|
||||||
|
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
|
||||||
|
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
|
||||||
|
|
||||||
|
<script src="http://cdn.datatables.net/1.10.2/js/jquery.dataTables.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// global package prefix for BRouter web application
|
// global package prefix for BRouter web application
|
||||||
BR = {};
|
BR = {};
|
||||||
|
|
@ -95,7 +117,9 @@
|
||||||
<script src="js/plugin/Permalink.Routing.js"></script>
|
<script src="js/plugin/Permalink.Routing.js"></script>
|
||||||
<script src="js/control/TrackStats.js"></script>
|
<script src="js/control/TrackStats.js"></script>
|
||||||
<script src="js/control/Download.js"></script>
|
<script src="js/control/Download.js"></script>
|
||||||
|
<script src="js/control/Tabs.js"></script>
|
||||||
<script src="js/control/Profile.js"></script>
|
<script src="js/control/Profile.js"></script>
|
||||||
|
<script src="js/control/TrackMessages.js"></script>
|
||||||
<script src="js/control/RoutingOptions.js"></script>
|
<script src="js/control/RoutingOptions.js"></script>
|
||||||
<script src="js/control/Message.js"></script>
|
<script src="js/control/Message.js"></script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,33 @@
|
||||||
BR.Profile = BR.Control.extend({
|
BR.Profile = L.Class.extend({
|
||||||
options: {
|
initialize: function () {
|
||||||
heading: 'Profile',
|
L.DomUtil.get('upload').onclick = L.bind(this._upload, this);
|
||||||
divId: 'profile_div'
|
|
||||||
},
|
|
||||||
|
|
||||||
onAdd: function (map) {
|
|
||||||
L.DomUtil.get('profile_upload').onsubmit = L.bind(this._submit, this);
|
|
||||||
L.DomUtil.get('clear').onclick = L.bind(this.clear, this);
|
L.DomUtil.get('clear').onclick = L.bind(this.clear, this);
|
||||||
|
|
||||||
|
|
||||||
return BR.Control.prototype.onAdd.call(this, map);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
clear: function(evt) {
|
clear: function(evt) {
|
||||||
|
var button = evt.target || evt.srcElement;
|
||||||
|
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
document.profile_upload.profile.value = null;
|
document.profile_upload.profile.value = null;
|
||||||
|
|
||||||
this.fire('clear');
|
this.fire('clear');
|
||||||
|
button.blur();
|
||||||
},
|
},
|
||||||
|
|
||||||
_submit: function(evt) {
|
_upload: function(evt) {
|
||||||
var form = evt.target || evt.srcElement,
|
var button = evt.target || evt.srcElement,
|
||||||
profile = document.profile_upload.profile.value;
|
profile = document.profile_upload.profile.value;
|
||||||
|
|
||||||
|
$(button).button('uploading');
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
|
|
||||||
this.fire('update', { profileText: profile });
|
this.fire('update', {
|
||||||
|
profileText: profile,
|
||||||
|
callback: function () {
|
||||||
|
$(button).button('reset');
|
||||||
|
$(button).blur();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
42
js/control/Tabs.js
Normal file
42
js/control/Tabs.js
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
BR.Tabs = BR.Control.extend({
|
||||||
|
options: {
|
||||||
|
divId: 'tabs_div',
|
||||||
|
// tab a.hash > instance
|
||||||
|
tabs: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function (options) {
|
||||||
|
L.setOptions(this, options);
|
||||||
|
},
|
||||||
|
|
||||||
|
onAdd: function (map) {
|
||||||
|
var tabs = this.options.tabs;
|
||||||
|
|
||||||
|
for (var key in tabs) {
|
||||||
|
if (tabs[key].onAdd) {
|
||||||
|
tabs[key].onAdd(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#tab a').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$(this).tab('show');
|
||||||
|
});
|
||||||
|
|
||||||
|
// e.target = activated tab
|
||||||
|
// e.relatedTarget = previous tab
|
||||||
|
$('#tab a').on('shown.bs.tab', L.bind(function (e) {
|
||||||
|
var tab = this.options.tabs[e.target.hash],
|
||||||
|
prevTab = this.options.tabs[e.relatedTarget.hash];
|
||||||
|
|
||||||
|
if (tab && tab.show) {
|
||||||
|
tab.show();
|
||||||
|
}
|
||||||
|
if (prevTab && prevTab.hide) {
|
||||||
|
prevTab.hide();
|
||||||
|
}
|
||||||
|
}, this));
|
||||||
|
|
||||||
|
return BR.Control.prototype.onAdd.call(this, map);
|
||||||
|
}
|
||||||
|
});
|
||||||
201
js/control/TrackMessages.js
Normal file
201
js/control/TrackMessages.js
Normal file
|
|
@ -0,0 +1,201 @@
|
||||||
|
BR.TrackMessages = L.Class.extend({
|
||||||
|
|
||||||
|
options: {
|
||||||
|
edgeStyle: {
|
||||||
|
color: 'yellow',
|
||||||
|
weight: 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// true when tab is shown, false when hidden
|
||||||
|
active: false,
|
||||||
|
|
||||||
|
columnOptions: {
|
||||||
|
'Longitude': { visible: false },
|
||||||
|
'Latitude': { visible: false },
|
||||||
|
'Elevation': { title: 'elev.', className: 'dt-body-right' },
|
||||||
|
'Distance': { title: 'dist.', className: 'dt-body-right' },
|
||||||
|
'CostPerKm': { title: '$/km', className: 'dt-body-right' },
|
||||||
|
'ElevCost': { title: 'elev$', className: 'dt-body-right' },
|
||||||
|
'TurnCost': { title: 'turn$', className: 'dt-body-right' },
|
||||||
|
'NodeCost': { title: 'node$', className: 'dt-body-right' },
|
||||||
|
'InitialCost': { title: 'initial$', className: 'dt-body-right' },
|
||||||
|
'OsmTags': { title: 'tags'}
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function (options) {
|
||||||
|
L.setOptions(this, options);
|
||||||
|
|
||||||
|
var table = document.getElementById('datatable');
|
||||||
|
this.tableClassName = table.className;
|
||||||
|
this.tableParent = table.parentElement;
|
||||||
|
},
|
||||||
|
|
||||||
|
onAdd: function (map) {
|
||||||
|
this._map = map;
|
||||||
|
},
|
||||||
|
|
||||||
|
update: function (polyline, segments) {
|
||||||
|
var i, messages, columns, headings,
|
||||||
|
data = [];
|
||||||
|
|
||||||
|
if (!this.active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; segments && i < segments.length; i++) {
|
||||||
|
messages = segments[i].feature.properties.messages;
|
||||||
|
if (messages) {
|
||||||
|
data = data.concat(messages.slice(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._destroyTable();
|
||||||
|
|
||||||
|
if (data.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
headings = messages[0];
|
||||||
|
columns = this._getColumns(headings, data);
|
||||||
|
|
||||||
|
console.time('datatable');
|
||||||
|
this._table = $('#datatable').DataTable({
|
||||||
|
destroy: true,
|
||||||
|
data: data,
|
||||||
|
columns: columns,
|
||||||
|
paging: false,
|
||||||
|
searching: false,
|
||||||
|
info: false,
|
||||||
|
scrollY: 330,
|
||||||
|
scrollX: 370,
|
||||||
|
scrollCollapse: true,
|
||||||
|
order: []
|
||||||
|
});
|
||||||
|
|
||||||
|
// highlight track segment (graph edge) on row hover
|
||||||
|
this._setEdges(polyline, segments);
|
||||||
|
$('#datatable tbody tr').hover(L.bind(this._handleHover, this), L.bind(this._handleHoverOut, this));
|
||||||
|
|
||||||
|
console.timeEnd('datatable');
|
||||||
|
},
|
||||||
|
|
||||||
|
show: function() {
|
||||||
|
this.active = true;
|
||||||
|
this.options.requestUpdate(this);
|
||||||
|
},
|
||||||
|
|
||||||
|
hide: function() {
|
||||||
|
this.active = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_destroyTable: function() {
|
||||||
|
var ele;
|
||||||
|
|
||||||
|
if ($.fn.DataTable.isDataTable('#datatable') ) {
|
||||||
|
// destroy option too slow on update, really remove elements with destroy method
|
||||||
|
$('#datatable').DataTable().destroy(true);
|
||||||
|
|
||||||
|
// recreate original table element, destroy removes all
|
||||||
|
ele = document.createElement('table');
|
||||||
|
ele.id = 'datatable';
|
||||||
|
ele.className = this.tableClassName;
|
||||||
|
this.tableParent.appendChild(ele);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ele || document.getElementById('datatable');
|
||||||
|
},
|
||||||
|
|
||||||
|
_getColumns: function(headings, data) {
|
||||||
|
var columns = [],
|
||||||
|
defaultOptions,
|
||||||
|
options,
|
||||||
|
emptyColumns = this._getEmptyColumns(data);
|
||||||
|
|
||||||
|
for (k = 0; k < headings.length; k++) {
|
||||||
|
defaultOptions = {
|
||||||
|
title: headings[k],
|
||||||
|
visible: !emptyColumns[k]
|
||||||
|
};
|
||||||
|
options = L.extend(defaultOptions, this.columnOptions[headings[k]]);
|
||||||
|
columns.push(options);
|
||||||
|
}
|
||||||
|
return columns;
|
||||||
|
},
|
||||||
|
|
||||||
|
_getEmptyColumns: function(data) {
|
||||||
|
var empty = new Array(data[0].length),
|
||||||
|
i;
|
||||||
|
|
||||||
|
for (i = 0; i < empty.length; i++) {
|
||||||
|
empty[i] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.forEach(function(row) {
|
||||||
|
row.forEach(function(val, i) {
|
||||||
|
empty[i] = empty[i] && !val;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return empty;
|
||||||
|
},
|
||||||
|
|
||||||
|
_getMessageLatLng: function(message) {
|
||||||
|
var lon = message[0] / 1000000,
|
||||||
|
lat = message[1] / 1000000;
|
||||||
|
|
||||||
|
return L.latLng(lat, lon);
|
||||||
|
},
|
||||||
|
|
||||||
|
_setEdges: function(polyline, segments) {
|
||||||
|
var messages, segLatLngs, length, si, mi, latLng, i, segIndex,
|
||||||
|
baseIndex = 0;
|
||||||
|
|
||||||
|
// track latLngs index for end node of edge
|
||||||
|
this._edges = [];
|
||||||
|
this._track = polyline;
|
||||||
|
|
||||||
|
for (si = 0; si < segments.length; si++) {
|
||||||
|
messages = segments[si].feature.properties.messages;
|
||||||
|
segLatLngs = segments[si].getLatLngs();
|
||||||
|
length = segLatLngs.length;
|
||||||
|
segIndex = 0;
|
||||||
|
|
||||||
|
for (mi = 1; mi < messages.length; mi++) {
|
||||||
|
latLng = this._getMessageLatLng(messages[mi]);
|
||||||
|
|
||||||
|
for (i = segIndex; i < length; i++) {
|
||||||
|
if (latLng.equals(segLatLngs[i])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i === length) {
|
||||||
|
i = length - 1;
|
||||||
|
if (mi !== messages.length - 1) debugger;
|
||||||
|
}
|
||||||
|
|
||||||
|
segIndex = i + 1;
|
||||||
|
this._edges.push(baseIndex + i);
|
||||||
|
}
|
||||||
|
baseIndex += length;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleHover: function(evt) {
|
||||||
|
var tr = $(evt.currentTarget),
|
||||||
|
row = this._table.row(tr),
|
||||||
|
trackLatLngs = this._track.getLatLngs(),
|
||||||
|
startIndex = row.index() > 0 ? this._edges[row.index() - 1] : 0,
|
||||||
|
endIndex = this._edges[row.index()],
|
||||||
|
edgeLatLngs = trackLatLngs.slice(startIndex, endIndex + 1);
|
||||||
|
|
||||||
|
this._selectedEdge = L.polyline(edgeLatLngs, this.options.edgeStyle).addTo(this._map);
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleHoverOut: function(evt) {
|
||||||
|
this._map.removeLayer(this._selectedEdge);
|
||||||
|
this._selectedEdge = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
BR.TrackMessages.include(L.Mixin.Events);
|
||||||
27
js/index.js
27
js/index.js
|
|
@ -76,6 +76,10 @@
|
||||||
}).addTo(map);
|
}).addTo(map);
|
||||||
|
|
||||||
map.addControl(new BR.Search());
|
map.addControl(new BR.Search());
|
||||||
|
|
||||||
|
// expose map instance for console debugging
|
||||||
|
BR.debug = BR.debug || {};
|
||||||
|
BR.debug.map = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
function initApp() {
|
function initApp() {
|
||||||
|
|
@ -88,6 +92,7 @@
|
||||||
elevation,
|
elevation,
|
||||||
download,
|
download,
|
||||||
profile,
|
profile,
|
||||||
|
trackMessages,
|
||||||
leftPaneId = 'leftpane',
|
leftPaneId = 'leftpane',
|
||||||
saveWarningShown = false;
|
saveWarningShown = false;
|
||||||
|
|
||||||
|
|
@ -106,6 +111,13 @@
|
||||||
routing.rerouteAllSegments(onUpdate);
|
routing.rerouteAllSegments(onUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function requestUpdate(updatable) {
|
||||||
|
var track = routing.toPolyline(),
|
||||||
|
segments = routing.getSegments();
|
||||||
|
|
||||||
|
updatable.update(track, segments);
|
||||||
|
}
|
||||||
|
|
||||||
routingOptions = new BR.RoutingOptions();
|
routingOptions = new BR.RoutingOptions();
|
||||||
routingOptions.on('update', updateRoute);
|
routingOptions.on('update', updateRoute);
|
||||||
|
|
||||||
|
|
@ -134,12 +146,19 @@
|
||||||
router.setOptions(routingOptions.getOptions());
|
router.setOptions(routingOptions.getOptions());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (evt.callback) {
|
||||||
|
evt.callback();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
profile.on('clear', function(evt) {
|
profile.on('clear', function(evt) {
|
||||||
BR.message.hideError();
|
BR.message.hideError();
|
||||||
routingOptions.setCustomProfile(null);
|
routingOptions.setCustomProfile(null);
|
||||||
});
|
});
|
||||||
|
trackMessages = new BR.TrackMessages({
|
||||||
|
requestUpdate: requestUpdate
|
||||||
|
});
|
||||||
|
|
||||||
routing = new BR.Routing({
|
routing = new BR.Routing({
|
||||||
routing: {
|
routing: {
|
||||||
|
|
@ -177,6 +196,7 @@
|
||||||
|
|
||||||
elevation.update(track);
|
elevation.update(track);
|
||||||
stats.update(track, segments);
|
stats.update(track, segments);
|
||||||
|
trackMessages.update(track, segments);
|
||||||
|
|
||||||
if (latLngs.length > 1) {
|
if (latLngs.length > 1) {
|
||||||
urls.gpx = router.getUrl(latLngs, 'gpx');
|
urls.gpx = router.getUrl(latLngs, 'gpx');
|
||||||
|
|
@ -196,7 +216,12 @@
|
||||||
stats.addTo(map);
|
stats.addTo(map);
|
||||||
download.addTo(map);
|
download.addTo(map);
|
||||||
elevation.addTo(map);
|
elevation.addTo(map);
|
||||||
profile.addTo(map);
|
map.addControl(new BR.Tabs({
|
||||||
|
tabs: {
|
||||||
|
'#tab_profile': profile,
|
||||||
|
'#tab_data': trackMessages
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
nogos.addTo(map);
|
nogos.addTo(map);
|
||||||
routing.addTo(map);
|
routing.addTo(map);
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ BR.Routing = L.Routing.extend({
|
||||||
this._edit._mouseMarker.setIcon(L.divIcon({
|
this._edit._mouseMarker.setIcon(L.divIcon({
|
||||||
className: 'line-mouse-marker'
|
className: 'line-mouse-marker'
|
||||||
,iconAnchor: [8, 8] // size/2 + border/2
|
,iconAnchor: [8, 8] // size/2 + border/2
|
||||||
,iconSize: [8, 8]
|
,iconSize: [16, 16]
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this._draw.on('enabled', function() {
|
this._draw.on('enabled', function() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue