aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--templates/web/angus/maps/fms.html3
-rw-r--r--templates/web/base/report/new/category_wrapper.html8
-rw-r--r--templates/web/bristol/footer_extra_js.html4
-rw-r--r--web/cobrands/angus/base.scss12
-rw-r--r--web/cobrands/angus/js.js15
-rw-r--r--web/cobrands/angus/layout.scss6
-rw-r--r--web/cobrands/angus/position_map.js330
-rw-r--r--web/cobrands/bristol/js.js45
-rw-r--r--web/cobrands/fixmystreet/assets.js381
-rw-r--r--web/cobrands/sass/_base.scss12
-rw-r--r--web/cobrands/sass/_layout.scss6
11 files changed, 469 insertions, 353 deletions
diff --git a/templates/web/angus/maps/fms.html b/templates/web/angus/maps/fms.html
index a47a5a6e3..aed4d1764 100644
--- a/templates/web/angus/maps/fms.html
+++ b/templates/web/angus/maps/fms.html
@@ -4,7 +4,8 @@
<script type="text/javascript" src="[% version('/js/map-OpenLayers.js') %]"></script>
<script type="text/javascript" src="[% version('/js/map-bing-ol.js') %]"></script>
<script type="text/javascript" src="[% version('/js/map-fms.js') %]"></script>
-<script src="[% version('/cobrands/angus/position_map.js') %]" charset="utf-8"></script>
+<script src="[% version('/cobrands/fixmystreet/assets.js') %]"></script>
+<script src="[% version('/cobrands/angus/js.js') %]"></script>
[% END %]
[% map_html = INCLUDE maps/openlayers.html include_key = 1 %]
diff --git a/templates/web/base/report/new/category_wrapper.html b/templates/web/base/report/new/category_wrapper.html
index 85b085999..9f628c44e 100644
--- a/templates/web/base/report/new/category_wrapper.html
+++ b/templates/web/base/report/new/category_wrapper.html
@@ -1,8 +1,7 @@
+<div id="form_category_row">
[% IF js %]
- <div id="form_category_row">
- <label for="form_category">[% loc('Category') %]</label>
- <select class="form-control" name="category" id="form_category" required><option>[% loc('Loading...') %]</option></select>
- </div>
+ <label for="form_category">[% loc('Category') %]</label>
+ <select class="form-control" name="category" id="form_category" required><option>[% loc('Loading...') %]</option></select>
[% ELSE %]
[% IF category_options.size %]
[% IF field_errors.category %]
@@ -11,6 +10,7 @@
[% PROCESS "report/new/category.html" %]
[% END %]
[% END %]
+</div>
[%- IF category_extras %]
[% PROCESS "report/new/category_extras.html" %]
diff --git a/templates/web/bristol/footer_extra_js.html b/templates/web/bristol/footer_extra_js.html
new file mode 100644
index 000000000..6ba5e3100
--- /dev/null
+++ b/templates/web/bristol/footer_extra_js.html
@@ -0,0 +1,4 @@
+<script src="[% version('/js/OpenLayers.Projection.OrdnanceSurvey.js') %]"></script>
+<script src="[% version('/cobrands/fixmystreet-uk-councils/js.js') %]"></script>
+<script src="[% version('/cobrands/fixmystreet/assets.js') %]"></script>
+<script src="[% version('/cobrands/bristol/js.js') %]"></script>
diff --git a/web/cobrands/angus/base.scss b/web/cobrands/angus/base.scss
index 25cb08b2b..31ba13a11 100644
--- a/web/cobrands/angus/base.scss
+++ b/web/cobrands/angus/base.scss
@@ -48,15 +48,3 @@ label[for=pc] {
.nav-menu--breadcrumb {
display: none;
}
-
-.streetlight-spot:before {
- content: "";
- display: inline-block;
- width: 10px;
- height: 10px;
- border: 2px solid #000;
- background-color: #ffff00;
- margin: 0 0.3em 0 0.2em;
- border-radius: 100%;
- vertical-align: -2px;
-}
diff --git a/web/cobrands/angus/js.js b/web/cobrands/angus/js.js
new file mode 100644
index 000000000..af70fd92f
--- /dev/null
+++ b/web/cobrands/angus/js.js
@@ -0,0 +1,15 @@
+$(fixmystreet.add_assets({
+ wfs_url: "https://data.angus.gov.uk/geoserver/services/wfs",
+ wfs_feature: "lighting_column_v",
+ wfs_fault_feature: "lighting_faults_v",
+ asset_category: "Street lighting",
+ asset_item: 'street light',
+ asset_type: 'spot',
+ max_resolution: 2.388657133579254,
+ min_resolution: 0.5971642833948135,
+ asset_id_field: 'n',
+ attributes: {
+ column_id: 'n'
+ },
+ geometryName: 'g'
+}));
diff --git a/web/cobrands/angus/layout.scss b/web/cobrands/angus/layout.scss
index 1e4277700..7b819185a 100644
--- a/web/cobrands/angus/layout.scss
+++ b/web/cobrands/angus/layout.scss
@@ -357,12 +357,6 @@ body.mappage {
#category_meta h4 {
display: none;
}
-
- #category_meta_message {
- padding-top: 0.5em;
- font-size: 0.9em;
- text-align: center;
- }
}
.angus_footer {
diff --git a/web/cobrands/angus/position_map.js b/web/cobrands/angus/position_map.js
deleted file mode 100644
index d5d3c942f..000000000
--- a/web/cobrands/angus/position_map.js
+++ /dev/null
@@ -1,330 +0,0 @@
-// Wrap custom functionality up in a closure to keep scopes tidy
-var add_streetlights = (function() {
- var wfs_url = "https://data.angus.gov.uk/geoserver/services/wfs";
- var wfs_feature = "lighting_column_v";
- var wfs_fault_feature = "lighting_faults_v";
- var streetlight_category = "Street lighting";
- var max_resolution = 2.388657133579254;
- var min_resolution = 0.5971642833948135;
-
- var streetlight_layer = null;
- var streetlight_fault_layer = null;
- var select_feature_control;
- var hover_feature_control;
- var selected_feature = null;
- var fault_popup = null;
-
- function close_fault_popup() {
- if (!!fault_popup) {
- fixmystreet.map.removePopup(fault_popup);
- fault_popup.destroy();
- fault_popup = null;
- }
- }
-
- function streetlight_selected(e) {
- close_fault_popup();
- var lonlat = e.feature.geometry.getBounds().getCenterLonLat();
-
- // Check if there is a known fault with the light that's been clicked,
- // and disallow selection if so.
- var fault_feature = find_matching_feature(e.feature, streetlight_fault_layer);
- if (!!fault_feature) {
- fault_popup = new OpenLayers.Popup.FramedCloud("popup",
- e.feature.geometry.getBounds().getCenterLonLat(),
- null,
- "This fault (" + e.feature.attributes.n + ")<br />has been reported.",
- { size: new OpenLayers.Size(0, 0), offset: new OpenLayers.Pixel(0, 0) },
- true, close_fault_popup);
- fixmystreet.map.addPopup(fault_popup);
- select_feature_control.unselect(e.feature);
- return;
- }
-
- // Set the 'column id' extra field to the value of the light that was clicked
- var column_id = e.feature.attributes.n;
- $("#form_column_id").val(column_id);
-
- // Hide the normal markers layer to keep things simple, but
- // move the green marker to the point of the click to stop
- // it jumping around unexpectedly if the user deselects street light.
- fixmystreet.markers.setVisibility(false);
- fixmystreet.markers.features[0].move(lonlat);
-
- // Need to ensure the correct coords are used for the report
- fixmystreet.maps.update_pin(lonlat);
-
- // Make sure the marker that was clicked is drawn on top of its neighbours
- var layer = e.feature.layer;
- var feature = e.feature;
- layer.eraseFeatures([feature]);
- layer.drawFeature(feature);
-
- // Keep track of selection in case layer is reloaded or hidden etc.
- selected_feature = feature.clone();
- }
-
- function streetlight_unselected(e) {
- fixmystreet.markers.setVisibility(true);
- $("#form_column_id").val("");
- selected_feature = null;
- }
-
- function find_matching_feature(feature, layer) {
- // When the WFS layer is reloaded the same features might be visible
- // but they'll be different instances of the class so we can't use
- // object identity comparisons.
- // This function will find the best matching feature based on its
- // attributes and distance from the original feature.
- var threshold = 1; // metres
- for (var i = 0; i < layer.features.length; i++) {
- var candidate = layer.features[i];
- var distance = candidate.geometry.distanceTo(feature.geometry);
- if (candidate.attributes.n == feature.attributes.n && distance <= threshold) {
- return candidate;
- }
- }
- }
-
- function check_zoom_message_visiblity() {
- var category = $("#problem_form select#form_category").val();
- if (category == streetlight_category) {
- var $p = $("#category_meta_message");
-
- if ($p.length === 0) {
- $p = $("<p>").prop("id", "category_meta_message");
- // #category_meta might not be here yet, but that's OK as the
- // element simply won't be added to the DOM.
- $p.insertAfter("#category_meta");
- }
-
- if (streetlight_layer.getVisibility() && streetlight_layer.inRange) {
- $p.html('Or pick a <b class="streetlight-spot">street light</b> from the map &raquo;');
- } else {
- $p.html('Or zoom in and pick a street light from the map');
- }
-
- } else {
- $("#category_meta_message").remove();
- }
- }
-
- function layer_visibilitychanged() {
- check_zoom_message_visiblity();
- select_nearest_streetlight();
- }
-
- function zoom_to_streetlights() {
- // This function is called when the street lighting category is
- // selected, and will zoom the map in to the first level that
- // makes the street light layer visible if it's not already shown.
- if (!streetlight_layer.inRange) {
- var firstVisibleResolution = streetlight_layer.resolutions[0];
- var zoomLevel = fixmystreet.map.getZoomForResolution(firstVisibleResolution);
- fixmystreet.map.zoomTo(zoomLevel);
- }
- }
-
- function select_nearest_streetlight() {
- // The user's green marker might be on the map the first time we show the
- // streetlights, so snap it to the closest streetlight marker if so.
- if (!fixmystreet.markers.getVisibility() || !(streetlight_layer.getVisibility() && streetlight_layer.inRange)) {
- return;
- }
- var threshold = 50; // metres
- var marker = fixmystreet.markers.features[0];
- if (marker === undefined) {
- // No marker to be found so bail out
- return;
- }
- var closest_feature;
- var closest_distance = null;
- for (var i = 0; i < streetlight_layer.features.length; i++) {
- var candidate = streetlight_layer.features[i];
- var distance = candidate.geometry.distanceTo(marker.geometry);
- if (closest_distance === null || distance < closest_distance) {
- closest_feature = candidate;
- closest_distance = distance;
- }
- }
- if (closest_distance <= threshold && !!closest_feature) {
- select_feature_control.select(closest_feature);
- }
- }
-
- function layer_loadend(e) {
- select_nearest_streetlight();
- // Preserve the selected marker when panning/zooming, if it's still on the map
- if (selected_feature !== null && !(selected_feature in this.selectedFeatures)) {
- var replacement_feature = find_matching_feature(selected_feature, streetlight_layer);
- if (!!replacement_feature) {
- select_feature_control.select(replacement_feature);
- }
- }
- }
-
- function get_streetlight_stylemap() {
- return new OpenLayers.StyleMap({
- 'default': new OpenLayers.Style({
- fillColor: "#FFFF00",
- fillOpacity: 0.6,
- strokeColor: "#000000",
- strokeOpacity: 0.8,
- strokeWidth: 2,
- pointRadius: 6
- }),
- 'select': new OpenLayers.Style({
- externalGraphic: fixmystreet.pin_prefix + "pin-spot.png",
- graphicWidth: 48,
- graphicHeight: 64,
- graphicXOffset: -24,
- graphicYOffset: -56,
- backgroundGraphic: fixmystreet.pin_prefix + "pin-shadow.png",
- backgroundWidth: 60,
- backgroundHeight: 30,
- backgroundXOffset: -7,
- backgroundYOffset: -22,
- popupYOffset: -40,
- graphicOpacity: 1.0
- }),
- 'temporary': new OpenLayers.Style({
- fillColor: "#55BB00",
- fillOpacity: 0.8,
- strokeColor: "#000000",
- strokeOpacity: 1,
- strokeWidth: 2,
- pointRadius: 8,
- cursor: 'pointer'
- })
- });
- }
-
- function get_fault_stylemap() {
- return new OpenLayers.StyleMap({
- 'default': new OpenLayers.Style({
- fillColor: "#FF6600",
- fillOpacity: 1,
- strokeColor: "#FF6600",
- strokeOpacity: 1,
- strokeWidth: 1.25,
- pointRadius: 8
- })
- });
- }
-
- function add_streetlights() {
- if (streetlight_layer !== null) {
- // Layer has already been added
- return;
- }
- if (window.fixmystreet === undefined) {
- // We're on a page without a map, yet somehow still got called...
- // Nothing to do.
- return;
- }
- if (fixmystreet.map === undefined) {
- // Map's not loaded yet, let's try again soon...
- setTimeout(add_streetlights, 250);
- return;
- }
- if (fixmystreet.page != 'new' && fixmystreet.page != 'around') {
- // We only want to show light markers when making a new report
- return;
- }
-
- // An interactive layer for selecting a street light
- var protocol = new OpenLayers.Protocol.WFS({
- version: "1.1.0",
- url: wfs_url,
- featureType: wfs_feature,
- geometryName: "g"
- });
- streetlight_layer = new OpenLayers.Layer.Vector("WFS", {
- strategies: [new OpenLayers.Strategy.BBOX()],
- protocol: protocol,
- visibility: false,
- maxResolution: max_resolution,
- minResolution: min_resolution,
- styleMap: get_streetlight_stylemap()
- });
- fixmystreet.streetlight_layer = streetlight_layer;
-
- // A non-interactive layer to display existing street light faults
- var fault_protocol = new OpenLayers.Protocol.WFS({
- version: "1.1.0",
- url: wfs_url,
- featureType: wfs_fault_feature,
- geometryName: "g"
- });
- streetlight_fault_layer = new OpenLayers.Layer.Vector("WFS", {
- strategies: [new OpenLayers.Strategy.BBOX()],
- protocol: fault_protocol,
- visibility: false,
- maxResolution: max_resolution,
- minResolution: min_resolution,
- styleMap: get_fault_stylemap()
- });
-
- // Set up handlers for selecting/unselecting markers and panning/zooming the map
- select_feature_control = new OpenLayers.Control.SelectFeature( streetlight_layer );
- streetlight_layer.events.register( 'featureselected', streetlight_layer, streetlight_selected);
- streetlight_layer.events.register( 'featureunselected', streetlight_layer, streetlight_unselected);
- streetlight_layer.events.register( 'loadend', streetlight_layer, layer_loadend);
- streetlight_layer.events.register( 'visibilitychanged', streetlight_layer, layer_visibilitychanged);
- fixmystreet.map.events.register( 'zoomend', streetlight_layer, check_zoom_message_visiblity);
- // Set up handlers for simply hovering over a street light marker
- hover_feature_control = new OpenLayers.Control.SelectFeature(
- streetlight_layer,
- {
- hover: true,
- highlightOnly: true,
- renderIntent: 'temporary'
- }
- );
- hover_feature_control.events.register('beforefeaturehighlighted', null, function(e) {
- // Don't let marker go from selected->hover state,
- // as it causes some mad flickering effect.
- if (e.feature.renderIntent == 'select') {
- return false;
- }
- });
-
- fixmystreet.map.addLayer(streetlight_layer);
- fixmystreet.map.addLayer(streetlight_fault_layer);
- fixmystreet.map.addControl( hover_feature_control );
- hover_feature_control.activate();
- fixmystreet.map.addControl( select_feature_control );
- select_feature_control.activate();
-
- // Make sure the fault markers always appear beneath the street lights
- streetlight_fault_layer.setZIndex(streetlight_layer.getZIndex()-1);
-
- // Show/hide the streetlight layer when the category is chosen
- $("#problem_form").on("change.category", "select#form_category", function(){
- var category = $(this).val();
- if (category == streetlight_category) {
- streetlight_layer.setVisibility(true);
- streetlight_fault_layer.setVisibility(true);
- zoom_to_streetlights();
- } else {
- streetlight_layer.setVisibility(false);
- streetlight_fault_layer.setVisibility(false);
- }
- });
- }
-
- // Make sure the streetlights get hidden if the back button is pressed
- fixmystreet.maps.display_around = (function(original) {
- function hide_streetlights() {
- streetlight_layer.setVisibility(false);
- streetlight_fault_layer.setVisibility(false);
- fixmystreet.markers.setVisibility(true);
- original.apply(fixmystreet.maps);
- }
- return hide_streetlights;
- })(fixmystreet.maps.display_around);
-
- return add_streetlights;
-})();
-
-$(add_streetlights);
diff --git a/web/cobrands/bristol/js.js b/web/cobrands/bristol/js.js
new file mode 100644
index 000000000..f47df6777
--- /dev/null
+++ b/web/cobrands/bristol/js.js
@@ -0,0 +1,45 @@
+(function(){
+
+var options = {
+ wfs_url: "https://maps.bristol.gov.uk/arcgis/services/ext/FixMyStreetSupportData/MapServer/WFSServer",
+ wfs_feature: "COD_ASSETS_POINT",
+ max_resolution: 0.33072982812632296,
+ min_resolution: 0.00001,
+ asset_id_field: 'COD_ASSET_ID',
+ asset_type: 'spot',
+ attributes: {
+ asset_id: 'COD_ASSET_ID',
+ usrn: 'COD_USRN'
+ },
+ geometryName: 'SHAPE'
+};
+
+$(fixmystreet.add_assets($.extend({}, options, {
+ wfs_feature: "COD_ASSETS_AREA",
+ asset_type: 'area',
+ asset_category: "Bridges/Subways",
+ asset_item: 'bridge/subway'
+})));
+
+$(fixmystreet.add_assets($.extend({}, options, {
+ asset_category: "Gully/Drainage",
+ asset_item: 'gully',
+ filter_key: 'COD_ASSET_TYPE',
+ filter_value: 'GULLY'
+})));
+
+$(fixmystreet.add_assets($.extend({}, options, {
+ asset_category: "Grit Bins",
+ asset_item: 'grit bin',
+ filter_key: 'COD_ASSET_TYPE',
+ filter_value: 'GRITBIN'
+})));
+
+$(fixmystreet.add_assets($.extend({}, options, {
+ asset_category: "Street Lighting",
+ asset_item: 'street light',
+ filter_key: 'COD_ASSET_TYPE',
+ filter_value: 'SL'
+})));
+
+})();
diff --git a/web/cobrands/fixmystreet/assets.js b/web/cobrands/fixmystreet/assets.js
new file mode 100644
index 000000000..630cebccb
--- /dev/null
+++ b/web/cobrands/fixmystreet/assets.js
@@ -0,0 +1,381 @@
+var fixmystreet = fixmystreet || {};
+
+(function(){
+
+var selected_feature = null;
+var fault_popup = null;
+
+function close_fault_popup() {
+ if (!!fault_popup) {
+ fixmystreet.map.removePopup(fault_popup);
+ fault_popup.destroy();
+ fault_popup = null;
+ }
+}
+
+function asset_selected(e) {
+ close_fault_popup();
+ var lonlat = e.feature.geometry.getBounds().getCenterLonLat();
+
+ // Check if there is a known fault with the light that's been clicked,
+ // and disallow selection if so.
+ var fault_feature = find_matching_feature(e.feature, this.fixmystreet.fault_layer, this.fixmystreet.asset_id_field);
+ if (!!fault_feature) {
+ fault_popup = new OpenLayers.Popup.FramedCloud("popup",
+ e.feature.geometry.getBounds().getCenterLonLat(),
+ null,
+ "This fault (" + e.feature.attributes[this.fixmystreet.asset_id_field] + ")<br />has been reported.",
+ { size: new OpenLayers.Size(0, 0), offset: new OpenLayers.Pixel(0, 0) },
+ true, close_fault_popup);
+ fixmystreet.map.addPopup(fault_popup);
+ get_select_control(this).unselect(e.feature);
+ return;
+ }
+
+ // Set the extra field to the value of the selected feature
+ $.each(this.fixmystreet.attributes, function (field_name, attribute_name) {
+ var id = e.feature.attributes[attribute_name];
+ $("#form_" + field_name).val(id);
+ });
+
+ // Hide the normal markers layer to keep things simple, but
+ // move the green marker to the point of the click to stop
+ // it jumping around unexpectedly if the user deselects street light.
+ fixmystreet.markers.setVisibility(false);
+ fixmystreet.markers.features[0].move(lonlat);
+
+ // Need to ensure the correct coords are used for the report
+ fixmystreet.maps.update_pin(lonlat);
+
+ // Make sure the marker that was clicked is drawn on top of its neighbours
+ var layer = e.feature.layer;
+ var feature = e.feature;
+ layer.eraseFeatures([feature]);
+ layer.drawFeature(feature);
+
+ // Keep track of selection in case layer is reloaded or hidden etc.
+ selected_feature = feature.clone();
+}
+
+function asset_unselected(e) {
+ fixmystreet.markers.setVisibility(true);
+ $.each(this.fixmystreet.attributes, function (field_name, attribute_name) {
+ $("#form_" + field_name).val("");
+ });
+ selected_feature = null;
+}
+
+function find_matching_feature(feature, layer, asset_id_field) {
+ if (!layer) {
+ return false;
+ }
+ // When the WFS layer is reloaded the same features might be visible
+ // but they'll be different instances of the class so we can't use
+ // object identity comparisons.
+ // This function will find the best matching feature based on its
+ // attributes and distance from the original feature.
+ var threshold = 1; // metres
+ for (var i = 0; i < layer.features.length; i++) {
+ var candidate = layer.features[i];
+ var distance = candidate.geometry.distanceTo(feature.geometry);
+ if (candidate.attributes[asset_id_field] == feature.attributes[asset_id_field] && distance <= threshold) {
+ return candidate;
+ }
+ }
+}
+
+function check_zoom_message_visibility() {
+ var category = $("#problem_form select#form_category").val(),
+ prefix = this.fixmystreet.asset_category.replace(/[^a-z]/gi, ''),
+ id = "category_meta_message_" + prefix,
+ $p = $('#' + id);
+ if (category == this.fixmystreet.asset_category) {
+ if ($p.length === 0) {
+ $p = $("<p>").prop("id", id).prop('class', 'category_meta_message');
+ $p.insertAfter('#form_category_row');
+ }
+
+ if (this.getVisibility() && this.inRange) {
+ $p.html('Or pick a <b class="asset-' + this.fixmystreet.asset_type + '">' + this.fixmystreet.asset_item + '</b> from the map &raquo;');
+ } else {
+ $p.html('Or zoom in and pick a ' + this.fixmystreet.asset_item + ' from the map');
+ }
+
+ } else {
+ $p.remove();
+ }
+}
+
+function layer_visibilitychanged() {
+ check_zoom_message_visibility.call(this);
+ var layers = fixmystreet.map.getLayersByName('WFS');
+ var visible = 0;
+ for (var i = 0; i<layers.length; i++) {
+ if (layers[i].getVisibility()) {
+ visible++;
+ }
+ }
+ if (visible === 2 || visible === 0) {
+ // We're either switching WFS layers (so going 1->2->1 or 1->0->1)
+ // or switching off WFS layer (so going 1->0). Either way, we want
+ // to show the marker again.
+ fixmystreet.markers.setVisibility(true);
+ }
+ select_nearest_asset.call(this);
+}
+
+function zoom_to_assets(layer) {
+ // This function is called when the asset category is
+ // selected, and will zoom the map in to the first level that
+ // makes the asset layer visible if it's not already shown.
+ if (!layer.inRange) {
+ var firstVisibleResolution = layer.resolutions[0];
+ var zoomLevel = fixmystreet.map.getZoomForResolution(firstVisibleResolution);
+ fixmystreet.map.zoomTo(zoomLevel);
+ }
+}
+
+function get_select_control(layer) {
+ var controls = fixmystreet.map.getControlsByClass('OpenLayers.Control.SelectFeature');
+ for (var i=0; i<controls.length; i++) {
+ var control = controls[i];
+ if (control.layer == layer && !control.hover) {
+ return control;
+ }
+ }
+}
+
+function select_nearest_asset() {
+ // The user's green marker might be on the map the first time we show the
+ // assets, so snap it to the closest asset marker if so.
+ if (!fixmystreet.markers.getVisibility() || !(this.getVisibility() && this.inRange)) {
+ return;
+ }
+ var threshold = 50; // metres
+ var marker = fixmystreet.markers.features[0];
+ if (marker === undefined) {
+ // No marker to be found so bail out
+ return;
+ }
+ var closest_feature;
+ var closest_distance = null;
+ for (var i = 0; i < this.features.length; i++) {
+ var candidate = this.features[i];
+ var distance = candidate.geometry.distanceTo(marker.geometry);
+ if (closest_distance === null || distance < closest_distance) {
+ closest_feature = candidate;
+ closest_distance = distance;
+ }
+ }
+ if (closest_distance <= threshold && !!closest_feature) {
+ get_select_control(this).select(closest_feature);
+ }
+}
+
+function layer_loadend() {
+ select_nearest_asset.call(this);
+ // Preserve the selected marker when panning/zooming, if it's still on the map
+ if (selected_feature !== null && !(selected_feature in this.selectedFeatures)) {
+ var replacement_feature = find_matching_feature(selected_feature, this, this.fixmystreet.asset_id_field);
+ if (!!replacement_feature) {
+ get_select_control(this).select(replacement_feature);
+ }
+ }
+}
+
+function get_asset_stylemap() {
+ return new OpenLayers.StyleMap({
+ 'default': new OpenLayers.Style({
+ fillColor: "#FFFF00",
+ fillOpacity: 0.6,
+ strokeColor: "#000000",
+ strokeOpacity: 0.8,
+ strokeWidth: 2,
+ pointRadius: 6
+ }),
+ 'select': new OpenLayers.Style({
+ externalGraphic: fixmystreet.pin_prefix + "pin-spot.png",
+ fillColor: "#55BB00",
+ graphicWidth: 48,
+ graphicHeight: 64,
+ graphicXOffset: -24,
+ graphicYOffset: -56,
+ backgroundGraphic: fixmystreet.pin_prefix + "pin-shadow.png",
+ backgroundWidth: 60,
+ backgroundHeight: 30,
+ backgroundXOffset: -7,
+ backgroundYOffset: -22,
+ popupYOffset: -40,
+ graphicOpacity: 1.0
+ }),
+ 'temporary': new OpenLayers.Style({
+ fillColor: "#55BB00",
+ fillOpacity: 0.8,
+ strokeColor: "#000000",
+ strokeOpacity: 1,
+ strokeWidth: 2,
+ pointRadius: 8,
+ cursor: 'pointer'
+ })
+ });
+}
+
+function get_fault_stylemap() {
+ return new OpenLayers.StyleMap({
+ 'default': new OpenLayers.Style({
+ fillColor: "#FF6600",
+ fillOpacity: 1,
+ strokeColor: "#FF6600",
+ strokeOpacity: 1,
+ strokeWidth: 1.25,
+ pointRadius: 8
+ })
+ });
+}
+
+fixmystreet.add_assets = function(options) {
+ var asset_layer = null;
+ var asset_fault_layer = null;
+
+ function add_assets() {
+ if (asset_layer !== null) {
+ // Layer has already been added
+ return;
+ }
+ if (window.fixmystreet === undefined) {
+ // We're on a page without a map, yet somehow still got called...
+ // Nothing to do.
+ return;
+ }
+ if (fixmystreet.map === undefined) {
+ // Map's not loaded yet, let's try again soon...
+ setTimeout(add_assets, 250);
+ return;
+ }
+ if (fixmystreet.page != 'new' && fixmystreet.page != 'around') {
+ // We only want to show light markers when making a new report
+ return;
+ }
+
+ // An interactive layer for selecting a street light
+ var protocol_options = {
+ version: "1.1.0",
+ url: options.wfs_url,
+ featureType: options.wfs_feature,
+ geometryName: options.geometryName
+ };
+ if (fixmystreet.wmts_config) {
+ protocol_options.srsName = fixmystreet.wmts_config.map_projection;
+ }
+ var protocol = new OpenLayers.Protocol.WFS(protocol_options);
+ var layer_options = {
+ fixmystreet: options,
+ strategies: [new OpenLayers.Strategy.BBOX()],
+ protocol: protocol,
+ visibility: false,
+ maxResolution: options.max_resolution,
+ minResolution: options.min_resolution,
+ styleMap: get_asset_stylemap()
+ };
+ if (fixmystreet.wmts_config) {
+ layer_options.projection = new OpenLayers.Projection(fixmystreet.wmts_config.map_projection);
+ }
+ if (options.filter_key) {
+ layer_options.filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.EQUAL_TO,
+ property: options.filter_key,
+ value: options.filter_value
+ });
+ }
+ asset_layer = new OpenLayers.Layer.Vector("WFS", layer_options);
+
+ // A non-interactive layer to display existing street light faults
+ if (options.wfs_fault_feature) {
+ var po = {
+ featureType: options.wfs_fault_feature
+ };
+ OpenLayers.Util.applyDefaults(po, protocol_options);
+ var fault_protocol = new OpenLayers.Protocol.WFS(po);
+ var lo = {
+ strategies: [new OpenLayers.Strategy.BBOX()],
+ protocol: fault_protocol,
+ styleMap: get_fault_stylemap()
+ };
+ OpenLayers.Util.applyDefaults(lo, layer_options);
+ asset_fault_layer = new OpenLayers.Layer.Vector("WFS", lo);
+ asset_layer.fixmystreet.fault_layer = asset_fault_layer;
+ }
+
+ // Set up handlers for selecting/unselecting markers and panning/zooming the map
+ var select_feature_control = new OpenLayers.Control.SelectFeature( asset_layer );
+ asset_layer.events.register( 'featureselected', asset_layer, asset_selected);
+ asset_layer.events.register( 'featureunselected', asset_layer, asset_unselected);
+ asset_layer.events.register( 'loadend', asset_layer, layer_loadend);
+ asset_layer.events.register( 'visibilitychanged', asset_layer, layer_visibilitychanged);
+ fixmystreet.map.events.register( 'zoomend', asset_layer, check_zoom_message_visibility);
+ // Set up handlers for simply hovering over a street light marker
+ var hover_feature_control = new OpenLayers.Control.SelectFeature(
+ asset_layer,
+ {
+ hover: true,
+ highlightOnly: true,
+ renderIntent: 'temporary'
+ }
+ );
+ hover_feature_control.events.register('beforefeaturehighlighted', null, function(e) {
+ // Don't let marker go from selected->hover state,
+ // as it causes some mad flickering effect.
+ if (e.feature.renderIntent == 'select') {
+ return false;
+ }
+ });
+
+ fixmystreet.map.addLayer(asset_layer);
+ if (asset_fault_layer) {
+ fixmystreet.map.addLayer(asset_fault_layer);
+ }
+ fixmystreet.map.addControl( hover_feature_control );
+ hover_feature_control.activate();
+ fixmystreet.map.addControl( select_feature_control );
+ select_feature_control.activate();
+
+ // Make sure the fault markers always appear beneath the street lights
+ if (asset_fault_layer) {
+ asset_fault_layer.setZIndex(asset_layer.getZIndex()-1);
+ }
+
+ // Show/hide the asset layer when the category is chosen
+ $("#problem_form").on("change.category", "select#form_category", function(){
+ var category = $(this).val();
+ if (category == options.asset_category) {
+ asset_layer.setVisibility(true);
+ if (asset_fault_layer) {
+ asset_fault_layer.setVisibility(true);
+ }
+ zoom_to_assets(asset_layer);
+ } else {
+ asset_layer.setVisibility(false);
+ if (asset_fault_layer) {
+ asset_fault_layer.setVisibility(false);
+ }
+ }
+ });
+ }
+
+ // Make sure the assets get hidden if the back button is pressed
+ fixmystreet.maps.display_around = (function(original) {
+ function hide_assets() {
+ asset_layer.setVisibility(false);
+ if (asset_fault_layer) {
+ asset_fault_layer.setVisibility(false);
+ }
+ fixmystreet.markers.setVisibility(true);
+ original.apply(fixmystreet.maps);
+ }
+ return hide_assets;
+ })(fixmystreet.maps.display_around);
+
+ return add_assets;
+};
+
+})();
diff --git a/web/cobrands/sass/_base.scss b/web/cobrands/sass/_base.scss
index 7cb47af6a..f3753905b 100644
--- a/web/cobrands/sass/_base.scss
+++ b/web/cobrands/sass/_base.scss
@@ -2041,6 +2041,18 @@ table.nicetable {
}
}
+.asset-spot:before {
+ content: "";
+ display: inline-block;
+ width: 10px;
+ height: 10px;
+ border: 2px solid #000;
+ background-color: #ffff00;
+ margin: 0 0.3em 0 0.2em;
+ border-radius: 100%;
+ vertical-align: -2px;
+}
+
@import "_admin";
@import "_fixedthead";
@import "_dropzone";
diff --git a/web/cobrands/sass/_layout.scss b/web/cobrands/sass/_layout.scss
index e7ccd5b03..48fdf32c0 100644
--- a/web/cobrands/sass/_layout.scss
+++ b/web/cobrands/sass/_layout.scss
@@ -455,6 +455,12 @@ body.mappage.admin {
}
}
+.category_meta_message {
+ padding-top: 0.5em;
+ font-size: 0.9em;
+ text-align: center;
+}
+
#skip-this-step {
display: block;
color: inherit;