419 lines
16 KiB
JavaScript
419 lines
16 KiB
JavaScript
var API_BASE = "/1.0/",
|
|
map;
|
|
(function() {
|
|
$(function() {
|
|
initMap();
|
|
|
|
$('.tabButton').click(function() {
|
|
if ($(this).hasClass("selected")) {
|
|
return;
|
|
}
|
|
var $that = $(this);
|
|
var name = $that.attr("data-name");
|
|
var $listWrapper = $('#' + name);
|
|
if ($that.data("loaded")) {
|
|
|
|
$.noop(); //dont load data
|
|
} else {
|
|
$that.data("loaded", true);
|
|
var $list = $('#' + name + 'List');
|
|
var url = API_BASE + name + "/";
|
|
var $loadingLi = $('<div />').text("Loading...").appendTo($list);
|
|
$.getJSON(url, {'srid': 3857}, function(items) {
|
|
$loadingLi.remove();
|
|
$.each(items, function(i,v) {
|
|
var $li = $('<div />')
|
|
.addClass("listItem")
|
|
.appendTo($list);
|
|
var $txt = $('<span />').addClass("listItemText").text(v).appendTo($li);
|
|
});
|
|
});
|
|
}
|
|
|
|
$('.listWrapper').hide();
|
|
$listWrapper.show();
|
|
$('.selected').removeClass("selected");
|
|
$that.addClass("selected");
|
|
});
|
|
|
|
$('.list').click(function(e) {
|
|
var name = $(this).attr("id").replace("sList", ""); //FIXME: stick name in a data attr or so?
|
|
var $target = $(e.target).parent();
|
|
//console.log($target);
|
|
if (!$target.hasClass('listItem')) {
|
|
return;
|
|
}
|
|
if ($target.data("loading")) {
|
|
return;
|
|
}
|
|
if ($target.hasClass("selectedListItem")) {
|
|
$target.find(".stopsList").hide().remove();
|
|
$target.removeClass("selectedListItem");
|
|
return;
|
|
}
|
|
$('.selectedListItem').find(".stopsList").hide().remove();
|
|
$('.selectedListItem').removeClass("selectedListItem");
|
|
$target.addClass("selectedListItem");
|
|
|
|
if ($target.data("hasList")) {
|
|
var $stopsList = $target.find(".stopsList");
|
|
$stopsList.slideDown();
|
|
return;
|
|
/*
|
|
var $stopsList = $target.find(".stopsList");
|
|
if (!$stopsList.is(":visible")) {
|
|
$stopsList.slideDown();
|
|
} else {
|
|
$stopsList.slideUp();
|
|
$target.removeClass("selectedListItem");
|
|
}
|
|
return;
|
|
*/
|
|
}
|
|
var url = API_BASE + name + "/" + $target.find(".listItemText").text();
|
|
$target.data("loading", true);
|
|
var $loading = $('<span />').addClass("loadingSpan").text("Loading...").appendTo($target);
|
|
$('#stopForm').remove();
|
|
$('#formCol').empty();
|
|
$.getJSON(url, {'srid': 3857}, function(obj) {
|
|
//console.log("here", $target);
|
|
$loading.remove();
|
|
var stopsGeojson = obj.stops;
|
|
var stops = stopsGeojson.features;
|
|
var $stopsList = getStopsList(stops);
|
|
//console.log($stopsList);
|
|
var stopsWithGeom = [];
|
|
$.each(stops, function(i,v) {
|
|
if (!$.isEmptyObject(v.geometry)) {
|
|
stopsWithGeom.push(v);
|
|
}
|
|
});
|
|
|
|
stopsGeojson.features = stopsWithGeom;
|
|
var currFeatures = jsonLayer.features;
|
|
jsonLayer.removeFeatures(currFeatures);
|
|
console.log(stopsWithGeom);
|
|
if (stopsWithGeom.length !== 0) {
|
|
jsonLayer.addFeatures(geojson_format.read(stopsGeojson));
|
|
var maxExtent = jsonLayer.getDataExtent();
|
|
//What you see here with the setTimeout is a sign of having given up - PLEASE PLEASE make this go away - you should not need to do this - but apparently there is some error being raised by map.zoomToExtent() ALTHOUGH it seems to be doing the right thing and calling it in a setTimeout makes the other code work alright. But it causes me to sleep a little less soundly at night. Please HELP.
|
|
setTimeout(function() {
|
|
map.zoomToExtent(maxExtent);
|
|
}, 50);
|
|
}
|
|
//console.log("whoosh", $target);
|
|
$target.append($stopsList);
|
|
// $target.data("hasList", true);
|
|
$target.data("loading", false);
|
|
});
|
|
});
|
|
|
|
$('.listSearch').keyup(function(e) {
|
|
var val = $(this).val();
|
|
var name = $(this).attr("id").replace("Search", "");
|
|
var $list = $('#' + name + "List");
|
|
$list.find(".listItem").each(function() {
|
|
var $that = $(this);
|
|
var txt = $that.find(".listItemText").text();
|
|
if (txt.indexOf(val) == -1) {
|
|
$that.hide();
|
|
} else {
|
|
$that.show();
|
|
}
|
|
});
|
|
});
|
|
|
|
});
|
|
|
|
function getStopsList(stops) {
|
|
var $ul = $('<ul />')
|
|
.addClass("stopsList")
|
|
.click(function(e) {
|
|
var $target = $(e.target);
|
|
if ($target.hasClass("selectedStop")) {
|
|
return;
|
|
}
|
|
// $('.selectedStop').removeClass("selectedStop");
|
|
// $target.addClass("selectedStop");
|
|
var props = $target.data("properties");
|
|
var geom = $target.data("geometry");
|
|
var $form = getStopForm(props, geom);
|
|
var slug = $target.data("slug");
|
|
if ($target.hasClass("has_point")) {
|
|
selectStopOnMap(slug);
|
|
} else {
|
|
selectStopNotOnMap(slug);
|
|
}
|
|
|
|
$('#formCol').find("#stopForm").remove();
|
|
$('#formCol').empty();
|
|
$('#formCol').append($form);
|
|
});
|
|
|
|
$.each(stops, function(i,v) {
|
|
var props = v.properties;
|
|
var geom = v.geometry;
|
|
var $li = $('<li />')
|
|
.addClass("stopItem")
|
|
.data("slug", props.slug)
|
|
.addClass(props.slug) //FIXME: please dont set data AND addClass AND include slug in properties.
|
|
.data("properties", props)
|
|
.data("geometry", geom)
|
|
.text(props.display_name)
|
|
.appendTo($ul);
|
|
$.isEmptyObject(geom) ? $li.addClass("no_has_point") : $li.addClass("has_point");
|
|
});
|
|
return $ul;
|
|
}
|
|
|
|
function getStopForm(stop, geom) {
|
|
// console.log(stop);
|
|
// console.log(geom);
|
|
var lon = !$.isEmptyObject(geom) ? geom.coordinates[0] : '';
|
|
var lat = !$.isEmptyObject(geom) ? geom.coordinates[1] : '';
|
|
var $div = $('<div />');
|
|
var $displayName = $('<h2 />').text(stop.display_name).appendTo($div);
|
|
var $slug = $('<div />').addClass("stopSlug").text(stop.slug).appendTo($div);
|
|
var $road = $("<div />").addClass("stopRoad").text("Road: " + stop.road).appendTo($div);
|
|
var $direction = $("<div />").addClass("stopDirection").text("Direction: " + stop.direction).appendTo($div);
|
|
var $routes = $('<div />').text("Routes: " + stop.routes).appendTo($div);
|
|
// var $formLabel = $("<div />").text("Edit:").appendTo($div);
|
|
var $form = $('<form />').attr("id", "stopForm").appendTo($div);
|
|
var $display_name_label = $('<label />').attr("for", "displayName").text("Display Name:").appendTo($form);;
|
|
var $display_name_input = $('<input />')
|
|
.val(stop.display_name)
|
|
.attr("id", "displayName")
|
|
.blur(function() {
|
|
$form.submit();
|
|
})
|
|
.appendTo($form);
|
|
$('<br />').appendTo($form);
|
|
var $name_mr_label = $('<label />').attr("for", "displayNameMr").text("Marathi Name:").appendTo($form);
|
|
var $name_mr_input = $('<input />')
|
|
.val(stop.name_mr)
|
|
.attr("id", "displayNameMr")
|
|
.blur(function() {
|
|
$form.submit();
|
|
})
|
|
.appendTo($form);
|
|
$('<br />').appendTo($form);
|
|
var $alt_names_label = $('<label />').attr("for", "altNames").text("Alternative Names:").appendTo($form);
|
|
var $alt_names_input = $('<input />')
|
|
.val(stop.alternative_names)
|
|
.attr("id", "altNames")
|
|
.blur(function() {
|
|
$form.submit();
|
|
})
|
|
.appendTo($form);
|
|
$('<br />').appendTo($form);
|
|
$('<input />').attr("type","button").val("Save")
|
|
.click(function () {
|
|
$form.submit();
|
|
})
|
|
.appendTo($form);
|
|
var $lat_input = $('<input />').attr("type", "hidden").val(lat).attr("id", "lat").appendTo($form);
|
|
var $lon_input = $('<input />').attr("type", "hidden").val(lon).attr("id", "lon").appendTo($form);
|
|
$form.submit(function(e) {
|
|
e.preventDefault();
|
|
var oldProps = $('.selectedStop').data("properties");
|
|
|
|
var geojson = {
|
|
'type': 'Feature',
|
|
'properties': {
|
|
'display_name': $display_name_input.val(),
|
|
'name_mr': $name_mr_input.val(),
|
|
'alternative_names': $alt_names_input.val()
|
|
},
|
|
'geometry': {
|
|
'type': 'Point',
|
|
'coordinates': [parseFloat($lon_input.val()), parseFloat($lat_input.val())]
|
|
}
|
|
};
|
|
var props = $.extend(oldProps, geojson.properties);
|
|
$('.selectedStop').data("properties", props);
|
|
var geojsonString = JSON.stringify(geojson);
|
|
//console.log(geojsonString);
|
|
var url = API_BASE + "stop/" + stop.slug + "?srid=3857";
|
|
var $postXHR = $.post(url, {'geojson': geojsonString}, function(response) {
|
|
if (response.errors) {
|
|
alert("error saving");
|
|
}
|
|
//console.log(response);
|
|
}, "json");
|
|
$postXHR.fail(function(e) {
|
|
alert('failed ' + JSON.stringify(e));
|
|
});
|
|
});
|
|
return $div;
|
|
}
|
|
|
|
function initMap() {
|
|
var center = new OpenLayers.LonLat(8110203.9998955, 2170000.4068373);
|
|
map = new OpenLayers.Map("mapCol", {
|
|
projection: new OpenLayers.Projection("EPSG:900913"),
|
|
displayProjection: new OpenLayers.Projection("EPSG:4326")
|
|
});
|
|
var layers = [];
|
|
// layers[0] = new OpenLayers.Layer.OSM();
|
|
|
|
layers[0] = new OpenLayers.Layer.OSM();
|
|
layers[1] = new OpenLayers.Layer.Bing({
|
|
name: "Bing Aerial",
|
|
type: "Aerial",
|
|
key: "AqGpO7N9ioFw3YHoPV3C8crGfJqW5YST4gGKgIOnijrUbitLlgcAS2A0M9SJrUv9",
|
|
});
|
|
geojson_format = new OpenLayers.Format.GeoJSON();
|
|
//
|
|
//yes, jsonLayer is global. Yes, I know it's wrong.
|
|
jsonLayer = layers[2] = new OpenLayers.Layer.Vector("Bus Stops");
|
|
map.addLayers(layers);
|
|
jsonLayer.events.on({
|
|
'featureselected': onFeatureSelect,
|
|
'featureunselected': onFeatureUnselect
|
|
});
|
|
|
|
map.setCenter(center, 12);
|
|
var navigationControl = new OpenLayers.Control.Navigation({
|
|
defaultDblClick: function(event) {
|
|
//var xy = event.xy;
|
|
var lonlat = map.getLonLatFromPixel(event.xy);
|
|
var $stopForm = $('#stopForm');
|
|
if ($stopForm.length === 0) {
|
|
return;
|
|
}
|
|
var slug = $('#formCol').find('.stopSlug').text();
|
|
//console.log("slug", slug);
|
|
var stop = $('.selectedStop').data("properties");
|
|
$('.selectedStop').data("geometry", {
|
|
'coordinates': [lonlat.x, lonlat.y]
|
|
});
|
|
var hasPoint = $('.selectedStop').hasClass('has_point');
|
|
$('#lon').val(lonlat.lon);
|
|
$('#lat').val(lonlat.lat);
|
|
$stopForm.submit();
|
|
if (hasPoint) {
|
|
var feature = getStopFromSlug(slug);
|
|
feature.move(lonlat);
|
|
} else {
|
|
var pt = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat);
|
|
var feature = new OpenLayers.Feature.Vector(pt, stop);
|
|
$('.selectedStop').removeClass("no_has_point").addClass("has_point");
|
|
jsonLayer.addFeatures([feature]);
|
|
mapControl.select(feature);
|
|
}
|
|
return;
|
|
}
|
|
});
|
|
map.addControl(navigationControl);
|
|
|
|
// Feature selection control
|
|
mapControl = new OpenLayers.Control.SelectFeature(jsonLayer, {
|
|
clickout: false,
|
|
toggle: true
|
|
});
|
|
|
|
//map.addControl(new OpenLayers.Control.ZoomPanel());
|
|
map.addControl(mapControl);
|
|
mapControl.activate();
|
|
|
|
// Add a LayerSwitcher since we now have Bing
|
|
map.addControl(new OpenLayers.Control.LayerSwitcher());
|
|
|
|
// Add a permalink that opens the relevant view in OSM.org in a different window
|
|
var permalink = new OpenLayers.Control.Permalink({base: "http://www.openstreetmap.org/"});
|
|
map.addControl(permalink);
|
|
$(".olControlPermalink a").attr("target","_blank").html("View in OSM");
|
|
//alert('Not here');
|
|
}
|
|
|
|
function onFeatureSelect(e) {
|
|
//alert(arguments);
|
|
//console.log(feature);
|
|
// console.log(e.feature);
|
|
var slug = e.feature.attributes.slug;
|
|
//alert("selected " + slug);
|
|
$('.selectedStop').removeClass("selectedStop");
|
|
highlightStop(slug);
|
|
var stop = e.feature.attributes;
|
|
var geom = {
|
|
'coordinates': [e.feature.geometry.x, e.feature.geometry.y]
|
|
};
|
|
var $form = getStopForm(stop, geom);
|
|
$('#stopForm').remove();
|
|
$('#formCol').empty();
|
|
$('#formCol').append($form);
|
|
// var matchedStops = $('.' + slug);
|
|
// matchedStops.click();
|
|
// matchedStops.addClass('highlightedStop');
|
|
|
|
}
|
|
|
|
function onFeatureUnselect(e) {
|
|
var slug = e.feature.attributes.slug;
|
|
//alert("unselected " + slug);
|
|
unhighlightStop(slug);
|
|
$('#stopForm').remove();
|
|
$('#formCol').empty();
|
|
// var matchedStops = $('.' + slug);
|
|
// matchedStops.removeClass('selectedStop');
|
|
}
|
|
|
|
function highlightStop(slug) {
|
|
$('.' + slug).addClass("selectedStop");
|
|
}
|
|
|
|
function unhighlightStop(slug) {
|
|
$('.' + slug).removeClass("selectedStop");
|
|
}
|
|
|
|
function getStopFromSlug(slug) {
|
|
var features = jsonLayer.features;
|
|
var matchedLayer = false;
|
|
for (var i=0; i<features.length; i++) {
|
|
var feature = features[i];
|
|
if (feature.attributes.slug === slug) {
|
|
matchedLayer = feature;
|
|
}
|
|
}
|
|
return matchedLayer;
|
|
}
|
|
|
|
function selectStopNotOnMap(slug) {
|
|
var selectedFeature = getCurrentlySelectedFeature();
|
|
if (selectedFeature) {
|
|
var currentSlug = selectedFeature.attributes.slug;
|
|
unhighlightStop(slug);
|
|
mapControl.unselect(selectedFeature);
|
|
} else {
|
|
$('.selectedStop').removeClass("selectedStop");
|
|
}
|
|
highlightStop(slug);
|
|
}
|
|
|
|
function selectStopOnMap(slug) {
|
|
var feature = getStopFromSlug(slug);
|
|
var selectedFeature = getCurrentlySelectedFeature();
|
|
if (selectedFeature) {
|
|
mapControl.unselect(selectedFeature);
|
|
} else {
|
|
$('.selectedStop').removeClass("selectedStop");
|
|
}
|
|
mapControl.select(feature);
|
|
//map.setCenter(feature.geometry);
|
|
var lonLat = new OpenLayers.LonLat(feature.geometry.x, feature.geometry.y);
|
|
map.setCenter(lonLat);
|
|
}
|
|
|
|
//return currently selected feature or false
|
|
function getCurrentlySelectedFeature() {
|
|
var selectedFeatures = jsonLayer.selectedFeatures;
|
|
if (selectedFeatures.length > 0) {
|
|
return jsonLayer.selectedFeatures[0];
|
|
// mapControl.unselect(selectedFeature);
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
})();
|