From eec54b3920b2974922a103b4bb4d5246f4cdefe8 Mon Sep 17 00:00:00 2001 From: Jacek Kowalski <Jacek@jacekk.info> Date: Wed, 03 May 2017 21:50:43 +0000 Subject: [PATCH] Fix JS error during vehicle removal when no feature is selected --- map.js | 320 ++++++++++++++++++++++++++++++++++------------------- 1 files changed, 204 insertions(+), 116 deletions(-) diff --git a/map.js b/map.js index fa587a0..f791391 100644 --- a/map.js +++ b/map.js @@ -15,7 +15,6 @@ var stop_points_layer = null; var feature_clicked = null; -var feature_selected = []; var feature_xhr = null; var feature_timer = null; @@ -24,18 +23,49 @@ var map = null; var map_sphere = null; -var popup_element = document.getElementById('popup'); var fail_element = document.getElementById('fail'); var ignore_hashchange = false; +var Panel = { + element: document.getElementById('popup'), + closeCallback: undefined, + + callCloseCallback: function() { + var callback = this.closeCallback; + this.closeCallback = null; + if(callback) callback(); + }, + + show: function(contents, closeCallback) { + this.callCloseCallback(); + this.closeCallback = closeCallback; + + deleteChildren(this.element); + + var close = addParaWithText(this.element, '×'); + close.className = 'close'; + close.addEventListener('click', this.hide.bind(this)); + + this.element.appendChild(contents); + + $(this.element).addClass('show'); + }, + + hide: function() { + this.callCloseCallback(); + + $(this.element).removeClass('show'); + }, + + fail: function(message) { + addParaWithText(this.element, message).className = 'error'; + }, +}; + function fail(msg) { setText(fail_element, msg); fail_element.style.top = '0.5em'; -} - -function fail_popup(msg) { - addElementWithText(popup_element, 'p', msg).className = 'error'; } function fail_ajax_generic(data, fnc) { @@ -56,99 +86,109 @@ } function fail_ajax_popup(data) { - fail_ajax_generic(data, fail_popup); + fail_ajax_generic(data, Panel.fail); } function getGeometry(object) { return new ol.geom.Point(ol.proj.fromLonLat([object.longitude / 3600000.0, object.latitude / 3600000.0])); } -function styleVehicle(vehicle, selected) { - var color_type = 'black'; - if(vehicle.get('vehicle_type')) { - switch(vehicle.get('vehicle_type').low) { - case 0: - color_type = 'orange'; +var Style = { + specialSelection: 2, + selectedFeatures: [], + + getStyleForVehicle: function(vehicleFeature, isSelected) { + var color_type = 'black'; + if(vehicleFeature.get('vehicle_type')) { + switch(vehicleFeature.get('vehicle_type').low) { + case 0: + color_type = 'orange'; + break; + case 1: + color_type = 'blue'; + break; + case 2: + color_type = 'green'; + break; + } + } + + var fill = (isSelected ? '#a00' : '#3399ff'); + + var image = '<svg xmlns="http://www.w3.org/2000/svg" height="30" width="20"><polygon points="10,0 20,23 0,23" style="fill:'+fill+';stroke:'+color_type+';stroke-width:2" /></svg>'; + + return new ol.style.Style({ + image: new ol.style.Icon({ + src: 'data:image/svg+xml;base64,' + btoa(image), + rotation: Math.PI * parseFloat(vehicleFeature.get('heading')) / 180.0, + }), + text: new ol.style.Text({ + font: 'bold 10px sans-serif', + text: vehicleFeature.get('line'), + fill: new ol.style.Fill({color: 'white'}), + }), + }); + }, + + getStyleForStop: function(stopFeature, isSelected) { + var fill = 'orange'; + var stroke = 'red'; + var stroke_width = 1; + var radius = 3; + + if(isSelected == this.specialSelection) { + radius = 5; + } else if(isSelected) { + fill = 'red'; + stroke = '#900'; + stroke_width = 2; + radius = 5; + } + + return new ol.style.Style({ + image: new ol.style.Circle({ + fill: new ol.style.Fill({color: fill}), + stroke: new ol.style.Stroke({color: stroke, width: stroke_width}), + radius: radius, + }), + }); + }, + + getStyleForStopPoint: function(stopFeature, isSelected) { + return this.getStyleForStop(stopFeature, isSelected); + }, + + feature: function(feature, isSelected) { + if(!feature) return; + if(!feature.getId()) return; + + var style = null; + + switch(feature.getId().substr(0, 1)) { + case 'v': + style = this.getStyleForVehicle(feature, isSelected); break; - case 1: - color_type = 'blue'; + case 's': + style = this.getStyleForStop(feature, isSelected); break; - case 2: - color_type = 'green'; + case 'p': + style = this.getStyleForStopPoint(feature, isSelected); break; } - } - - var fill = (selected ? '#a00' : '#3399ff'); - - var image = '<svg xmlns="http://www.w3.org/2000/svg" height="30" width="20"><polygon points="10,0 20,23 0,23" style="fill:'+fill+';stroke:'+color_type+';stroke-width:2" /></svg>'; - - return new ol.style.Style({ - image: new ol.style.Icon({ - src: 'data:image/svg+xml;base64,' + btoa(image), - rotation: Math.PI * parseFloat(vehicle.get('heading')) / 180.0, - }), - text: new ol.style.Text({ - font: 'bold 10px sans-serif', - text: vehicle.get('line'), - fill: new ol.style.Fill({color: 'white'}), - }), - }); -} - -function styleStop(stop, selected) { - var fill = 'orange'; - var stroke = 'red'; - var stroke_width = 1; - var radius = 3; - - if(selected == 2) { - radius = 5; - } else if(selected) { - fill = 'red'; - stroke = '#900'; - stroke_width = 2; - radius = 5; - } - - return new ol.style.Style({ - image: new ol.style.Circle({ - fill: new ol.style.Fill({color: fill}), - stroke: new ol.style.Stroke({color: stroke, width: stroke_width}), - radius: radius, - }), - }); -} - -function styleFeature(feature, selected) { - if(!feature) return; - if(!feature.getId()) return; - - var style = null; - - switch(feature.getId().substr(0, 1)) { - case 'v': - style = styleVehicle(feature, selected); - break; - case 's': - case 'p': - style = styleStop(feature, selected); - break; - } + feature.setStyle(style); + if(isSelected) { + this.selectedFeatures.push(feature); + } + }, - feature.setStyle(style); - if(selected) { - feature_selected.push(feature); + unstyleSelected: function() { + for(var i = 0; i < this.selectedFeatures.length; i++) { + this.feature(this.selectedFeatures[i]); + } + this.selectedFeatures = []; } -} - -function unstyleSelectedFeatures() { - for(var i = 0; i < feature_selected.length; i++) { - styleFeature(feature_selected[i]); - } - feature_selected = []; -} +}; function updateVehicles() { if(vehicles_timer) clearTimeout(vehicles_timer); @@ -169,7 +209,7 @@ if(vehicle.isDeleted) { if(vehicle_feature) { vehicles_source.removeFeature(vehicle_feature); - if(feature_clicked.getId() == vehicle_feature.getId()) { + if(feature_clicked && feature_clicked.getId() == vehicle_feature.getId()) { featureClicked(); } } @@ -190,7 +230,7 @@ vehicle_feature = new ol.Feature(vehicle); vehicle_feature.setId('v' + vehicle.id); - styleFeature(vehicle_feature); + Style.feature(vehicle_feature); vehicles_source.addFeature(vehicle_feature); } else { vehicle_feature.setProperties(vehicle); @@ -218,7 +258,7 @@ var stop_feature = new ol.Feature(stop); stop_feature.setId(prefix + stop.id); - styleFeature(stop_feature); + Style.feature(stop_feature); source.addFeature(stop_feature); } @@ -257,7 +297,7 @@ + '?tripId=' + encodeURIComponent(tripId) + '&mode=departure' ).done(function(data) { - if(!data.routeName || !data.directionText || data.old.length + data.actual.length == 0) { + if(!data.routeName || !data.directionText) { return; } @@ -272,15 +312,15 @@ table.appendChild(tr); } - unstyleSelectedFeatures(); - styleFeature(feature_clicked, true); + Style.unstyleSelected(); + Style.feature(feature_clicked, true); for(var i = 0, il = data.actual.length; i < il; i++) { var tr = document.createElement('tr'); addCellWithText(tr, data.actual[i].actualTime || data.actual[i].plannedTime); addCellWithText(tr, data.actual[i].stop_seq_num + '. ' + data.actual[i].stop.name); - styleFeature(stops_source.getFeatureById('s' + data.actual[i].stop.id), 2); + Style.feature(stops_source.getFeatureById('s' + data.actual[i].stop.id), 2); if(data.actual[i].status == 'STOPPING') { tr.className = 'success'; @@ -371,27 +411,17 @@ function featureClicked(feature) { if(feature && !feature.getId()) return; - unstyleSelectedFeatures(); + Style.unstyleSelected(); route_source.clear(); if(!feature) { - feature_clicked = null; - - $(popup_element).removeClass('show'); - - ignore_hashchange = true; - window.location.hash = ''; - + Panel.hide(); return; } var coordinates = feature.getGeometry().getCoordinates(); - deleteChildren(popup_element); - - var close = addParaWithText(popup_element, '×'); - close.className = 'close'; - close.addEventListener('click', function() { featureClicked(); }); + var div = document.createElement('div'); var type; var name = feature.get('name'); @@ -460,25 +490,37 @@ loader.className = 'active'; loader.colSpan = thead.childNodes.length; - addParaWithText(popup_element, type).className = 'type'; - addParaWithText(popup_element, name).className = 'name'; + addParaWithText(div, type).className = 'type'; + addParaWithText(div, name).className = 'name'; if(additional) { - popup_element.appendChild(additional); + div.appendChild(additional); } - popup_element.appendChild(table); + div.appendChild(table); - ignore_hashchange = true; - window.location.hash = '#!' + feature.getId(); - - styleFeature(feature, true); + Style.feature(feature, true); setTimeout(function () {map.getView().animate({ center: feature.getGeometry().getCoordinates(), }) }, 10); - $(popup_element).addClass('show'); + ignore_hashchange = true; + window.location.hash = '#!' + feature.getId(); + + Panel.show(div, function() { + if(!ignore_hashchange) { + ignore_hashchange = true; + window.location.hash = ''; + + feature_clicked = null; + Style.unstyleSelected(); + route_source.clear(); + + if(feature_xhr) feature_xhr.abort(); + if(feature_timer) clearTimeout(feature_timer); + } + }); feature_clicked = feature; } @@ -621,8 +663,50 @@ // Display popup on click map.on('singleclick', function(e) { var point = e.coordinate; - var feature = map.forEachFeatureAtPixel(e.pixel, function(feature) { return feature; }); + var features = []; + map.forEachFeatureAtPixel(e.pixel, function(feature) { if(feature.getId()) features.push(feature); }); + if(features.length > 1) { + var div = document.createElement('div'); + + addParaWithText(div, lang.select_feature); + + for(var i = 0; i < features.length; i++) { + var feature = features[i]; + + var p = document.createElement('p'); + var a = document.createElement('a'); + p.appendChild(a); + a.addEventListener('click', function(feature) { return function() { + featureClicked(feature); + }}(feature)); + + var type = ''; + switch(feature.getId().substr(0, 1)) { + case 'v': + type = lang.type_vehicle + ' ' + feature.get('vehicle_type').num; + break; + case 's': + type = lang.type_stop; + break; + case 'p': + type = lang.type_stoppoint; + break; + } + + addElementWithText(a, 'span', type).className = 'small'; + a.appendChild(document.createTextNode(' ')); + addElementWithText(a, 'span', feature.get('name')); + + div.appendChild(p); + } + + Panel.show(div); + + return; + } + + var feature = features[0]; if(!feature) { if(stops_layer.getVisible()) { feature = returnClosest(point, feature, stops_source.getClosestFeatureToCoordinate(point)); @@ -641,6 +725,10 @@ featureClicked(feature); }); + + fail_element.addEventListener('click', function() { + fail_element.style.top = '-10em'; + }); // Change mouse cursor when over marker map.on('pointermove', function(e) { -- Gitblit v1.9.1