diff options
author | Marius Halden <marius.h@lden.org> | 2016-12-16 15:02:53 +0100 |
---|---|---|
committer | Marius Halden <marius.h@lden.org> | 2016-12-16 15:02:53 +0100 |
commit | dbf56159e44c1560a413022451bf1a1c4cb22a52 (patch) | |
tree | 275599a1894ca48d8dbf3c2843064c3dbf4affc7 /web | |
parent | a1603b96cae9258761f8cc59d76e0512f49afc3d (diff) | |
parent | 38490f6ea18064c232bda6ebfbaee052bd8f0951 (diff) |
Merge tag 'v2.0.1' into fiksgatami-dev-v2
Diffstat (limited to 'web')
-rw-r--r-- | web/cobrands/bromley/map.js | 1 | ||||
-rw-r--r-- | web/cobrands/fixmystreet/fixmystreet.js | 112 | ||||
-rw-r--r-- | web/cobrands/sass/_base.scss | 2 | ||||
-rw-r--r-- | web/cobrands/sass/_report_list_pins.scss | 8 | ||||
-rw-r--r-- | web/js/OpenLayers/OpenLayers.fixmystreet.js | 4 | ||||
-rw-r--r-- | web/js/OpenLayers/theme/default/style.css | 3 | ||||
-rw-r--r-- | web/js/map-OpenLayers.js | 87 | ||||
-rw-r--r-- | web/js/map-fms.js | 3 | ||||
-rw-r--r-- | web/js/map-google.js | 3 |
9 files changed, 179 insertions, 44 deletions
diff --git a/web/cobrands/bromley/map.js b/web/cobrands/bromley/map.js new file mode 100644 index 000000000..0753907cc --- /dev/null +++ b/web/cobrands/bromley/map.js @@ -0,0 +1 @@ +fixmystreet.maps.tile_base = [ [ "", "a-" ], "https://{S}fix.bromley.gov.uk/tilma" ]; diff --git a/web/cobrands/fixmystreet/fixmystreet.js b/web/cobrands/fixmystreet/fixmystreet.js index fed983a2c..e4c5ba71c 100644 --- a/web/cobrands/fixmystreet/fixmystreet.js +++ b/web/cobrands/fixmystreet/fixmystreet.js @@ -390,6 +390,87 @@ $.extend(fixmystreet.set_up, { }); }, + manage_duplicates: function() { + // Deal with changes to report state by inspector/other staff, specifically + // displaying nearby reports if it's changed to 'duplicate'. + function refresh_duplicate_list() { + var report_id = $("#report_inspect_form .js-report-id").text(); + var args = { + filter_category: $("#report_inspect_form select#category").val(), + latitude: $('input[name="latitude"]').val(), + longitude: $('input[name="longitude"]').val() + }; + $("#js-duplicate-reports ul").html("<li>Loading...</li>"); + var nearby_url = '/report/'+report_id+'/nearby.json'; + $.getJSON(nearby_url, args, function(data) { + var duplicate_of = $("#report_inspect_form [name=duplicate_of]").val(); + var $reports = $(data.current) + .filter("li") + .not("[data-report-id="+report_id+"]") + .slice(0, 5); + $reports.filter("[data-report-id="+duplicate_of+"]").addClass("item-list--reports__item--selected"); + + (function() { + var timeout; + $reports.on('mouseenter', function(){ + clearTimeout(timeout); + fixmystreet.maps.markers_highlight(parseInt($(this).data('reportId'), 10)); + }).on('mouseleave', function(){ + timeout = setTimeout(fixmystreet.maps.markers_highlight, 50); + }); + })(); + + $("#js-duplicate-reports ul").empty().prepend($reports); + + $reports.find("a").click(function() { + var report_id = $(this).closest("li").data('reportId'); + $("#report_inspect_form [name=duplicate_of]").val(report_id); + $("#js-duplicate-reports ul li").removeClass("item-list--reports__item--selected"); + $(this).closest("li").addClass("item-list--reports__item--selected"); + return false; + }); + + show_nearby_pins(data, report_id); + }); + } + + function show_nearby_pins(data, report_id) { + var markers = fixmystreet.maps.markers_list( data.pins, true ); + // We're replacing all the features in the markers layer with the + // possible duplicates, but the list of pins from the server doesn't + // include the current report. So we need to extract the feature for + // the current report and include it in the list of features we're + // showing on the layer. + var report_marker = fixmystreet.maps.get_marker_by_id(parseInt(report_id, 10)); + if (report_marker) { + markers.unshift(report_marker); + } + fixmystreet.markers.removeAllFeatures(); + fixmystreet.markers.addFeatures( markers ); + } + + function state_change() { + // The duplicate report list only makes sense when state is 'duplicate' + if ($(this).val() !== "duplicate") { + $("#js-duplicate-reports").addClass("hidden"); + return; + } else { + $("#js-duplicate-reports").removeClass("hidden"); + } + // If this report is already marked as a duplicate of another, then + // there's no need to refresh the list of duplicate reports + var duplicate_of = $("#report_inspect_form [name=duplicate_of]").val(); + if (!!duplicate_of) { + return; + } + + refresh_duplicate_list(); + } + + $("#report_inspect_form").on("change.state", "select#state", state_change); + $("#js-change-duplicate-report").click(refresh_duplicate_list); + }, + contribute_as: function() { $('.content').on('change', '.js-contribute-as', function(){ @@ -563,6 +644,9 @@ $.extend(fixmystreet.set_up, { return; } + // Focus on form + $('html,body').scrollTop($('#report_inspect_form').offset().top); + // On the manage/inspect report form, we already have all the extra inputs // in the DOM, we just need to hide/show them as appropriate. $('form#report_inspect_form [name=category]').change(function() { @@ -570,8 +654,33 @@ $.extend(fixmystreet.set_up, { selector = "[data-category='" + category + "']"; $("form#report_inspect_form [data-category]:not(" + selector + ")").addClass("hidden"); $("form#report_inspect_form " + selector).removeClass("hidden"); + // And update the associated priority list + var priorities = $("form#report_inspect_form " + selector).data('priorities'); + var $select = $('#problem_priority'), + curr_pri = $select.val(); + $select.find('option:gt(0)').remove(); + $.each(priorities.split('&'), function(i, kv) { + if (!kv) { + return; + } + kv = kv.split('=', 2); + $select.append($('<option>', { value: kv[0], text: decodeURIComponent(kv[1]) })); + }); + $select.val(curr_pri); }); + // The inspect form submit button can change depending on the selected state + $("#report_inspect_form [name=state]").change(function(){ + var state = $(this).val(); + var $submit = $("#report_inspect_form input[type=submit]"); + var value = $submit.attr('data-value-'+state); + if (value !== undefined) { + $submit.val(value); + } else { + $submit.val($submit.data('valueOriginal')); + } + }).change(); + $('.js-toggle-public-update').each(function() { var $checkbox = $(this); var toggle_public_update = function() { @@ -943,7 +1052,7 @@ fixmystreet.update_pin = function(lonlat, savePushState) { // something from it, then pre-fill the category field in the report, // if it's a value already present in the drop-down. var category = $("#filter_categories").val(); - if (category !== undefined && $("#form_category option[value="+category+"]").length) { + if (category !== undefined && $("#form_category option[value='"+category+"']").length) { $("#form_category").val(category); } @@ -1090,6 +1199,7 @@ fixmystreet.display = { $twoColReport.appendTo('#map_sidebar'); $('body').addClass('with-actions'); fixmystreet.set_up.report_page_inspect(); + fixmystreet.set_up.manage_duplicates(); } else { $sideReport.appendTo('#map_sidebar'); } diff --git a/web/cobrands/sass/_base.scss b/web/cobrands/sass/_base.scss index f3753905b..7fb0c797f 100644 --- a/web/cobrands/sass/_base.scss +++ b/web/cobrands/sass/_base.scss @@ -289,7 +289,7 @@ select.form-control { &[multiple] { height: auto; } - .js &[multiple] { + .js &.js-multiple[multiple] { height: 2.2em; } } diff --git a/web/cobrands/sass/_report_list_pins.scss b/web/cobrands/sass/_report_list_pins.scss index 74f0a5f90..eaeefbc10 100644 --- a/web/cobrands/sass/_report_list_pins.scss +++ b/web/cobrands/sass/_report_list_pins.scss @@ -50,6 +50,14 @@ color: #777; } } +.item-list--reports__item--selected { + background: $base_bg; + + a, a:hover, a:focus { + background-color: transparent; + } +} + .item-list__item--empty { background: none; diff --git a/web/js/OpenLayers/OpenLayers.fixmystreet.js b/web/js/OpenLayers/OpenLayers.fixmystreet.js index cfa4c2bee..df0a88c98 100644 --- a/web/js/OpenLayers/OpenLayers.fixmystreet.js +++ b/web/js/OpenLayers/OpenLayers.fixmystreet.js @@ -225,8 +225,8 @@ if(g)for(var h=0;!f&&h<g.length;){var k=g[h];if(k.name==b&&k.observer==c&&k.useC !1}},CLASS_NAME:"OpenLayers.Event"};OpenLayers.Event.observe(window,"unload",OpenLayers.Event.unloadCache,!1); OpenLayers.Events=OpenLayers.Class({BROWSER_EVENTS:"mouseover mouseout mousedown mouseup mousemove click dblclick rightclick dblrightclick resize focus blur touchstart touchmove touchend keydown".split(" "),TOUCH_MODEL_POINTER:"pointer",TOUCH_MODEL_MSPOINTER:"MSPointer",TOUCH_MODEL_TOUCH:"touch",listeners:null,object:null,element:null,eventHandler:null,fallThrough:null,includeXY:!1,extensions:null,extensionCount:null,clearMouseListener:null,initialize:function(a,b,c,d,e){OpenLayers.Util.extend(this, e);this.object=a;this.fallThrough=d;this.listeners={};this.extensions={};this.extensionCount={};this._pointerTouches=[];null!=b&&this.attachToElement(b)},destroy:function(){for(var a in this.extensions)"boolean"!==typeof this.extensions[a]&&this.extensions[a].destroy();this.extensions=null;this.element&&(OpenLayers.Event.stopObservingElement(this.element),this.element.hasScrollEvent&&OpenLayers.Event.stopObserving(window,"scroll",this.clearMouseListener));this.eventHandler=this.fallThrough=this.object= -this.listeners=this.element=null},addEventType:function(a){},attachToElement:function(a){this.element?OpenLayers.Event.stopObservingElement(this.element):(this.eventHandler=OpenLayers.Function.bindAsEventListener(this.handleBrowserEvent,this),this.clearMouseListener=OpenLayers.Function.bind(this.clearMouseCache,this));this.element=a;for(var b=this.getTouchModel(),c,d=0,e=this.BROWSER_EVENTS.length;d<e;d++)c=this.BROWSER_EVENTS[d],OpenLayers.Event.observe(a,c,this.eventHandler),b!==this.TOUCH_MODEL_POINTER&& -b!==this.TOUCH_MODEL_MSPOINTER||0!==c.indexOf("touch")||this.addPointerTouchListener(a,c,this.eventHandler);OpenLayers.Event.observe(a,"dragstart",OpenLayers.Event.stop)},on:function(a){for(var b in a)"scope"!=b&&a.hasOwnProperty(b)&&this.register(b,a.scope,a[b])},register:function(a,b,c,d){a in OpenLayers.Events&&!this.extensions[a]&&(this.extensions[a]=new OpenLayers.Events[a](this));if(null!=c){null==b&&(b=this.object);var e=this.listeners[a];e||(e=[],this.listeners[a]=e,this.extensionCount[a]= +this.listeners=this.element=null},addEventType:function(a){},attachToElement:function(a){this.element?OpenLayers.Event.stopObservingElement(this.element):(this.eventHandler=OpenLayers.Function.bindAsEventListener(this.handleBrowserEvent,this),this.clearMouseListener=OpenLayers.Function.bind(this.clearMouseCache,this));this.element=a;for(var b=this.getTouchModel(),c,d=0,e=this.BROWSER_EVENTS.length;d<e;d++){c=this.BROWSER_EVENTS[d];(b===this.TOUCH_MODEL_POINTER|| +b===this.TOUCH_MODEL_MSPOINTER)&&0===c.indexOf("touch")?this.addPointerTouchListener(a,c,this.eventHandler):OpenLayers.Event.observe(a,c,this.eventHandler);}OpenLayers.Event.observe(a,"dragstart",OpenLayers.Event.stop)},on:function(a){for(var b in a)"scope"!=b&&a.hasOwnProperty(b)&&this.register(b,a.scope,a[b])},register:function(a,b,c,d){a in OpenLayers.Events&&!this.extensions[a]&&(this.extensions[a]=new OpenLayers.Events[a](this));if(null!=c){null==b&&(b=this.object);var e=this.listeners[a];e||(e=[],this.listeners[a]=e,this.extensionCount[a]= 0);b={obj:b,func:c};d?(e.splice(this.extensionCount[a],0,b),"object"===typeof d&&d.extension&&this.extensionCount[a]++):e.push(b)}},registerPriority:function(a,b,c){this.register(a,b,c,!0)},un:function(a){for(var b in a)"scope"!=b&&a.hasOwnProperty(b)&&this.unregister(b,a.scope,a[b])},unregister:function(a,b,c){null==b&&(b=this.object);a=this.listeners[a];if(null!=a)for(var d=0,e=a.length;d<e;d++)if(a[d].obj==b&&a[d].func==c){a.splice(d,1);break}},remove:function(a){null!=this.listeners[a]&&(this.listeners[a]= [])},triggerEvent:function(a,b){var c=this.listeners[a];if(c&&0!=c.length){null==b&&(b={});b.object=this.object;b.element=this.element;b.type||(b.type=a);for(var c=c.slice(),d,e=0,f=c.length;e<f&&(d=c[e],d=d.func.apply(d.obj,[b]),void 0==d||0!=d);e++);this.fallThrough||OpenLayers.Event.stop(b,!0);return d}},handleBrowserEvent:function(a){var b=a.type,c=this.listeners[b];if(c&&0!=c.length){if((c=a.touches)&&c[0]){for(var d=0,e=0,f=c.length,g,h=0;h<f;++h)g=this.getTouchClientXY(c[h]),d+=g.clientX,e+= g.clientY;a.clientX=d/f;a.clientY=e/f}this.includeXY&&(a.xy=this.getMousePosition(a));this.triggerEvent(b,a)}},getTouchClientXY:function(a){var b=window.olMockWin||window,c=b.pageXOffset,b=b.pageYOffset,d=a.clientX,e=a.clientY;if(0===a.pageY&&Math.floor(e)>Math.floor(a.pageY)||0===a.pageX&&Math.floor(d)>Math.floor(a.pageX))d-=c,e-=b;else if(e<a.pageY-b||d<a.pageX-c)d=a.pageX-c,e=a.pageY-b;a.olClientX=d;a.olClientY=e;return{clientX:d,clientY:e}},clearMouseCache:function(){this.element.scrolls=null; diff --git a/web/js/OpenLayers/theme/default/style.css b/web/js/OpenLayers/theme/default/style.css index cbed84e8c..cefab060b 100644 --- a/web/js/OpenLayers/theme/default/style.css +++ b/web/js/OpenLayers/theme/default/style.css @@ -3,11 +3,12 @@ div.olMap { padding: 0 !important; margin: 0 !important; cursor: default; + -ms-touch-action: none; + touch-action: none; } div.olMapViewport { text-align: left; - -ms-touch-action: none; } div.olLayerDiv { diff --git a/web/js/map-OpenLayers.js b/web/js/map-OpenLayers.js index 3de8e4d1f..49801911b 100644 --- a/web/js/map-OpenLayers.js +++ b/web/js/map-OpenLayers.js @@ -90,7 +90,8 @@ var fixmystreet = fixmystreet || {}; size: pin[5] || marker_size, faded: 0, id: pin[3], - title: pin[4] || '' + title: pin[4] || '', + draggable: pin[6] === false ? false : true }); markers.push( marker ); } @@ -144,7 +145,7 @@ var fixmystreet = fixmystreet || {}; admin_drag: function(pin_moved_callback, confirm_change) { confirm_change = confirm_change || false; var original_lonlat; - var drag = new OpenLayers.Control.DragFeature( fixmystreet.markers, { + var drag = new OpenLayers.Control.DragFeatureFMS( fixmystreet.markers, { onStart: function(feature, e) { // Keep track of where the feature started, so we can put it // back if the user cancels the operation. @@ -167,12 +168,41 @@ var fixmystreet = fixmystreet || {}; } ); fixmystreet.map.addControl( drag ); drag.activate(); + }, + + // `markers.redraw()` in markers_highlight will trigger an + // `overFeature` event if the mouse cursor is still over the same + // marker on the map, which would then run markers_highlight + // again, causing an infinite flicker while the cursor remains over + // the same marker. We really only want to redraw the markers when + // the cursor moves from one marker to another (ie: when there is an + // overFeature followed by an outFeature followed by an overFeature). + // Therefore, we keep track of the previous event in + // fixmystreet.latest_map_hover_event and only call markers_highlight + // if we know the previous event was different to the current one. + // (See the `overFeature` and `outFeature` callbacks inside of + // fixmystreet.select_feature). + + markers_highlight: function(problem_id) { + for (var i = 0; i < fixmystreet.markers.features.length; i++) { + if (typeof problem_id == 'undefined') { + // There is no highlighted marker, so unfade this marker + fixmystreet.markers.features[i].attributes.faded = 0; + } else if (problem_id == fixmystreet.markers.features[i].attributes.id) { + // This is the highlighted marker, unfade it + fixmystreet.markers.features[i].attributes.faded = 0; + } else { + // This is not the hightlighted marker, fade it + fixmystreet.markers.features[i].attributes.faded = 1; + } + } + fixmystreet.markers.redraw(); } }; var drag = { activate: function() { - this._drag = new OpenLayers.Control.DragFeature( fixmystreet.markers, { + this._drag = new OpenLayers.Control.DragFeatureFMS( fixmystreet.markers, { onComplete: function(feature, e) { fixmystreet.update_pin( feature.geometry ); } @@ -195,35 +225,6 @@ var fixmystreet = fixmystreet || {}; fixmystreet.map.setCenter(center, z); } - // `markers.redraw()` in markers_highlight will trigger an - // `overFeature` event if the mouse cursor is still over the same - // marker on the map, which would then run markers_highlight - // again, causing an infinite flicker while the cursor remains over - // the same marker. We really only want to redraw the markers when - // the cursor moves from one marker to another (ie: when there is an - // overFeature followed by an outFeature followed by an overFeature). - // Therefore, we keep track of the previous event in - // fixmystreet.latest_map_hover_event and only call markers_highlight - // if we know the previous event was different to the current one. - // (See the `overFeature` and `outFeature` callbacks inside of - // fixmystreet.select_feature). - - function markers_highlight(problem_id) { - for (var i = 0; i < fixmystreet.markers.features.length; i++) { - if (typeof problem_id == 'undefined') { - // There is no highlighted marker, so unfade this marker - fixmystreet.markers.features[i].attributes.faded = 0; - } else if (problem_id == fixmystreet.markers.features[i].attributes.id) { - // This is the highlighted marker, unfade it - fixmystreet.markers.features[i].attributes.faded = 0; - } else { - // This is not the hightlighted marker, fade it - fixmystreet.markers.features[i].attributes.faded = 1; - } - } - fixmystreet.markers.redraw(); - } - function sidebar_highlight(problem_id) { if (typeof problem_id !== 'undefined') { var $a = $('.item-list--reports a[href$="/' + problem_id + '"]'); @@ -505,7 +506,7 @@ var fixmystreet = fixmystreet || {}; overFeature: function (feature) { if (fixmystreet.latest_map_hover_event != 'overFeature') { document.getElementById('map').style.cursor = 'pointer'; - markers_highlight(feature.attributes.id); + fixmystreet.maps.markers_highlight(feature.attributes.id); sidebar_highlight(feature.attributes.id); fixmystreet.latest_map_hover_event = 'overFeature'; } @@ -513,7 +514,7 @@ var fixmystreet = fixmystreet || {}; outFeature: function (feature) { if (fixmystreet.latest_map_hover_event != 'outFeature') { document.getElementById('map').style.cursor = ''; - markers_highlight(); + fixmystreet.maps.markers_highlight(); sidebar_highlight(); fixmystreet.latest_map_hover_event = 'outFeature'; } @@ -606,6 +607,7 @@ var fixmystreet = fixmystreet || {}; // Create the basics of the map fixmystreet.map = new OpenLayers.Map( "map", OpenLayers.Util.extend({ + theme: null, controls: fixmystreet.controls, displayProjection: new OpenLayers.Projection("EPSG:4326") }, fixmystreet.map_options) @@ -665,9 +667,9 @@ var fixmystreet = fixmystreet || {}; var href = $('a', this).attr('href'); var id = parseInt(href.replace(/^.*[/]([0-9]+)$/, '$1')); clearTimeout(timeout); - markers_highlight(id); + fixmystreet.maps.markers_highlight(id); }).on('mouseleave', '.item-list--reports__item', function(){ - timeout = setTimeout(markers_highlight, 50); + timeout = setTimeout(fixmystreet.maps.markers_highlight, 50); }); })(); }); @@ -887,6 +889,19 @@ OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control, { } }); +/* Drag handler that allows individual features to disable dragging */ +OpenLayers.Control.DragFeatureFMS = OpenLayers.Class(OpenLayers.Control.DragFeature, { + CLASS_NAME: "OpenLayers.Control.DragFeatureFMS", + + overFeature: function(feature) { + if (feature.attributes.draggable) { + return OpenLayers.Control.DragFeature.prototype.overFeature.call(this, feature); + } else { + return false; + } + } +}) + OpenLayers.Renderer.SVGBig = OpenLayers.Class(OpenLayers.Renderer.SVG, { MAX_PIXEL: 15E7, CLASS_NAME: "OpenLayers.Renderer.SVGBig" diff --git a/web/js/map-fms.js b/web/js/map-fms.js index 65c02a503..61206a90a 100644 --- a/web/js/map-fms.js +++ b/web/js/map-fms.js @@ -2,9 +2,6 @@ fixmystreet.maps.tile_base = [ [ '', 'a-', 'b-', 'c-' ], '//{S}tilma.mysociety.o fixmystreet.maps.config = (function(original) { return function(){ - if (fixmystreet.map_type) { - this.tile_base = fixmystreet.map_type; - } original(); fixmystreet.map_type = OpenLayers.Layer.BingUK; }; diff --git a/web/js/map-google.js b/web/js/map-google.js index 4c3f6188e..be2df8502 100644 --- a/web/js/map-google.js +++ b/web/js/map-google.js @@ -56,6 +56,9 @@ fixmystreet.maps = {}; google.maps.event.trigger(fixmystreet.map, 'idle'); }; + // This is a noop on Google Maps right now. + fixmystreet.maps.markers_highlight = function() {}; + function PaddingControl(div) { div.style.padding = '40px'; } |