diff options
-rw-r--r-- | templates/web/angus/maps/fms.html | 3 | ||||
-rw-r--r-- | templates/web/base/report/new/category_wrapper.html | 8 | ||||
-rw-r--r-- | templates/web/bristol/footer_extra_js.html | 4 | ||||
-rw-r--r-- | web/cobrands/angus/base.scss | 12 | ||||
-rw-r--r-- | web/cobrands/angus/js.js | 15 | ||||
-rw-r--r-- | web/cobrands/angus/layout.scss | 6 | ||||
-rw-r--r-- | web/cobrands/angus/position_map.js | 330 | ||||
-rw-r--r-- | web/cobrands/bristol/js.js | 45 | ||||
-rw-r--r-- | web/cobrands/fixmystreet/assets.js | 381 | ||||
-rw-r--r-- | web/cobrands/sass/_base.scss | 12 | ||||
-rw-r--r-- | web/cobrands/sass/_layout.scss | 6 |
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 »'); - } 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 »'); + } 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; |