From a69d425c0e5c004145ac1ab70e2f7f9fc329b54c Mon Sep 17 00:00:00 2001 From: Struan Donald Date: Fri, 3 Oct 2014 15:07:08 +0100 Subject: update Android to Cordova 3.6 Required due to security issue Remove Android directory as no longer required, move src -> www to match standard layout, update .gitignore to avoid including the standard platform files, update README based on Steve's zurich one --- www/js/map-OpenLayers.js | 440 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 440 insertions(+) create mode 100644 www/js/map-OpenLayers.js (limited to 'www/js/map-OpenLayers.js') diff --git a/www/js/map-OpenLayers.js b/www/js/map-OpenLayers.js new file mode 100644 index 0000000..8a60e30 --- /dev/null +++ b/www/js/map-OpenLayers.js @@ -0,0 +1,440 @@ +// -*- mode: espresso; espresso-indent-level: 4; indent-tabs-mode: nil -*- + +// This function might be passed either an OpenLayers.LonLat (so has +// lon and lat) or an OpenLayers.Geometry.Point (so has x and y) +function fixmystreet_update_pin(lonlat) { + lonlat.transform( + fixmystreet.map.getProjectionObject(), + new OpenLayers.Projection("EPSG:4326") + ); + document.getElementById('fixmystreet.latitude').value = lonlat.lat || lonlat.y; + document.getElementById('fixmystreet.longitude').value = lonlat.lon || lonlat.x; +} + +function fixmystreet_activate_drag() { + fixmystreet.drag = new OpenLayers.Control.DragFeature( fixmystreet.markers, { + onComplete: function(feature, e) { + fixmystreet_update_pin( feature.geometry.clone() ); + } + } ); + fixmystreet.map.addControl( fixmystreet.drag ); + fixmystreet.drag.activate(); +} + +function fms_markers_list(pins, transform) { + var markers = []; + for (var i=0; i 2) || + (device.platform !== 'Android') ) ) { + location_img = 'images/pin.svg'; + location_bg_img = 'images/pin_shadow.svg'; + } + + pin_layer_style_map.addUniqueValueRules('default', 'size', { + 'normal': { + externalGraphic: "images/pin-${colour}.png", + graphicWidth: 48, + graphicHeight: 64, + graphicXOffset: -24, + graphicYOffset: -64, + backgroundGraphic: "images/pin-shadow.png", + backgroundWidth: 60, + backgroundHeight: 30, + backgroundXOffset: -7, + backgroundYOffset: -30 + }, + 'big': { + externalGraphic: "images/pin-${colour}-big.png", + graphicWidth: 78, + graphicHeight: 105, + graphicXOffset: -39, + graphicYOffset: -105, + backgroundGraphic: "images/pin-shadow-big.png", + backgroundWidth: 88, + backgroundHeight: 40, + backgroundXOffset: -10, + backgroundYOffset: -35 + }, + 'location': { + externalGraphic: location_img, + graphicWidth: 70, + graphicHeight: 110, + graphicXOffset: -35, + graphicYOffset: -110, + backgroundGraphic: location_bg_img, + backgroundWidth: 186, + backgroundHeight: 110, + backgroundXOffset: -93, + backgroundYOffset: -110 + } + }); + var pin_layer_options = { + rendererOptions: { + yOrdering: true + }, + styleMap: pin_layer_style_map + }; + + // This layer is for displaying the location of the current report. + // It's in its own layer as that means canceling a report means we only + // need to switch layer visibility rather than fetching the position of the + // existing reports all over again. + fixmystreet.report_location = new OpenLayers.Layer.Vector("Report", pin_layer_options); + fixmystreet.report_location.setVisibility(false) + fixmystreet.map.addLayer(fixmystreet.report_location); + + if (fixmystreet.page == 'around') { + fixmystreet.bbox_strategy = new OpenLayers.Strategy.BBOX({ ratio: 1 }); + pin_layer_options.strategies = [ fixmystreet.bbox_strategy ]; + pin_layer_options.protocol = new OpenLayers.Protocol.HTTP({ + url: CONFIG.FMS_URL + '/ajax', + params: fixmystreet.all_pins ? { all_pins: 1 } : { }, + format: new OpenLayers.Format.FixMyStreet() + }); + } + fixmystreet.markers = new OpenLayers.Layer.Vector("Pins", pin_layer_options); + fixmystreet.markers.events.register( 'loadend', fixmystreet.markers, function(evt) { + if (fixmystreet.map.popups.length) fixmystreet.map.removePopup(fixmystreet.map.popups[0]); + }); + + fixmystreet.nav = getNavControl(fixmystreet.map); + + var markers = fms_markers_list( fixmystreet.pins, true ); + fixmystreet.markers.addFeatures( markers ); + if (fixmystreet.page == 'around' || fixmystreet.page == 'reports' || fixmystreet.page == 'my') { + fixmystreet.select_feature = new OpenLayers.Control.SelectFeature( fixmystreet.markers ); + var selectedFeature; + function onPopupClose(evt) { + fixmystreet.select_feature.unselect(selectedFeature); + OpenLayers.Event.stop(evt); + } + fixmystreet.markers.events.register( 'featureunselected', fixmystreet.markers, function(evt) { + var feature = evt.feature, popup = feature.popup; + fixmystreet.map.removePopup(popup); + popup.destroy(); + feature.popup = null; + $('#OpenLayers_Control_Crosshairs_crosshairs').show(); + }); + fixmystreet.markers.events.register( 'featureselected', fixmystreet.markers, function(evt) { + var feature = evt.feature; + selectedFeature = feature; + var popup = new OpenLayers.Popup.FramedCloud("popup", + feature.geometry.getBounds().getCenterLonLat(), + null, + feature.attributes.title + "
More details", + { size: new OpenLayers.Size(0,0), offset: new OpenLayers.Pixel(0,-40) }, + true, onPopupClose); + feature.popup = popup; + fixmystreet.map.addPopup(popup); + $('#OpenLayers_Control_Crosshairs_crosshairs').hide(); + }); + fixmystreet.map.addControl( fixmystreet.select_feature ); + fixmystreet.select_feature.activate(); + } else if (fixmystreet.page == 'new') { + fixmystreet_activate_drag(); + } + fixmystreet.map.addLayer(fixmystreet.markers); + + // this layer is for the position of the 'You are here' blue dot + fixmystreet.location = new OpenLayers.Layer.Vector('location'); + fixmystreet.map.addLayer(fixmystreet.location); + + if ( fixmystreet.zoomToBounds ) { + var bounds = fixmystreet.markers.getDataExtent(); + if (bounds) { fixmystreet.map.zoomToExtent( bounds ); } + } + + if (fixmystreet.page == 'around' ) { + fixmystreet.actionafterdrag = new OpenLayers.Control.ActionAfterDrag({'autoActivate': true}); + fixmystreet.map.addControl(fixmystreet.actionafterdrag); + fixmystreet.map.addControl( new OpenLayers.Control.Crosshairs(null) ); + } +} +OpenLayers.Map.prototype.getCurrentSize = function() { + var mapDiv = $(this.div); + return new OpenLayers.Size(mapDiv.width(), mapDiv.height()); +}; + +function show_map(event) { + if (typeof fixmystreet !== 'undefined' && fixmystreet.page == 'around') { + // Immediately go full screen map if on around page + var mapTop = 0; + if ( $('body').hasClass('ios7') ) { + mapTop = 20; + } + $('#map_box').css({ + position: 'fixed', + top: mapTop, left: 0, right: 0, bottom: 0, + height: FMS.windowHeight, + margin: 0 + }); + } else { + $('#map_box').css({ + zIndex: '', position: '', + top: '', left: '', right: '', bottom: '', + width: '', height: '10em', + margin: '' + }); + } + + set_map_config(); + $('#mark-here').hide(); + + fixmystreet.map = new OpenLayers.Map("map", { + controls: fixmystreet.controls, + displayProjection: new OpenLayers.Projection("EPSG:4326") + }); + + fixmystreet.layer_options = OpenLayers.Util.extend({ + zoomOffset: fixmystreet.zoomOffset, + transitionEffect: 'resize', + numZoomLevels: fixmystreet.numZoomLevels + }, fixmystreet.layer_options); + var layer = new fixmystreet.map_type("", fixmystreet.layer_options); + fixmystreet.map.addLayer(layer); + + if (!fixmystreet.map.getCenter()) { + var centre = new OpenLayers.LonLat( fixmystreet.longitude, fixmystreet.latitude ); + FMS.currentPosition = { latitude: centre.lat, longitude: centre.lon }; + centre.transform( + new OpenLayers.Projection("EPSG:4326"), + fixmystreet.map.getProjectionObject() + ); + fixmystreet.map.setCenter(centre, fixmystreet.zoom || 4); + } + + fixmystreet_onload(); + + var crosshairsControls, i, markHere, confirm, newX, newY; + + if (typeof fixmystreet !== 'undefined' && typeof fixmystreet.map !== "undefined") { + // Update the position of any crosshairs controls: + crosshairsControls = fixmystreet.map.getControlsByClass( + "OpenLayers.Control.Crosshairs"); + for (i = 0; i < crosshairsControls.length; ++i) { + crosshairsControls[i].reposition(); + } + } + + if ( fixmystreet.page == 'around' ) { + fixmystreet.nav.activate(); + $('#view-my-reports').show(); + $('#login-options').show(); + $('#mark-here').show(); + } +} + + +OpenLayers.Control.Crosshairs = OpenLayers.Class.create(); +OpenLayers.Control.Crosshairs.CROSSHAIR_SIDE = 106; +OpenLayers.Control.Crosshairs.DIV_ID = "OpenLayers_Control_Crosshairs_crosshairs"; +OpenLayers.Control.Crosshairs.prototype = + OpenLayers.Class.inherit( OpenLayers.Control, { + element: null, + position: null, + + initialize: function(element) { + OpenLayers.Control.prototype.initialize.apply(this, arguments); + this.element = OpenLayers.Util.getElement(element); + this.imageSize = new OpenLayers.Size(OpenLayers.Control.Crosshairs.CROSSHAIR_SIDE, + OpenLayers.Control.Crosshairs.CROSSHAIR_SIDE); + }, + + draw: function() { + var position; + OpenLayers.Control.prototype.draw.apply(this, arguments); + position = this.getIdealPosition(); + this.buttons = new Array(); + // we set the background image in CSS so we can use media queries for retina + // screens so we want an blank image here + var imgLocation = OpenLayers.Util.getImagesLocation() + "blank.gif"; + return OpenLayers.Util.createAlphaImageDiv(OpenLayers.Control.Crosshairs.DIV_ID, + position, this.imageSize, imgLocation, "absolute"); + }, + + getIdealPosition: function() { + this.map.updateSize(); + var mapSize = this.map.getSize(); + var center = this.map.getCenter(); + var px = this.map.getPixelFromLonLat( center ); + return new OpenLayers.Pixel( px.x - ( this.imageSize.w / 2 ), + px.y - ( this.imageSize.h / 2 ) ); + }, + + getMapPosition: function() { + var left = parseInt( $('#' + OpenLayers.Control.Crosshairs.DIV_ID).css('left') ); + var top = parseInt( $('#' + OpenLayers.Control.Crosshairs.DIV_ID).css('top') ); + + left += ( this.imageSize.w / 2 ); + top += ( this.imageSize.h / 2 ); + + var pos = this.map.getLonLatFromViewPortPx( new OpenLayers.Pixel( left, top ) ); + return pos; + }, + + reposition: function() { + var position = this.getIdealPosition(); + $('#' + OpenLayers.Control.Crosshairs.DIV_ID).css({ + left: position.x, + top: position.y}); + }, + + CLASS_NAME: "OpenLayers.Control.Crosshairs" +}); + +OpenLayers.Control.PanZoomFMS = OpenLayers.Class(OpenLayers.Control.PanZoom, { + buttonDown: function (evt) { + if (!OpenLayers.Event.isLeftClick(evt)) { + return; + } + + switch (this.action) { + case "panup": + this.map.pan(0, -this.getSlideFactor("h")); + break; + case "pandown": + this.map.pan(0, this.getSlideFactor("h")); + break; + case "panleft": + this.map.pan(-this.getSlideFactor("w"), 0); + break; + case "panright": + this.map.pan(this.getSlideFactor("w"), 0); + break; + case "zoomin": + this.map.zoomIn(); + break; + case "zoomout": + this.map.zoomOut(); + break; + case "zoomworld": + this.map.zoomTo(0); + break; + } + + OpenLayers.Event.stop(evt); + } +}); + + +/* Pan data handler */ +OpenLayers.Format.FixMyStreet = OpenLayers.Class(OpenLayers.Format.JSON, { + read: function(json, filter) { + if (typeof json == 'string') { + obj = OpenLayers.Format.JSON.prototype.read.apply(this, [json, filter]); + } else { + obj = json; + } + var current, current_near; + if (typeof(obj.current) != 'undefined' && (current = document.getElementById('current'))) { + current.innerHTML = obj.current; + } + if (typeof(obj.current_near) != 'undefined' && (current_near = document.getElementById('current_near'))) { + current_near.innerHTML = obj.current_near; + } + var markers = fms_markers_list( obj.pins, false ); + return markers; + }, + CLASS_NAME: "OpenLayers.Format.FixMyStreet" +}); + +OpenLayers.Control.ActionAfterDrag = OpenLayers.Class(OpenLayers.Control, { + + defaultHandlerOptions: { + 'stopDown': false + /* important, otherwise it prevent the click-drag event from + triggering the normal click-drag behavior on the map to pan it */ + }, + + initialize: function(options) { + this.handlerOptions = OpenLayers.Util.extend( + {}, this.defaultHandlerOptions + ); + OpenLayers.Control.prototype.initialize.apply( + this, arguments + ); + this.handler = new OpenLayers.Handler.Drag( + this, { + 'move': this.onDragStart + }, this.handlerOptions + ); + }, + + onDragStart: function(evt) { + if ( $('#confirm-map').css('display') == 'block' ) { + $('#reposition').show(); + } else { + $('#relocate').show(); + $('#front-howto').hide(); + } + } +}); + + +// Overload the PinchZoom control so we can stop zoom snapback when we +// reach the limit of zooming +OpenLayers.Control.PinchZoom = OpenLayers.Class(OpenLayers.Control.PinchZoom,{ + pinchMove: function(evt,pinchData) { + var maxZoom = fixmystreet.numZoomLevels - 1; + var scale = pinchData.scale; + var containerOrigin = this.containerOrigin; + var pinchOrigin = this.pinchOrigin; + var current = evt.xy; + var dx = Math.round((current.x-pinchOrigin.x) + (scale-1) * (containerOrigin.x-pinchOrigin.x)); + var dy = Math.round((current.y-pinchOrigin.y) + (scale-1) * (containerOrigin.y-pinchOrigin.y)); + + // if we are at the limits of the zoom then do nothing to stop zoom snapback effect + var mapZoom = this.map.getZoom(); + if ( ( ( dx < 0 || dy < 0 ) && mapZoom == maxZoom ) || ( ( dx > 0 || dy > 0 ) && mapZoom == 0 ) ) { + return false; + } + + this.applyTransform("translate("+dx+"px, "+dy+"px) scale("+scale+")"); + this.currentCenter=current; + }, + CLASS_NAME: "OpenLayers.Control.PinchZoom" +}); -- cgit v1.2.3