您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Provides access to certain OS OpenData products within the WME environment
当前为
// ==UserScript== // @name WME OpenData // @namespace http://greasemonkey.chizzum.com // @description Provides access to certain OS OpenData products within the WME environment // @include https://*.waze.com/*editor* // @include https://editor-beta.waze.com/* // @include https://beta.waze.com/* // @include https://one.network/* // @include http://public.londonworks.gov.uk/roadworks/* // @include http://streetworks.wiltshire.gov.uk/* // @include https://openspacewmb.ordnancesurvey.co.uk/osmapapi/mapbuilder* // @grant GM_setValue // @grant GM_getValue // @grant GM_addValueChangeListener // @grant unsafeWindow // @version 3.10 // ==/UserScript== // Contains Ordnance Survey data Crown copyright and database right 2012-2020 // // Contents of the locatorData_*.js files are derived under the // Open Government Licence from the OS Open Names and Open Roads datasets // // Contents of the gazetteer.js file are derived under the // Open Government Licence from the OS Open Names dataset /* ======================================================================================================================= DONE FOR THIS RELEASE ======================================================================================================================= Uses gazetteer data derived from the Open Names dataset Fixes startup error on one.network page ======================================================================================================================= Bug fixes - MUST BE CLEARED BEFORE RELEASE ======================================================================================================================= ======================================================================================================================= Things to be checked ======================================================================================================================= ======================================================================================================================= Proposed functionality ======================================================================================================================= Restrict city name uniqueness testing to within each county rather than country-wide ======================================================================================================================= New functionality in progress ======================================================================================================================= Mark on map where the OS city names are located */ /* JSHint Directives */ /* globals OpenLayers: true */ /* globals osMap: true */ /* globals OpenSpace: true */ /* globals Elgin: true */ /* globals google: true */ /* globals gazetteerDataA: true */ /* globals gazetteerDataB: true */ /* globals oslRoadNameMatches: true */ /* globals map: true */ /* globals GM_setValue: true */ /* globals GM_getValue: true */ /* globals GM_addValueChangeListener: true */ /* globals unsafeWindow: true */ /* jshint bitwise: false */ /* jshint evil: true */ /* jshint esversion: 6 */ const oslVersion = '3.10'; const oslUpdateURL = 'https://greasyfork.org/scripts/1941-wme-to-os-link'; const oslBlockPath = 'https://greasemonkey.chizzum.com/osl_v3.0/'; const oslGazetteerURL = 'https://chizzum.com/greasemonkey/gaz_v5/gazetteer.js'; const oslPi = 3.14159265358979; const oslPiDiv180 = (oslPi / 180); const osl180DivPi = (180 / oslPi); const oslLocatorBlockSize = 1000; const oslCacheDecayPeriod = 60; const oslMinUIWidth = 360; const GAZ_ELM = { Name: 0, CEast: 1, CNorth: 2, Type: 3, Area: 4, LEast: 5, LNorth: 6, REast: 7, RNorth: 8 }; const OSL_ELM = { RoadName: 0, RoadNumber: 1, BoundW: 2, BoundE: 3, BoundS: 4, BoundN: 5, Geometry: 6, AreaName: 7, AltName: 8, Classification: 9, Function: 10, Form: 11, Structure: 12, IsPrimary: 13, IsTrunk: 14, MAX: 15 }; const OSL_MODE = { Conversion: 0, OpenNames: 1, NameCheck: 2, OpenRoads: 3, }; const OSL_ROADCLASSIFICATIONS = { Undefined: 0, Motorway: 1, A_Road: 2, B_Road: 3, Classified_Unnumbered: 4, Unclassified: 5, Not_Classified: 6, Unknown: 7 }; const oslRoadClassifications = new Array ( 'Undefined', 'Motorway', 'A Road', 'B Road', 'Classified Unnumbered', 'Unclassified', 'Not Classified', 'Unknown' ); const OSL_ROADFUNCTIONS = { Undefined: 0, Motorway: 1, A_Road: 2, B_Road: 3, Minor_Road: 4, Local_Road: 5, Local_Access_Road: 6, Restricted_Local_Access_Road: 7, Secondary_Access_Road: 8 }; const oslRoadFunctions = new Array ( 'Undefined', 'Motorway', 'A Road', 'B Road', 'Minor Road', 'Local Road', 'Local Access Road', 'Restricted Local Access Road', 'Secondary Access Road' ); const oslStrokeColoursByFunction = new Array ( "red", "deepskyblue", "limegreen", "darkorange", "yellow", "white", "grey", "tan", "grey" ); const OSL_ROADSTRUCTURES = { Undefined: 0, Road_In_Tunnel: 1, Road_On_Bridge: 2 }; const oslRoadStructures = new Array ( 'Undefined', 'Road In Tunnel', 'Road On Bridge' ); const OSL_FORMSOFWAY = { Undefined: 0, Single_Carriageway: 1, Dual_Carriageway: 2, Slip_Road: 3, Roundabout: 4, Collapsed_Dual_Carriageway: 5, Guided_Busway: 6, Shared_Use_Carriageway: 7 }; const oslFormsOfWay = new Array ( 'Undefined', 'Single Carriageway', 'Dual Carriageway', 'Slip Road', 'Roundabout', 'Collapsed Dual Carriageway', 'Guided Busway', 'Shared Use Carriageway' ); // include names that don't get abbreviated, so that for names such as "Somewhere Green Way", the // abbreviation function is able to detect the "Way" part of the name as the part that ought to // be abbreviated, rather than treating it as a non-abbreviatable suffix and instead abbreviating // the "Green" part instead... const oslNameAbbreviations = new Array ( 'Avenue','Ave', 'Boulevard','Blvd', 'Broadway','Bdwy', 'Circus','Cir', 'Close','Cl', 'Court','Ct', 'Crescent','Cr', 'Drive','Dr', 'Garden','Gdn', 'Gardens','Gdns', 'Green','Gn', 'Grove','Gr', 'Lane','Ln', 'Mews','Mews', 'Mount','Mt', 'Place','Pl', 'Park','Pk', 'Ridge','Rdg', 'Road','Rd', 'Square','Sq', 'Street','St', 'Terrace','Ter', 'Valley','Val', 'By-pass','Bypass', 'Way','Way' ); var oslUserPrefs = {}; var oslGazetteerData = []; var oslAdvancedMode = false; var oslEvalString = ''; var oslLoadingMsg = false; var oslMLCDiv = null; var oslOSLDiv = null; var oslBBDiv = null; var oslPrevHighlighted = null; var oslSegmentHighlighted = false; var oslPrevMouseX = null; var oslPrevMouseY = null; var oslDivDragging = false; var oslPrevSelected = null; var oslDoOSLUpdate = false; var oslMousepos = null; var oslMousePixelpos = null; var oslDoneOnload = false; var oslRefreshAutoTrack = false; var oslOSOD_url = ''; var oslOSMC_url = ''; var oslRWO_url = ''; var oslLRR_url = ''; var oslSWG_url = ''; var oslPrevStreetName = ''; var oslMergeGazData = false; var oslOSLMaskLayer = null; var oslOSLNameCheckTimer = 0; var oslOSLNCSegments = []; var oslInUK = false; var oslInLondon = false; var oslInWiltshire = false; var oslNorthings = null; var oslEastings = null; var oslLatitude = null; var oslLongitude = null; var oslHelmX = null; var oslHelmY = null; var oslHelmZ = null; var oslBlocksToLoad = []; var oslBlocksToTest = []; // 50.06574112187924 -5.699894626953322 // 135261,25033 // 135256,25014 // +6, +19 // 51.35363338966115 1.4443961072966522 // 639795,167306 // 639800,167284 // -5, +22 // 60.15795987870581 -1.1466271562283679 // 447367,1141743 // 447362,1141733 // +5, +10 var oslVPLeft = 0; var oslVPRight = 0; var oslVPBottom = 0; var oslVPTop = 0; var oslBBDivInnerHTML = ''; var oslEvalEBlock = 0; var oslEvalNBlock = 0; var oslBlockData = null; var oslBlockCacheList = []; var oslBlockCacheTestTimer = (oslCacheDecayPeriod * 10); var oslSegGeoDivInnerHTML = ''; var oslONC_E = null; var oslONC_N = null; var oslEBlock_min = null; var oslEBlock_max = null; var oslNBlock_min = null; var oslNBlock_max = null; var oslWazeBitsPresent = 0; var oslOSLDivLeft; var oslOSLDivTop; var oslSegGeoDiv; var oslWazeMapElement; var oslDragBar; var oslWindow; var oslOSLDivTopMinimised; var oslNCDiv; var oslSegGeoUIDiv; var oslOffsetToolbar = false; var oslMOAdded = false; var oslMTEMode = false; var oslLocatorElements = null; var oslUsingNewName = false; var oslUseName = false; var oslCityName = ''; var oslCountyName = ''; var oslUseAlt = false; var oslAltNamesClearing = false; var oslRORCenter = null; var oslRORZoom = null; var W = null; function oslBootstrap() { if(document.location.host == 'one.network') { hlp_ONE.init(); } else if(document.location.host == 'openspacewmb.ordnancesurvey.co.uk') { hlp_ODM.init(); } else if(document.location.host == 'public.londonworks.gov.uk') { hlp_LRR.init(); } else if(document.location.host == 'streetworks.wiltshire.gov.uk') { hlp_WSW.init(); } else { // something in this version prevents WME from starting up properly if we initialise early in the WME startup. // since I haven't yet figured out what it is we need to wait for, using a fixed delay of 2s seems to work OK... window.setTimeout(oslInitialise,2000); } } function oslAddLog(logtext) { console.log('WMEOpenData: '+logtext); } //----------------------------------------------------------------------------------------------------------------------------------------- // all code between here and the next ------------- marker line is a stripped down version of the original from Paul Dixon // // * GeoTools javascript coordinate transformations // * http://www.nearby.org.uk/tests/geotools2.js // * // * This file copyright (c)2005 Paul Dixon ([email protected]) // * // * This program is free software; you can redistribute it and/or // * modify it under the terms of the GNU General Public License // * as published by the Free Software Foundation; either version 2 // * of the License, or (at your option) any later version. // * // * This program is distributed in the hope that it will be useful, // * but WITHOUT ANY WARRANTY; without even the implied warranty of // * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // * GNU General Public License for more details. // * // * You should have received a copy of the GNU General Public License // * along with this program; if not, write to the Free Software // * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // * // * --------------------------------------------------------------------------- // * // * Credits // * // * The algorithm used by the script for WGS84-OSGB36 conversions is derived // * from an OSGB spreadsheet (www.gps.gov.uk) with permission. This has been // * adapted into Perl by Ian Harris, and into PHP by Barry Hunter. Conversion // * accuracy is in the order of 7m for 90% of Great Britain, and should be // * be similar to the conversion made by a typical GPSr // * // * See accompanying documentation for more information // * http://www.nearby.org.uk/tests/GeoTools2.html function oslOSGBtoWGS(oseast, osnorth) { const a = 6377563.396; const b = 6356256.910; const e0 = 400000; const n0 = -100000; const f0 = 0.999601272; const PHI0 = 49.00000; const LAM0 = -2.00000; const RadPHI0 = PHI0 * oslPiDiv180; const RadLAM0 = LAM0 * oslPiDiv180; //Compute af0, bf0, e squared (e2), n and Et var af0 = a * f0; var bf0 = b * f0; var e2 = (Math.pow(af0,2) - Math.pow(bf0,2)) / Math.pow(af0,2); var n = (af0 - bf0) / (af0 + bf0); var Et = oseast - e0; //Compute initial value for oslLatitude (PHId) in radians var PHI1 = ((osnorth - n0) / af0) + RadPHI0; var M = oslMarc(bf0, n, RadPHI0, PHI1); var PHId = ((osnorth - n0 - M) / af0) + PHI1; while (Math.abs(osnorth - n0 - M) > 0.00001) { PHId = ((osnorth - n0 - M) / af0) + PHI1; M = oslMarc(bf0, n, RadPHI0, PHId); PHI1 = PHId; } //Compute nu, rho and eta2 using value for PHId var nu = af0 / (Math.sqrt(1 - (e2 * ( Math.pow(Math.sin(PHId),2))))); var rho = (nu * (1 - e2)) / (1 - (e2 * Math.pow(Math.sin(PHId),2))); var eta2 = (nu / rho) - 1; //Compute Latitude var VII = (Math.tan(PHId)) / (2 * rho * nu); var VIII = ((Math.tan(PHId)) / (24 * rho * Math.pow(nu,3))) * (5 + (3 * (Math.pow(Math.tan(PHId),2))) + eta2 - (9 * eta2 * (Math.pow(Math.tan(PHId),2)))); //var IX = ((Math.tan(PHId)) / (720 * rho * Math.pow(nu,5))) * (61 + (90 * ((Math.tan(PHId)) ^ 2)) + (45 * (Math.pow(Math.tan(PHId),4)))); var IX = ((Math.tan(PHId)) / (720 * rho * Math.pow(nu,5))) * (61 + (90 * (Math.pow(Math.tan(PHId), 2))) + (45 * (Math.pow(Math.tan(PHId),4)))); //oslLatitude = osl180DivPi * (PHId - (Math.pow(Et,2) * VII) + (Math.pow(Et,4) * VIII) - ((Et ^ 6) * IX)); oslLatitude = osl180DivPi * (PHId - (Math.pow(Et,2) * VII) + (Math.pow(Et,4) * VIII) - (Math.pow(Et, 6) * IX)); //Compute Longitude var X = (Math.pow(Math.cos(PHId),-1)) / nu; var XI = ((Math.pow(Math.cos(PHId),-1)) / (6 * Math.pow(nu,3))) * ((nu / rho) + (2 * (Math.pow(Math.tan(PHId),2)))); var XII = ((Math.pow(Math.cos(PHId),-1)) / (120 * Math.pow(nu,5))) * (5 + (28 * (Math.pow(Math.tan(PHId),2))) + (24 * (Math.pow(Math.tan(PHId),4)))); var XIIA = ((Math.pow(Math.cos(PHId),-1)) / (5040 * Math.pow(nu,7))) * (61 + (662 * (Math.pow(Math.tan(PHId),2))) + (1320 * (Math.pow(Math.tan(PHId),4))) + (720 * (Math.pow(Math.tan(PHId),6)))); oslLongitude = osl180DivPi * (RadLAM0 + (Et * X) - (Math.pow(Et,3) * XI) + (Math.pow(Et,5) * XII) - (Math.pow(Et,7) * XIIA)); var RadPHI = oslLatitude * oslPiDiv180; var RadLAM = oslLongitude * oslPiDiv180; e2 = (Math.pow(6377563.396,2) - Math.pow(6356256.910,2)) / Math.pow(6377563.396,2); var V = a / (Math.sqrt(1 - (e2 * ( Math.pow(Math.sin(RadPHI),2))))); X = V * (Math.cos(RadPHI)) * (Math.cos(RadLAM)); var Y = V * (Math.cos(RadPHI)) * (Math.sin(RadLAM)); var Z = (V * (1 - e2)) * (Math.sin(RadPHI)); // do Helmert transforms var sfactor = -20.4894 * 0.000001; var RadX_Rot = (0.1502 / 3600) * oslPiDiv180; var RadY_Rot = (0.2470 / 3600) * oslPiDiv180; var RadZ_Rot = (0.8421 / 3600) * oslPiDiv180; var X2 = (X + (X * sfactor) - (Y * RadZ_Rot) + (Z * RadY_Rot) + 446.448); var Y2 = (X * RadZ_Rot) + Y + (Y * sfactor) - (Z * RadX_Rot) -125.157; var Z2 = (-1 * X * RadY_Rot) + (Y * RadX_Rot) + Z + (Z * sfactor) + 542.060; var RootXYSqr = Math.sqrt(Math.pow(X2,2) + Math.pow(Y2,2)); e2 = (Math.pow(6378137.000,2) - Math.pow(6356752.313,2)) / Math.pow(6378137.000,2); PHI1 = Math.atan2(Z2 , (RootXYSqr * (1 - e2)) ); V = 6378137.000 / (Math.sqrt(1 - (e2 * Math.pow(Math.sin(PHI1),2)))); var PHI2 = Math.atan2((Z + (e2 * V * (Math.sin(PHI1)))) , RootXYSqr); while (Math.abs(PHI1 - PHI2) > 0.000000001) { PHI1 = PHI2; V = 6378137.000 / (Math.sqrt(1 - (e2 * Math.pow(Math.sin(PHI1),2)))); PHI2 = Math.atan2((Z2 + (e2 * V * (Math.sin(PHI1)))) , RootXYSqr); } oslLatitude = PHI2 * osl180DivPi; oslLongitude = Math.atan2(Y2 , X2) * osl180DivPi; } function oslWGStoOSGB() { oslLatLontoHelmXYZ(); var oslLatitude2 = oslXYZtoLat(); var oslLongitude2 = Math.atan2(oslHelmY , oslHelmX) * osl180DivPi; oslLatLonoslToOSGrid(oslLatitude2,oslLongitude2); } function oslLatLontoHelmXYZ() { const a = 6378137.0; const b = 6356752.313; const DX = -446.448; const DY = 125.157; const DZ = -542.060; const rotX = -0.1502; const rotY = -0.2470; const rotZ = -0.8421; const sfactor = 20.4894 * 0.000001; const e2 = (Math.pow(a,2) - Math.pow(b,2)) / Math.pow(a,2); // perform initial lat-lon to cartesian coordinate translation var RadPHI = oslLatitude * oslPiDiv180; var RadLAM = oslLongitude * oslPiDiv180; var V = a / (Math.sqrt(1 - (e2 * ( Math.pow(Math.sin(RadPHI),2))))); var cartX = V * (Math.cos(RadPHI)) * (Math.cos(RadLAM)); var cartY = V * (Math.cos(RadPHI)) * (Math.sin(RadLAM)); var cartZ = (V * (1 - e2)) * (Math.sin(RadPHI)); // Compute Helmert transformed coordinates var RadX_Rot = (rotX / 3600) * oslPiDiv180; var RadY_Rot = (rotY / 3600) * oslPiDiv180; var RadZ_Rot = (rotZ / 3600) * oslPiDiv180; oslHelmX = (cartX + (cartX * sfactor) - (cartY * RadZ_Rot) + (cartZ * RadY_Rot) + DX); oslHelmY = (cartX * RadZ_Rot) + cartY + (cartY * sfactor) - (cartZ * RadX_Rot) + DY; oslHelmZ = (-1 * cartX * RadY_Rot) + (cartY * RadX_Rot) + cartZ + (cartZ * sfactor) + DZ; } function oslXYZtoLat() { const a = 6377563.396; const b = 6356256.910; const e2 = (Math.pow(a,2) - Math.pow(b,2)) / Math.pow(a,2); var RootXYSqr = Math.sqrt(Math.pow(oslHelmX,2) + Math.pow(oslHelmY,2)); var PHI1 = Math.atan2(oslHelmZ , (RootXYSqr * (1 - e2)) ); var PHI = oslIterateOSLXYZtoLat(a, e2, PHI1, oslHelmZ, RootXYSqr); return PHI * osl180DivPi; } function oslIterateOSLXYZtoLat(a, e2, PHI1, Z, RootXYSqr) { var V = a / (Math.sqrt(1 - (e2 * Math.pow(Math.sin(PHI1),2)))); var PHI2 = Math.atan2((Z + (e2 * V * (Math.sin(PHI1)))) , RootXYSqr); while (Math.abs(PHI1 - PHI2) > 0.000000001) { PHI1 = PHI2; V = a / (Math.sqrt(1 - (e2 * Math.pow(Math.sin(PHI1),2)))); PHI2 = Math.atan2((Z + (e2 * V * (Math.sin(PHI1)))) , RootXYSqr); } return PHI2; } function oslMarc(bf0, n, PHI0, PHI) { return bf0 * (((1 + n + ((5 / 4) * Math.pow(n,2)) + ((5 / 4) * Math.pow(n,3))) * (PHI - PHI0)) - (((3 * n) + (3 * Math.pow(n,2)) + ((21 / 8) * Math.pow(n,3))) * (Math.sin(PHI - PHI0)) * (Math.cos(PHI + PHI0))) + ((((15 / 8) * Math.pow(n,2)) + ((15 / 8) * Math.pow(n,3))) * (Math.sin(2 * (PHI - PHI0))) * (Math.cos(2 * (PHI + PHI0)))) - (((35 / 24) * Math.pow(n,3)) * (Math.sin(3 * (PHI - PHI0))) * (Math.cos(3 * (PHI + PHI0))))); } function oslLatLonoslToOSGrid(PHI, LAM) { const a = 6377563.396; const b = 6356256.910; const e0 = 400000; const n0 = -100000; const f0 = 0.999601272; const PHI0 = 49.00000; const LAM0 = -2.00000; const RadPHI0 = PHI0 * oslPiDiv180; const RadLAM0 = LAM0 * oslPiDiv180; const af0 = a * f0; const bf0 = b * f0; const n = (af0 - bf0) / (af0 + bf0); const e2 = (Math.pow(af0,2) - Math.pow(bf0,2)) / Math.pow(af0,2); var RadPHI = PHI * oslPiDiv180; var RadLAM = LAM * oslPiDiv180; var nu = af0 / (Math.sqrt(1 - (e2 * Math.pow(Math.sin(RadPHI),2) ))); var rho = (nu * (1 - e2)) / (1 - (e2 * Math.pow(Math.sin(RadPHI),2) )); var eta2 = (nu / rho) - 1; var p = RadLAM - RadLAM0; var M = oslMarc(bf0, n, RadPHI0, RadPHI); var I = M + n0; var II = (nu / 2) * (Math.sin(RadPHI)) * (Math.cos(RadPHI)); var III = ((nu / 24) * (Math.sin(RadPHI)) * (Math.pow(Math.cos(RadPHI),3))) * (5 - (Math.pow(Math.tan(RadPHI),2)) + (9 * eta2)); var IIIA = ((nu / 720) * (Math.sin(RadPHI)) * (Math.pow(Math.cos(RadPHI),5))) * (61 - (58 * (Math.pow(Math.tan(RadPHI),2))) + (Math.pow(Math.tan(RadPHI),4))); var IV = nu * (Math.cos(RadPHI)); var V = (nu / 6) * ( Math.pow(Math.cos(RadPHI),3)) * ((nu / rho) - (Math.pow(Math.tan(RadPHI),2))); var VI = (nu / 120) * (Math.pow(Math.cos(RadPHI),5)) * (5 - (18 * (Math.pow(Math.tan(RadPHI),2))) + (Math.pow(Math.tan(RadPHI),4)) + (14 * eta2) - (58 * (Math.pow(Math.tan(RadPHI),2)) * eta2)); oslEastings = Math.round(e0 + (p * IV) + (Math.pow(p,3) * V) + (Math.pow(p,5) * VI)); oslNorthings = Math.round(I + (Math.pow(p,2) * II) + (Math.pow(p,4) * III) + (Math.pow(p,6) * IIIA)); oslNorthings -= 16; // the above calculations give a northings error of between 10-22m, so add a final adjustment so that the error is evened out and reduced to +/- 6m } //----------------------------------------------------------------------------------------------------------------------------------------- function oslCaseCorrect(wrongcase) { var loop; var correctedCase = ''; for(loop=0;loop<wrongcase.length;loop++) { // capitalise first letter following one of these substrings if ( (loop === 0)|| (wrongcase[loop-1] == ' ')|| (wrongcase[loop-1] == '(')|| (wrongcase.substr(loop-3,3) == '-Y-')|| (wrongcase.substr(loop-4,4) == '-YR-') ) correctedCase += wrongcase[loop].toUpperCase(); else correctedCase += wrongcase[loop].toLowerCase(); } // recapitalise any roman numerals correctedCase = correctedCase.replace(' Ii ',' II '); correctedCase = correctedCase.replace(' Iii ',' III '); correctedCase = correctedCase.replace(' Iv ',' IV '); correctedCase = correctedCase.replace(' Vi ',' VI '); correctedCase = correctedCase.replace(' Vii ',' VII '); return correctedCase; } function oslSaintsPreserveUs(oslName) { var nameBits = []; if(oslName.indexOf('St ') != -1) { nameBits = oslName.split('St '); oslName = nameBits[0] + 'St. ' + nameBits[1]; } else if(oslName.indexOf('Saint ') != -1) { nameBits = oslName.split('Saint '); oslName = nameBits[0] + 'St. ' + nameBits[1]; } return oslName; } function oslWazeifyStreetName(oslName, debugOutput) { var wazeName = ''; var loop; // strip out any HTML encoding added by the server when returning the street name data... var textArea = document.createElement('textarea'); textArea.innerHTML = oslName; oslName = textArea.value; wazeName = oslCaseCorrect(oslName); wazeName = oslSaintsPreserveUs(wazeName); var nameoslPieces = wazeName.split(' '); if(nameoslPieces.length > 1) { var dirSuffix = ''; var namePrefix = ''; if((nameoslPieces[nameoslPieces.length-1] == 'North')||(nameoslPieces[nameoslPieces.length-1] == 'South')||(nameoslPieces[nameoslPieces.length-1] == 'East')||(nameoslPieces[nameoslPieces.length-1] == 'West')) { dirSuffix = ' ' + nameoslPieces[nameoslPieces.length-1][0]; for(loop=0;loop<nameoslPieces.length-1;loop++) namePrefix += (nameoslPieces[loop] + ' '); } else { for(loop=0;loop<nameoslPieces.length;loop++) namePrefix += (nameoslPieces[loop] + ' '); } namePrefix = namePrefix.trimRight(1); if(debugOutput === true) console.log(oslName); // replace road type with abbreviated form for(var pass=0;pass<2;pass++) { for(loop=0;loop<oslNameAbbreviations.length;loop+=2) { var abbrPos = namePrefix.lastIndexOf(oslNameAbbreviations[loop]); var abbrLen = oslNameAbbreviations[loop].length; var npLength = namePrefix.length; var npRemaining = npLength - abbrPos; if(debugOutput === true) console.log(pass,' ',oslNameAbbreviations[loop],' ',abbrPos,' ',abbrLen,' ',npLength,' ',npRemaining); if(abbrPos != -1) { // make sure the road type we've found comes firstly at the end of the name string, or is suffixed with a space // if there's a non-road type at the end of the string (e.g. High Road Eastcote) // isn't, then we've actually found a type match within a longer string segment (e.g. The Parkside) and so we // should leave it alone... if ( ((pass === 0) && (npRemaining == abbrLen)) || ((pass == 1) && (namePrefix[abbrPos+abbrLen] == ' ')) ) { var preName = namePrefix.substr(0,abbrPos); if((preName.length >= 4) && (preName.lastIndexOf("The") != (preName.length - 4))) { var theName = namePrefix.substr(abbrPos); theName = theName.replace(oslNameAbbreviations[loop],oslNameAbbreviations[loop+1]); wazeName = preName + theName + dirSuffix; return wazeName; } } } } } wazeName = namePrefix + dirSuffix; } return wazeName; } function oslCPDistance(cpE, cpN, posE, posN) { return Math.round(Math.sqrt(((posE - cpE) * (posE - cpE)) + ((posN - cpN) * (posN - cpN)))); } function oslGetBBCornerPixels(boxW, boxE, boxS, boxN) { var lonlat_sw = new OpenLayers.LonLat(boxW,boxS); var lonlat_se = new OpenLayers.LonLat(boxE,boxS); var lonlat_nw = new OpenLayers.LonLat(boxW,boxN); var lonlat_ne = new OpenLayers.LonLat(boxE,boxN); lonlat_sw.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913")); lonlat_se.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913")); lonlat_nw.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913")); lonlat_ne.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913")); var pix_sw = W.map.getPixelFromLonLat(lonlat_sw); var pix_se = W.map.getPixelFromLonLat(lonlat_se); var pix_ne = W.map.getPixelFromLonLat(lonlat_ne); var pix_nw = W.map.getPixelFromLonLat(lonlat_nw); boxE = (pix_ne.x + pix_se.x) / 2; boxW = (pix_nw.x + pix_sw.x) / 2; boxN = (pix_ne.y + pix_nw.y) / 2; boxS = (pix_se.y + pix_sw.y) / 2; var boxToleranceWidth = ((boxE - boxW) * 0.05); var boxToleranceHeight = ((boxS - boxN) * 0.05); boxW -= boxToleranceWidth; boxE += boxToleranceWidth; boxS += boxToleranceHeight; boxN -= boxToleranceHeight; boxE = Math.round(boxE); boxW = Math.round(boxW); boxS = Math.round(boxS); boxN = Math.round(boxN); // extend width/height of box if the calculated dimension is too small for the box to be readily visible if(boxE-boxW < 20) { boxE += 10; boxW -= 10; } if(boxS-boxN < 20) { boxS += 10; boxN -= 10; } return [boxW, boxE, boxS, boxN]; } function oslVisualiseBoundingBox(boxW, boxE, boxS, boxN, mode) { if(oslOSLDiv.style.height == '0px') { oslBBDiv.innerHTML = ''; return; } var boxPos = [boxW, boxE, boxS, boxN]; if((mode == 1) || (mode == 2)) { boxPos = oslGetBBCornerPixels(boxW, boxE, boxS, boxN); } if(mode === 0) { oslBBDivInnerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="'+document.getElementById('WazeMap').offsetWidth+'px" height="'+document.getElementById('WazeMap').offsetHeight+'px" version="1.1">'; } else if(mode == 1) { oslBBDivInnerHTML += '<rect x="'+boxPos[0]+'" y="'+boxPos[3]+'" width="'+(boxPos[1]-boxPos[0])+'" height="'+(boxPos[2]-boxPos[3])+'" style="fill:yellow;stroke:pink;stroke-width:4;fill-opacity:0.25;stroke-opacity:0.25"/>'; } else if(mode == 2) { oslBBDivInnerHTML += '<rect x="'+boxPos[0]+'" y="'+boxPos[3]+'" width="'+(boxPos[1]-boxPos[0])+'" height="'+(boxPos[2]-boxPos[3])+'" style="fill:lightgrey;stroke:grey;stroke-width:4;fill-opacity:0.25;stroke-opacity:0.25"/>'; } else if(mode == 3) { oslBBDivInnerHTML += '</svg>'; oslBBDiv.innerHTML = oslBBDivInnerHTML; } } function oslMergeGazetteerData() { if((typeof(gazetteerDataA) == "undefined") || (typeof(gazetteerDataB) == "undefined")) return false; if(oslMergeGazData) { oslGazetteerData = gazetteerDataA; oslGazetteerData = oslGazetteerData.concat(gazetteerDataB); oslMergeGazData = false; for(var idx=0;idx<oslGazetteerData.length;idx++) { oslGazetteerData[idx] = oslSaintsPreserveUs(oslGazetteerData[idx]); } oslAddLog('gazetteer data loaded, '+oslGazetteerData.length+' entries'); } return true; } function oslHighlightOSCityName() { var selectedIdx = document.getElementById('oslOSCityNames').selectedIndex; } function oslGetNearbyCityNames() { if(oslMergeGazetteerData() === false) return; var names = []; for(var idx=0;idx<oslGazetteerData.length;idx++) { var gazElements = oslGazetteerData[idx].split(':'); var cnEastings = gazElements[GAZ_ELM.CEast]; var cnNorthings = gazElements[GAZ_ELM.CNorth]; if((Math.abs(cnNorthings-oslNorthings) <= 5000)&&(Math.abs(cnEastings-oslEastings) <= 5000)) { var dist = oslCPDistance(cnEastings,cnNorthings,oslEastings,oslNorthings); if(dist <= 5000) { names.push((dist * 1000000) + idx); } } } if(names.length > 1) names.sort(function(a,b){return a-b;}); var cityInTopTen = false; var matchedOSName = false; var matchedIdx = -1; var listLength = names.length; if(listLength > 10) listLength = 10; var listOpt; var gElements; var gDist; var cityName; var oOCN = document.getElementById('oslOSCityNames'); for(idx=0;idx<listLength;idx++) { gElements = oslGazetteerData[names[idx] % 1000000].split(':'); gDist = (Math.round(names[idx] / 100000000)/10); // Build namestring for entry in the drop-down list - start with the placename :-) listOpt = document.createElement('option'); cityName = gElements[GAZ_ELM.Name]; listOpt.text = cityName; // if the name is neither a city nor unique, append a (county) suffix if(gElements[GAZ_ELM.Type] == 'C') cityInTopTen = true; else { if(oslCheckCityNameDuplicates(gElements[GAZ_ELM.Name],1) > 1) { listOpt.text += ', '+gElements[GAZ_ELM.Area]; } } if(sessionStorage.cityNameRB == 'optUseOS') { if(cityName == sessionStorage.myCity) { matchedOSName = true; matchedIdx = idx; } } // Add place type and distance in [] brackets to allow easy removal later... if(gElements[GAZ_ELM.Type] == 'C') listOpt.text += ' [City, '; else if(gElements[GAZ_ELM.Type] == 'T') listOpt.text += ' [Town, '; else if(gElements[GAZ_ELM.Type] == 'V') listOpt.text += ' [Village, '; else if(gElements[GAZ_ELM.Type] == 'H') listOpt.text += ' [Hamlet, '; else listOpt.text += ' [Other, '; listOpt.text += gDist + 'km]'; oOCN.add(listOpt,null); } if((!cityInTopTen) && (names.length > 10)) { idx = 10; while((idx < names.length) && (!cityInTopTen)) { gElements = oslGazetteerData[names[idx] % 1000000].split(':'); if(gElements[GAZ_ELM.Type] == 'C') { cityInTopTen = true; gDist = ' [City, '+(Math.round(names[idx] / 100000000)/10)+'km]'; listOpt = document.createElement('option'); listOpt.text = gElements[GAZ_ELM.Name]+gDist; oOCN.add(listOpt,null); if(sessionStorage.cityNameRB == 'optUseOS') { if(gElements[GAZ_ELM.Name] == sessionStorage.myCity) { matchedOSName = true; matchedIdx = 10; break; } } } idx++; } } //oOCN.addEventListener("input", oslHighlightOSCityName, false); if(matchedOSName === true) oOCN.options.selectedIndex = matchedIdx; if((sessionStorage.cityNameRB == 'optUseOS') && (matchedOSName === false)) { oslAddLog('Selected city name no longer in nearby OS list...'); alert('City name no longer present in nearby OS data, please reselect'); sessionStorage.cityNameRB = 'optUseExisting'; document.getElementById('optUseExisting').checked = true; } } function oslCheckCityNameDuplicates(cityName, mode) { if(oslMergeGazetteerData() === false) return; var cnCount = 0; var searchDist = Math.round(oslGazetteerData.length/2); var searchIdx = searchDist; var hasCounty = false; var debugOutput = false; // remove county suffix from actual city name string if present if(cityName.indexOf('(') != -1) { cityName = cityName.substr(0,cityName.indexOf('(')); cityName = cityName.replace(/^\s+|\s+$/g, ""); hasCounty = true; } // remove script-appended county suffix from city name held in drop down if present if(cityName.indexOf(',') != -1) { cityName = cityName.substr(0,cityName.indexOf(',')); cityName = cityName.replace(/^\s+|\s+$/g, ""); } cityName = cityName.toLowerCase(); cityName = cityName.replace(/-/g, ' '); var gazName = ''; if(debugOutput === true) console.log('scan for duplicates of '+cityName); var gazElements = []; while((searchDist > 1) && (cityName.localeCompare(gazName) !== 0)) { searchDist = Math.round(searchDist/2); gazElements = oslGazetteerData[searchIdx].split(':'); gazName = gazElements[GAZ_ELM.Name].toLowerCase(); gazName = gazName.replace(/-/g, ' '); if(debugOutput === true) console.log('a: '+searchDist+' '+searchIdx+' '+gazName); if(cityName.localeCompare(gazName) > 0) searchIdx += searchDist; else if(cityName.localeCompare(gazName) < 0) searchIdx -= searchDist; if(searchIdx >= oslGazetteerData.length) searchIdx = oslGazetteerData.length-1; if(searchIdx < 0) searchIdx = 0; } gazElements = oslGazetteerData[searchIdx].split(':'); gazName = gazElements[GAZ_ELM.Name].toLowerCase(); gazName = gazName.replace(/-/g, ' '); while((searchIdx > 0) && (cityName.localeCompare(gazName) <= 0)) { gazElements = oslGazetteerData[--searchIdx].split(':'); gazName = gazElements[GAZ_ELM.Name].toLowerCase(); gazName = gazName.replace(/-/g, ' '); if(debugOutput === true) console.log('b: '+(searchIdx)+' '+gazName); } gazElements = oslGazetteerData[searchIdx].split(':'); gazName = gazElements[GAZ_ELM.Name].toLowerCase(); gazName = gazName.replace(/-/g, ' '); while((searchIdx < oslGazetteerData.length) && (cityName.localeCompare(gazName) > 0)) { gazElements = oslGazetteerData[++searchIdx].split(':'); gazName = gazElements[GAZ_ELM.Name].toLowerCase(); gazName = gazName.replace(/-/g, ' '); if(debugOutput === true) console.log('c: '+(searchIdx)+' '+gazName); } while((cityName.localeCompare(gazName) === 0) && (searchIdx < oslGazetteerData.length)) { cnCount++; gazElements = oslGazetteerData[++searchIdx].split(':'); gazName = gazElements[GAZ_ELM.Name].toLowerCase(); gazName = gazName.replace(/-/g, ' '); if(debugOutput === true) console.log('d: '+(searchIdx)+' '+gazName+' '+cnCount); } if(mode === 0) { var newHTML = ''; if(cnCount === 0) newHTML = ' Place name is not in OS data'; else if(cnCount == 1) { newHTML = ' Place name is unique'; if(hasCounty) newHTML += '<br> <i>(County) suffix not required</i>'; } else { newHTML = ' Place name is not unique'; } document.getElementById('oslCNInfo').innerHTML = newHTML; } else return cnCount; } function oslHighlightAdjacentSameNameSegments(ldEastings, ldNorthings, ldIgnoreIdx, srcElements) { ldNorthings -= oslLocatorBlockSize; ldEastings -= oslLocatorBlockSize; for(var x = 0; x < 3; ++x) { for(var y = 0; y < 3; ++y) { var arrayName = 'locatorData_'+(ldEastings + (x * oslLocatorBlockSize))+'_'+(ldNorthings + (y * oslLocatorBlockSize)); oslEvalString = 'typeof '+arrayName; if(eval(oslEvalString) != "undefined") { oslEvalString = 'oslBlockData = '+arrayName; eval(oslEvalString); for(var loop = 0; loop < oslBlockData.length; ++loop) { if(loop != ldIgnoreIdx) { var locatorElements = oslBlockData[loop].split(':'); if ( (locatorElements[OSL_ELM.RoadName] == srcElements[OSL_ELM.RoadName]) && (locatorElements[OSL_ELM.RoadNumber] == srcElements[OSL_ELM.RoadNumber]) && (locatorElements[OSL_ELM.AreaName] == srcElements[OSL_ELM.AreaName]) ) { oslVisualiseBoundingBox(locatorElements[OSL_ELM.BoundW],locatorElements[OSL_ELM.BoundE],locatorElements[OSL_ELM.BoundS],locatorElements[OSL_ELM.BoundN],2); } } } } } } } function oslRadioClick() { var oslElements = document.getElementById('oslRoadNameMatches'); var selectedName = ''; var loop; var roadData; var locatorElements; var tagname; var attr; var oslID; var evalstr; for(loop=0;loop<oslElements.childNodes.length;loop++) { if(oslElements.childNodes[loop].nodeType == 1) { tagname = oslElements.childNodes[loop].tagName; if(tagname !== null) { if(tagname == "LABEL") { if(oslElements.childNodes[loop].childNodes[0].checked) { attr = oslElements.childNodes[loop].childNodes[0].attributes.getNamedItem("id").value; if((attr.indexOf('oslID_') === 0) || (attr.indexOf('alt-oslID_') === 0)) { roadData = ''; oslID = attr.split('_'); if(oslID[1] != 'null') { evalstr = 'var roadData = locatorData_'+oslID[1]+'_'+oslID[2]+'['+oslID[3]+']'; eval(evalstr); } else { roadData = "null:null"; } locatorElements = roadData.split(":"); if(locatorElements[OSL_ELM.RoadName] != 'null') { selectedName = locatorElements[OSL_ELM.RoadName]+locatorElements[OSL_ELM.RoadNumber]; oslVisualiseBoundingBox(0,0,0,0,0); oslVisualiseBoundingBox(locatorElements[OSL_ELM.BoundW],locatorElements[OSL_ELM.BoundE],locatorElements[OSL_ELM.BoundS],locatorElements[OSL_ELM.BoundN],1); oslHighlightAdjacentSameNameSegments(oslID[1], oslID[2], oslID[3], locatorElements); } else { oslBBDiv.innerHTML = ''; } } } } } } } if(selectedName === '') { oslBBDiv.innerHTML = ''; return; } oslVisualiseBoundingBox(0,0,0,0,3); } function oslClick() { oslCityName = ''; oslCountyName = ''; oslUsingNewName = false; if(document.getElementById('optUseNewManual').checked) { oslCityName = oslCaseCorrect(document.getElementById('myCityName').value); oslUsingNewName = true; } else if(document.getElementById('optUseExistingWME').checked) { var oWCN = document.getElementById('oslWMECityNames'); oslCityName = oWCN.options[oWCN.options.selectedIndex].text; if(oslCityName.indexOf(', ') !== -1) { oslCountyName = oslCityName.split(', ')[1]; oslCityName = oslCityName.split(', ')[0]; } oslUsingNewName = true; } else if(document.getElementById('optUseOS').checked) { var oOCN = document.getElementById('oslOSCityNames'); oslCityName = oOCN.options[oOCN.options.selectedIndex].text; oslCityName = oslCityName.substring(0,oslCityName.indexOf('[')-1); if(oslCityName.indexOf(', ') !== -1) { oslCountyName = oslCityName.split(', ')[1]; oslCityName = oslCityName.split(', ')[0]; } oslUsingNewName = true; } if(sessionStorage.myCity === '') { oslAddLog('Update city name position at '+oslEastings+'x'+oslNorthings); sessionStorage.cityChangeEastings = oslEastings; sessionStorage.cityChangeNorthings = oslNorthings; } if(oslCountyName !== '') { sessionStorage.myCity = oslCityName+', '+oslCountyName; } else { sessionStorage.myCity = oslCityName; } oslUseName = false; if((oslCityName.length > 0) && oslUsingNewName) { oslCheckCityNameDuplicates(oslCityName,0); if(oslCityName != sessionStorage.prevCityName) { oslAddLog('Change of city name at '+oslEastings+'x'+oslNorthings); sessionStorage.cityChangeEastings = oslEastings; sessionStorage.cityChangeNorthings = oslNorthings; sessionStorage.prevCityName = oslCityName; oslUseName = true; } else { var nameChangeDist = oslCPDistance(oslEastings,oslNorthings,sessionStorage.cityChangeEastings,sessionStorage.cityChangeNorthings); oslAddLog('Current name was set '+nameChangeDist+'m away from segment location'); if(nameChangeDist > 1000) { oslAddLog('Distance exceeds 1km threshold, name verification required...'); if(confirm('Confirm continued use of this city name')) { oslAddLog('Confirm city name at '+oslEastings+'x'+oslNorthings); sessionStorage.cityChangeEastings = oslEastings; sessionStorage.cityChangeNorthings = oslNorthings; oslUseName = true; } } else { oslUseName = true; } } } var oslElements = document.getElementById('oslRoadNameMatches'); for(var loop=0;loop<oslElements.childNodes.length;loop++) { if(oslElements.childNodes[loop].nodeType == 1) { var tagname = oslElements.childNodes[loop].tagName; if(tagname !== null) { if(tagname == "LABEL") { var rbElement = oslElements.childNodes[loop].childNodes[0]; if((rbElement.name == "oslChoice") && (rbElement.checked)) { var attr = rbElement.attributes.getNamedItem("id").value; var useMain = (attr.indexOf('oslID_') === 0); oslUseAlt = (attr.indexOf('alt-oslID_') === 0); if((useMain === true) || (oslUseAlt === true)) { var roadData = ''; var oslID = attr.split('_'); if(oslID[1] != 'null') { var evalstr = 'var roadData = locatorData_'+oslID[1]+'_'+oslID[2]+'['+oslID[3]+']'; eval(evalstr); } else { for(var i = 0; i < OSL_ELM.MAX; ++i) { roadData += ':'; } } oslLocatorElements = roadData.split(":"); // auto-click the Edit Address link... document.getElementsByClassName('full-address')[0].click(); oslAltNamesClearing = false; oslWaitAddressElementOpen(); } } } } } } } function oslWaitAddressElementOpen() { // clear any altnames that may be present... var altNames = document.getElementsByClassName('alt-street-delete').length; if(altNames > 0) { if(oslAltNamesClearing == false) { if(document.getElementsByClassName('alt-street-delete')[0].offsetHeight == 0) { window.setTimeout(oslWaitAddressElementOpen, 500); return; } } oslAltNamesClearing = true; for(var j = 0; j < altNames; ++j) { document.getElementsByClassName('alt-street-delete')[j].click(); if(document.getElementsByClassName('alt-street-delete')[j].offsetHeight > 0) { window.setTimeout(oslWaitAddressElementOpen, 500); return; } } } // make sure the Country field is set to "United Kingdom" var snelm = document.getElementsByClassName('country-id')[0]; if(snelm.value != 234) snelm.value = 234; snelm.dispatchEvent(new Event('change', { 'bubbles': true })); // fill in the City field snelm = document.getElementsByClassName('city-name')[0]; if(oslUsingNewName) { if(document.getElementById('optUseNewManual').checked === true) { sessionStorage.cityNameRB = 'optUseNewManual'; } else if(document.getElementById('optUseExistingWME').checked === true) { sessionStorage.cityNameRB = 'optUseExistingWME'; } else if(document.getElementById('optUseOS').checked === true) { sessionStorage.cityNameRB = 'optUseOS'; } if(oslUseName) { snelm.value = oslCityName; snelm.disabled = false; snelm.dispatchEvent(new Event('change', { 'bubbles': true })); snelm = document.getElementsByClassName('empty-city')[0]; snelm.checked = false; snelm.dispatchEvent(new Event('change', { 'bubbles': true })); if(oslCountyName !== '') { // set the county field if one was provided with the selected city name var countyIdx; for(countyIdx = 0; countyIdx < document.getElementsByClassName('state-id')[0].options.length; countyIdx++) { if(document.getElementsByClassName('state-id')[0].options[countyIdx].innerHTML == oslCountyName) { document.getElementsByClassName('state-id')[0].options.selectedIndex = countyIdx; document.getElementsByClassName('state-id')[0].dispatchEvent(new Event('change', { 'bubbles': true })); break; } } } } } else if(document.getElementById('optClearExisting').checked === true) { sessionStorage.cityNameRB = 'optClearExisting'; snelm.disabled = true; snelm.dispatchEvent(new Event('change', { 'bubbles': true })); snelm = document.getElementsByClassName('empty-city')[0]; snelm.checked = true; snelm.dispatchEvent(new Event('change', { 'bubbles': true })); } else { sessionStorage.cityNameRB = 'optUseExisting'; } if(oslUseAlt === true) { var tName = oslLocatorElements[OSL_ELM.RoadName]; oslLocatorElements[OSL_ELM.RoadName] = oslLocatorElements[OSL_ELM.AltName]; oslLocatorElements[OSL_ELM.AltName] = tName; } // finally the Street field var oslName = oslLocatorElements[OSL_ELM.RoadNumber]; if((oslLocatorElements[OSL_ELM.RoadName].length > 0)&&(oslLocatorElements[OSL_ELM.RoadNumber].length > 0)) oslName += ' - '; var altName = oslName; if((oslName.length > 0)||(oslLocatorElements[OSL_ELM.RoadName].length > 0)) { oslName += oslWazeifyStreetName(oslLocatorElements[OSL_ELM.RoadName], false); oslPrevStreetName = oslName; snelm = document.getElementsByClassName('street-name')[0]; snelm.value = oslName; snelm.disabled = false; snelm.dispatchEvent(new Event('change', { 'bubbles': true })); snelm = document.getElementsByClassName('empty-street')[0]; snelm.checked = false; snelm.dispatchEvent(new Event('change', { 'bubbles': true })); } else { snelm = document.getElementsByClassName('street-name')[0]; snelm.value = ''; snelm.disabled = true; snelm.dispatchEvent(new Event('change', { 'bubbles': true })); snelm = document.getElementsByClassName('empty-street')[0]; snelm.checked = true; snelm.dispatchEvent(new Event('change', { 'bubbles': true })); } if(oslLocatorElements[OSL_ELM.AltName] != '') { altName += oslWazeifyStreetName(oslLocatorElements[OSL_ELM.AltName], false); document.getElementsByClassName('add-alt-street-btn')[0].click(); snelm = document.getElementsByClassName('alt-street-name')[0]; snelm.value = altName; snelm.disabled = false; snelm.dispatchEvent(new Event('change', { 'bubbles': true})); if(document.getElementById('optUseExisting').checked === true) { if(document.getElementsByClassName('empty-city')[0].checked === true) { snelm = document.getElementsByClassName('alt-address empty-city')[0]; snelm.checked = true; snelm.dispatchEvent(new Event('change', { 'bubbles': true })); } else { oslUsingNewName = true; oslUseName = true; oslCityName = document.getElementsByClassName("city-name form-control")[0].value; } } snelm = document.getElementsByClassName('alt-city-name')[0]; if(oslUsingNewName) { if(oslUseName) { snelm.value = oslCityName; snelm.disabled = false; snelm.dispatchEvent(new Event('change', { 'bubbles': true })); snelm = document.getElementsByClassName('alt-address empty-city')[0]; snelm.checked = false; snelm.dispatchEvent(new Event('change', { 'bubbles': true })); } } else if(document.getElementById('optClearExisting').checked === true) { snelm.disabled = true; snelm.dispatchEvent(new Event('change', { 'bubbles': true })); snelm = document.getElementsByClassName('alt-address empty-city')[0]; snelm.checked = true; snelm.dispatchEvent(new Event('change', { 'bubbles': true })); } } if(oslAdvancedMode) { // auto-click the Apply button... document.getElementsByClassName('address-form')[0].getElementsByClassName('save-button')[0].click(); } } function oslMatch(oslLink, oslArea, oslRadioID, oslAltRadioID) { this.oslLink = oslLink; this.oslArea = oslArea; this.oslRadioID = oslRadioID; this.oslAltRadioID = oslAltRadioID; } function oslSortCandidates(a,b) { var x = a.oslArea; var y = b.oslArea; return((x<y) ? -1 : ((x>y) ? 1 : 0)); } function oslCityNameKeyup() { oslCheckCityNameDuplicates(oslCaseCorrect(document.getElementById('myCityName').value),0); document.getElementById('optUseNewManual').checked = true; } function oslSelectWMEName() { var oWCN = document.getElementById('oslWMECityNames'); var cityName = oWCN.options[oWCN.options.selectedIndex].text; oslCheckCityNameDuplicates(cityName,0); document.getElementById('optUseExistingWME').checked = true; } function oslSelectOSName() { var oOCN = document.getElementById('oslOSCityNames'); var cityName = oOCN.options[oOCN.options.selectedIndex].text; cityName = cityName.substring(0,cityName.indexOf('[')-1); document.getElementById('optUseOS').checked = true; document.getElementById('oslCNInfo').innerHTML = ''; } function oslBlockCacheObj(blockName) { this.blockName = blockName; this.lastAccessed = Math.floor(new Date().getTime() / 1000); } function oslLoadBlocks() { for(var i = 0; i < oslBlocksToLoad.length;) { // inject block data var script = document.createElement("script"); script.setAttribute('type','text/javascript'); script.setAttribute('charset','UTF-8'); script.src = oslBlocksToLoad[i]; document.head.appendChild(script); oslLoadingMsg = true; oslBlockCacheList.push(new oslBlockCacheObj(oslBlocksToLoad[i+1])); i += 2; } } function oslToOSGrid(lat, lon, mode) { if(oslInUK === false) return; var loop; var i; var x; var y; var eBlock_point; var nBlock_point; var eBlock; var nBlock; if((lat !== 0) && (mode != OSL_MODE.OpenRoads)) { if(mode == OSL_MODE.NameCheck) { oslEastings = lat; oslNorthings = lon; } else { oslLatitude = lat; oslLongitude = lon; oslWGStoOSGB(); } } if((mode == OSL_MODE.OpenNames) || (mode == OSL_MODE.NameCheck)) { // determine which grid block contains the current mouse position eBlock_point = (Math.floor(oslEastings/oslLocatorBlockSize)) * oslLocatorBlockSize; nBlock_point = (Math.floor(oslNorthings/oslLocatorBlockSize)) * oslLocatorBlockSize; var candidates = []; oslBlocksToLoad = []; var arrayName; var oslEvalString; for(x = -1; x < 2; x++) { for(y = -1; y < 2; y++) { eBlock = (eBlock_point + (oslLocatorBlockSize * x)); nBlock = (nBlock_point + (oslLocatorBlockSize * y)); // check we're within the outer bounds of the current OS dataset... if ( (eBlock >= 64000) && (eBlock <= 655999) && (nBlock >= 8000) && (nBlock <= 1214999) ) { arrayName = 'locatorData_'+eBlock+'_'+nBlock; // check to see if there's a corresponding array already loaded... oslEvalString = 'typeof '+arrayName; if(eval(oslEvalString) == "undefined") { // create a blank placeholder which will get replaced by the actual data if the array is present on the server... eval(arrayName+' = []'); oslBlocksToLoad.push(oslBlockPath+Math.floor(eBlock / 100000)+'/'+Math.floor(nBlock / 100000)+'/'+arrayName+'.user.js'); oslBlocksToLoad.push(arrayName); } } } } if(oslBlocksToLoad.length > 0) { oslLoadBlocks(); } candidates = []; if(mode == OSL_MODE.OpenNames) candidates[candidates.length++] = new oslMatch('<label style="display:inline;"><input type="radio" name="oslChoice" id="oslID_null_null_null" />Un-named segment</label><br>',1000000000000,'oslID_null_null_null',null); for(x = -1; x < 2; x++) { for(y = -1; y < 2; y++) { eBlock = (eBlock_point + (oslLocatorBlockSize * x)); nBlock = (nBlock_point + (oslLocatorBlockSize * y)); // check we're within the outer bounds of the current OS dataset... if ((eBlock >= 64000) && (eBlock <= 655999) && (nBlock >= 8000) && (nBlock <= 1214999)) { arrayName = 'locatorData_'+eBlock+'_'+nBlock; oslEvalString = 'typeof '+arrayName; if(eval(oslEvalString) != "undefined") { oslLoadingMsg = false; // yes... make a local copy to avoid having an eval() in each iteration of the loop if((eBlock != oslEvalEBlock) || (nBlock != oslEvalNBlock)) { oslEvalEBlock = eBlock; oslEvalNBlock = nBlock; var evalstr = 'oslBlockData = locatorData_'+eBlock+'_'+nBlock; eval(evalstr); } for (var bcObj in oslBlockCacheList) { if(oslBlockCacheList[bcObj].blockName == arrayName) { oslBlockCacheList[bcObj].lastAccessed = Math.floor(new Date().getTime() / 1000); } } var bdstr = ''; var preselect = false; for(loop = 0;loop < oslBlockData.length; loop++) { var locatorElements = []; // for each entry in the array, test the centrepoint position to see if it lies within the bounding box for that entry // note that we allow a 30m tolerance on all sides of the box to allow for inaccuracies in the latlon->gridref conversion, // and to increase the chance of a successful match when the road runs E-W or N-S and thus has a long but narrow bounding box // the following block of code more or less replicates the string.split() method, but is around 2x faster in the Chrome // JS engine... if(navigator.userAgent.indexOf("Chrome") != -1) { bdstr = oslBlockData[loop]; while(bdstr.indexOf(':') != -1) { locatorElements.push(bdstr.substr(0,bdstr.indexOf(':'))); bdstr = bdstr.substr(bdstr.indexOf(':')+1); } locatorElements.push(bdstr); } else { locatorElements = oslBlockData[loop].split(':'); } if((locatorElements[OSL_ELM.RoadName].length > 0) || (locatorElements[OSL_ELM.RoadNumber].length > 0)) { var tolE; var tolN; if(mode == OSL_MODE.NameCheck) { // wider tolerance when doing a namecheck lookup, to reduce falsely flagging roads as being mis-named tolE = 20; tolN = 30; } else { // tighter tolerance when doing other lookups tolE = 10; tolN = 10; } var streetName = ''; if(locatorElements[OSL_ELM.RoadNumber].length > 0) { streetName += locatorElements[OSL_ELM.RoadNumber]; if(locatorElements[OSL_ELM.RoadName].length > 0) { streetName += ' - '; } } streetName += oslWazeifyStreetName(locatorElements[OSL_ELM.RoadName], false); var altName = ''; if(locatorElements[OSL_ELM.AltName] != '') { if(locatorElements[OSL_ELM.RoadNumber].length > 0) { altName += locatorElements[OSL_ELM.RoadNumber]; if(locatorElements[OSL_ELM.AltName].length > 0) { altName += ' - '; } } altName += oslWazeifyStreetName(locatorElements[OSL_ELM.AltName], false); } if(mode == OSL_MODE.OpenNames) { // Name search from mouse position... var bbPix = oslGetBBCornerPixels(parseFloat(locatorElements[OSL_ELM.BoundW]), parseFloat(locatorElements[OSL_ELM.BoundE]), parseFloat(locatorElements[OSL_ELM.BoundS]), parseFloat(locatorElements[OSL_ELM.BoundN])); bbPix[0] -= tolE; bbPix[1] += tolE; bbPix[2] += tolN; bbPix[3] -= tolN; if((oslMousePixelpos.x >= bbPix[0])&&(oslMousePixelpos.x <= bbPix[1])&&(oslMousePixelpos.y <= bbPix[2])&&(oslMousePixelpos.y >= bbPix[3])) { var area = ((bbPix[1] - bbPix[0]) * (bbPix[2] - bbPix[3])); var radioID = 'oslID_'+eBlock+'_'+nBlock+'_'+loop; var altRadioID = null; var oslLink = '<label style="display:inline;"><input type="radio" name="oslChoice" id="'+radioID+'"'; if((streetName == oslPrevStreetName)&&(preselect === false)) { oslLink += 'checked="true"'; preselect = true; } oslLink += '/>'; oslLink += streetName+' [<i>'+locatorElements[OSL_ELM.AreaName]+'</i>]</label>'; if(altName != '') { altRadioID = 'alt-'+radioID; oslLink += '<br> <label style="display:inline;"><input type="radio" name="oslChoice" id="'+altRadioID+'"'; if((altName == oslPrevStreetName)&&(preselect === false)) { oslLink += 'checked="true"'; preselect = true; } oslLink += '/>'; oslLink += '<i>Alt name: '+altName+'</i></label>'; } if(locatorElements[OSL_ELM.Form] == 'Collapsed Dual Carriageway') { locatorElements[OSL_ELM.Form] = 'Dual Carriageway'; } oslLink += '<br> <i>'+oslRoadClassifications[locatorElements[OSL_ELM.Classification]] + ' - '; oslLink += oslRoadFunctions[locatorElements[OSL_ELM.Function]] + ' - ' + oslFormsOfWay[locatorElements[OSL_ELM.Form]]; if(locatorElements[OSL_ELM.Structure] == OSL_ROADSTRUCTURES.Road_In_Tunnel) { oslLink += ' [Tunnel]'; } else if(locatorElements[OSL_ELM.Structure] == OSL_ROADSTRUCTURES.Road_On_Bridge) { oslLink += ' [Bridge]'; } if(locatorElements[OSL_ELM.IsPrimary] == 'Y') { oslLink += ' (PRN)'; } if(locatorElements[OSL_ELM.IsTrunk] == 'Y') { oslLink += ' (TRN)'; } oslLink += '</i><br>'; candidates[candidates.length++] = new oslMatch(oslLink,area,radioID,altRadioID); } } else if(mode == OSL_MODE.NameCheck) { // NameCheck comparisons... var bbW = parseFloat(locatorElements[OSL_ELM.BoundW]) - tolE; var bbE = parseFloat(locatorElements[OSL_ELM.BoundE]) + tolE; var bbS = parseFloat(locatorElements[OSL_ELM.BoundS]) - tolN; var bbN = parseFloat(locatorElements[OSL_ELM.BoundN]) + tolN; for(i=0;i<oslOSLNCSegments.length;i++) { if(oslOSLNCSegments[i].match === false) { if ( ((oslOSLNCSegments[i].lonA >= bbW) && (oslOSLNCSegments[i].lonA <= bbE)) && ((oslOSLNCSegments[i].lonB >= bbW) && (oslOSLNCSegments[i].lonB <= bbE)) && ((oslOSLNCSegments[i].latA >= bbS) && (oslOSLNCSegments[i].latA <= bbN)) && ((oslOSLNCSegments[i].latB >= bbS) && (oslOSLNCSegments[i].latB <= bbN)) ) { if((oslOSLNCSegments[i].streetname == streetName) || (oslOSLNCSegments[i].streetname == altName)) oslOSLNCSegments[i].match = true; } } } } } } } } } } if(mode == OSL_MODE.OpenNames) { var newHTML = '<b>Matches at '+oslEastings+', '+oslNorthings+'</b>'; if(candidates.length > 0) { var btnStyle = "cursor:pointer;"; btnStyle += "font-size:14px;"; btnStyle += "border: thin outset black;"; btnStyle += "padding:2px 10px 2px 10px;"; btnStyle += "background: #ccccff;"; newHTML += '<div style="margin:10px;"><span id="oslSelect" style="'+btnStyle+'">'; if(oslAdvancedMode) newHTML += 'Apply to Properties'; else newHTML += 'Copy to Properties'; newHTML += '</span></div>'; if(candidates.length > 1) candidates.sort(oslSortCandidates); for(loop=0;loop<candidates.length;loop++) { newHTML += candidates[loop].oslLink; } newHTML += '<br>City name:<br>'; newHTML += '<label style="display:inline;"><input type="radio" name="oslCityNameOpt" id="optUseExisting"/>Use existing segment name(s)</label><br>'; newHTML += '<label style="display:inline;"><input type="radio" name="oslCityNameOpt" id="optClearExisting" />Clear existing segment name(s)</label><br>'; newHTML += '<label style="display:inline;"><input type="radio" name="oslCityNameOpt" id="optUseNewManual" />Use new name:</label><br>'; newHTML += ' <input id="myCityName" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px; transition:none; focus:none; box-shadow:none" type="text"'; if(sessionStorage.cityNameRB == 'optUseNewManual') newHTML += 'value="'+sessionStorage.myCity+'"/><br>'; else newHTML += 'value=""/><br>'; newHTML += '<label style="display:inline;"><input type="radio" name="oslCityNameOpt" id="optUseExistingWME" />Use name from map:</label><br>'; newHTML += ' <select id="oslWMECityNames"></select><br>'; newHTML += '<label style="display:inline;"><input type="radio" name="oslCityNameOpt" id="optUseOS" />Use name from OS Gazetteer:</label><br>'; newHTML += ' <select id="oslOSCityNames"></select><br>'; newHTML += '<div id="oslCNInfo"></div><br>'; oslRoadNameMatches.innerHTML = newHTML; oslGetNearbyCityNames(); var oWCN = document.getElementById('oslWMECityNames'); var nameList = []; for(var cityObj in W.model.cities.objects) { if(W.model.cities.objects.hasOwnProperty(cityObj)) { var cityname = W.model.cities.objects[cityObj].attributes.name; if(cityname !== '') { var countyID = []; countyID[0] = W.model.cities.objects[cityObj].attributes.stateID; var countyName = W.model.states.getByIds(countyID)[0].name; if(countyName !== '') { cityname += ', '+countyName; } nameList.push(cityname); } } } nameList.sort(); var matchedWMEName = false; for(i=0; i<nameList.length; i++) { var listOpt = document.createElement('option'); listOpt.text = nameList[i]; oWCN.add(listOpt,null); if(sessionStorage.cityNameRB == 'optUseExistingWME') { if(nameList[i] == sessionStorage.myCity) { oWCN.options.selectedIndex = i; matchedWMEName = true; } } } if((!matchedWMEName) && (sessionStorage.cityNameRB == 'optUseExistingWME')) { oWCN.options.selectedIndex = 0; } document.getElementById('oslSelect').addEventListener("click", oslClick, true); document.getElementById('oslWMECityNames').addEventListener("click", oslSelectWMEName, true); document.getElementById('optUseExistingWME').addEventListener("click", oslSelectWMEName, true); document.getElementById('oslOSCityNames').addEventListener("click", oslSelectOSName, true); document.getElementById('optUseOS').addEventListener("click", oslSelectOSName, true); document.getElementById('myCityName').addEventListener("keyup", oslCityNameKeyup, true); document.getElementById('optUseNewManual').addEventListener("click", oslCityNameKeyup, true); for(loop=0;loop<candidates.length;loop++) { document.getElementById(candidates[loop].oslRadioID).addEventListener("click", oslRadioClick, true); if(candidates[loop].oslAltRadioID != null) { document.getElementById(candidates[loop].oslAltRadioID).addEventListener("click", oslRadioClick, true); } } document.getElementById(sessionStorage.cityNameRB).checked = true; oslKeepUIVisible(); } else oslRoadNameMatches.innerHTML = newHTML; } } if(mode == OSL_MODE.OpenRoads) { // OpenRoads check var eastingsLeft = (Math.floor(oslVPLeft/oslLocatorBlockSize) - 1) * oslLocatorBlockSize; var eastingsRight = (Math.ceil(oslVPRight/oslLocatorBlockSize) + 1) * oslLocatorBlockSize; var northingsTop = (Math.ceil(oslVPTop/oslLocatorBlockSize) + 1) * oslLocatorBlockSize; var northingsBottom = (Math.floor(oslVPBottom/oslLocatorBlockSize) - 1) * oslLocatorBlockSize; var highlightMode = 0; for(var eLoop = eastingsLeft; eLoop <= eastingsRight; eLoop += oslLocatorBlockSize) { for(var nLoop = northingsBottom; nLoop <= northingsTop; nLoop += oslLocatorBlockSize) { highlightMode = oslHighlightOpenRoads(eLoop,nLoop,highlightMode); } } oslHighlightOpenRoads(0,0,2); } else return '?e='+oslEastings+'&n='+oslNorthings; } function oslRemoveDirSuffix(currentName, dirSuffix) { var dPos = currentName.indexOf(dirSuffix); if(dPos != -1) { var dLength = dirSuffix.length; currentName = currentName.substr(0,dPos) + currentName.substr(dPos+dLength); } return currentName; } function oslNameCheckTrigger() { oslOSLNameCheckTimer = 2; } function oslNameComparison() { for(;oslONC_E<=oslEBlock_max;) { for(;oslONC_N<=oslNBlock_max;) { oslToOSGrid(oslONC_E*oslLocatorBlockSize, oslONC_N*oslLocatorBlockSize, OSL_MODE.NameCheck); if(oslLoadingMsg === true) { window.setTimeout(oslNameComparison,500); return; } oslONC_N++; } oslONC_N = oslNBlock_min; oslONC_E++; } for(var i=0;i<oslOSLNCSegments.length;i++) { if(oslOSLNCSegments[i].match === false) { var pline = oslOSLNCSegments[i].pline; pline.setAttribute("stroke","#000000"); pline.setAttribute("stroke-opacity","0.5"); pline.setAttribute("stroke-width","9"); pline.setAttribute("stroke-dasharray","none"); } } } function oslNCCandidateNew(pline, lonA, latA, lonB, latB, streetname) { this.pline = pline; this.lonA = lonA; this.latA = latA; this.lonB = lonB; this.latB = latB; this.streetname = streetname; this.match = false; } function oslNCStateChange() { if(document.getElementById('_cbNCEnabled').checked === false) { for(var segObj in W.model.segments.objects) { if(W.model.segments.objects.hasOwnProperty(segObj)) { var seg = W.model.segments.objects[segObj]; var pline = document.getElementById(seg.geometry.id); if(pline !== null) { pline.setAttribute("stroke-width","5"); pline.setAttribute("stroke","#dd7700"); pline.setAttribute("stroke-opacity","0.001"); pline.setAttribute("stroke-dasharray","none"); } } } } else { if(W.map.getZoom() >= 4) oslNameCheck(); } } function oslOpenRoadsStateChange(e) { oslMapIsStaticProcessing(true); oslUpdateHighlightCBs(e.srcElement.id); } function oslNameCheck() { if((document.getElementById('_cbNCEnabled').checked === false) || (W.map.getZoom() < 4)) return; var geoCenter=new OpenLayers.LonLat(W.map.getCenter().lon,W.map.getCenter().lat); geoCenter.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326")); oslToOSGrid(geoCenter.lat, geoCenter.lon, OSL_MODE.Conversion); if(oslLoadingMsg === true) { window.setTimeout(oslNameCheck,500); return; } oslEBlock_min = 99999; oslEBlock_max = -1; oslNBlock_min = 99999; oslNBlock_max = -1; var mapExtents = W.map.getExtent(); var ignoreSegment; oslOSLNCSegments = []; for(var segObj in W.model.segments.objects) { if(W.model.segments.objects.hasOwnProperty(segObj)) { ignoreSegment = false; var seg = W.model.segments.objects[segObj]; var segRT = seg.attributes.roadType; if ( (seg.geometry.bounds.left > mapExtents.right) || (seg.geometry.bounds.right < mapExtents.left) || (seg.geometry.bounds.top < mapExtents.bottom) || (seg.geometry.bounds.bottom > mapExtents.top) ) { // ignore segment as it's not visible... ignoreSegment = true; } if ( (segRT < 1) || ((segRT > 3) && (segRT < 6)) || ((segRT > 8) && (segRT < 17)) || ((segRT > 17) && (segRT < 20)) || (segRT > 21) ) { // ignore segment as it's non-driveable... ignoreSegment = true; } if(ignoreSegment === false) { var streetObj = W.model.streets.objects[seg.attributes.primaryStreetID]; if(streetObj !== undefined) { var currentName = streetObj.name; var gid = seg.geometry.id; var pline = document.getElementById(gid); if((currentName !== null) && (pline !== null)) { currentName = oslRemoveDirSuffix(currentName,' (N)'); currentName = oslRemoveDirSuffix(currentName,' (S)'); currentName = oslRemoveDirSuffix(currentName,' (E)'); currentName = oslRemoveDirSuffix(currentName,' (W)'); currentName = oslRemoveDirSuffix(currentName,' (CW)'); currentName = oslRemoveDirSuffix(currentName,' (ACW)'); var endPointA = new OpenLayers.LonLat(seg.geometry.components[0].x,seg.geometry.components[0].y); endPointA.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326")); oslToOSGrid(endPointA.lat, endPointA.lon, OSL_MODE.Conversion); var eBlock = Math.floor(oslEastings/oslLocatorBlockSize); var nBlock = Math.floor(oslNorthings/oslLocatorBlockSize); if(eBlock < oslEBlock_min) oslEBlock_min = eBlock; if(eBlock > oslEBlock_max) oslEBlock_max = eBlock; if(nBlock < oslNBlock_min) oslNBlock_min = nBlock; if(nBlock > oslNBlock_max) oslNBlock_max = nBlock; var endPointB = new OpenLayers.LonLat(seg.geometry.components[seg.geometry.components.length-1].x,seg.geometry.components[seg.geometry.components.length-1].y); endPointB.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326")); oslToOSGrid(endPointB.lat, endPointB.lon, OSL_MODE.Conversion); oslOSLNCSegments.push(new oslNCCandidateNew(pline, endPointA.lon, endPointA.lat, endPointB.lon, endPointB.lat, currentName)); eBlock = Math.floor(oslEastings/oslLocatorBlockSize); nBlock = Math.floor(oslNorthings/oslLocatorBlockSize); if(eBlock < oslEBlock_min) oslEBlock_min = eBlock; if(eBlock > oslEBlock_max) oslEBlock_max = eBlock; if(nBlock < oslNBlock_min) oslNBlock_min = nBlock; if(nBlock > oslNBlock_max) oslNBlock_max = nBlock; } } } } } if(oslOSLNCSegments.length > 0) { oslONC_E = oslEBlock_min; oslONC_N = oslNBlock_min; oslNameComparison(); } } function oslTenthSecondTick() { if(W.app.modeController.mode.mteModeState !== undefined) { if(!oslMTEMode) { oslAddLog('MTE mode, sleeping until normal service is resumed...'); oslWindowMinimise(); } oslMTEMode = true; return; } oslMTEMode = false; if(oslMOAdded === false) { if(document.getElementById('edit-panel') !== null) { oslAddLog('edit-panel mutation observer added...'); var editPanelMO = new MutationObserver(oslEditPanelCheck); editPanelMO.observe(document.getElementById('edit-panel'),{childList:true,subtree:true}); oslMOAdded = true; } } var hideUI = Boolean ( (document.getElementsByClassName('menu')[0].className.indexOf('not-visible') === -1) && (document.getElementsByClassName('menu')[0].className.indexOf('hide') === -1) ); hideUI = Boolean(hideUI || (document.getElementsByClassName('toolbar-group open').length > 0)); if(hideUI === false) { oslWindow.style.zIndex = 2000; } else { oslWindow.style.zIndex = -2000; } if(!oslAdvancedMode) oslEnableAdvancedOptions(); var oslSelectedItems = []; if(W.selectionManager.selectedItems === undefined) { oslSelectedItems = W.selectionManager._selectedFeatures; } else { oslSelectedItems = W.selectionManager.selectedItems; } if(oslSelectedItems.length == 1) { if(oslPrevSelected === null) oslDoOSLUpdate = true; else if(oslSelectedItems[0].model.attributes.id != oslPrevSelected) oslDoOSLUpdate = true; oslPrevSelected = oslSelectedItems[0].model.attributes.id; } else { oslPrevSelected = null; } if(document.getElementById('oslSelect') !== null) { var editDisabled = ((document.getElementsByClassName('full-address disabled').length > 0) || (document.getElementsByClassName('full-address-container').length === 0)); if(editDisabled === true) { document.getElementById('oslSelect').style.background = "rgb(160, 160, 160)"; } else { document.getElementById('oslSelect').style.background = "rgb(204, 204, 255)"; } document.getElementById('oslSelect').disabled = editDisabled; } if(oslOSLNameCheckTimer > 0) { if(--oslOSLNameCheckTimer === 0) oslNameCheck(); } var bcIdx; var timeNow; if(--oslBlockCacheTestTimer === 0) { oslBlockCacheTestTimer = (oslCacheDecayPeriod * 10); timeNow = Math.floor(new Date().getTime() / 1000); for(bcIdx = oslBlockCacheList.length-1; bcIdx >= 0; bcIdx--) { if((timeNow - oslBlockCacheList[bcIdx].lastAccessed) > oslCacheDecayPeriod) { eval('delete '+oslBlockCacheList[bcIdx].blockName); oslBlockCacheList.splice(bcIdx,1); } } } if((oslDoOSLUpdate === true) && (oslMousepos !== null)) { // update the OS Locator matches oslToOSGrid(oslMousepos.lat,oslMousepos.lon,OSL_MODE.OpenNames); oslDoOSLUpdate = oslLoadingMsg; if(!oslDoOSLUpdate) oslRadioClick(); } if(oslRefreshAutoTrack) { // refresh any of the site tabs/windows we've checked for auto-tracking if(oslInUK === true) { if(document.getElementById('_cbAutoTrackOSOD').checked == 1) window.open(oslOSOD_url,'_osopendata'); if(document.getElementById('_cbAutoTrackRWO').checked == 1) window.open(oslRWO_url,'_roadworksorg'); if(oslInWiltshire === true) { if(document.getElementById('_cbAutoTrackSWG').checked == 1) window.open(oslSWG_url,'_wiltshire'); } if(oslInLondon === true) { if(document.getElementById('_cbAutoTrackLRR').checked == 1) window.open(oslLRR_url,'_londonregister'); } } oslRefreshAutoTrack = false; } if(oslBlocksToTest.length > 0) { for(var i=0; i<oslBlocksToTest.length; i++) { var oslEvalString = 'typeof '+oslBlocksToTest[i]; if(eval(oslEvalString) != 'undefined') { oslBlocksToTest.splice(i, 1); } } if(oslBlocksToTest.length === 0) { oslMapIsStaticProcessing(true); } } } function oslEnableAdvancedOptions() { if (oslAdvancedMode) return; if(W.loginManager === null) return; if(W.loginManager.isLoggedIn() === true) { var thisUser = W.loginManager.user; if (thisUser !== null && thisUser.getRank() >= 2) { oslAdvancedMode = true; oslAddLog('advanced mode enabled'); } } } function oslUpdateLiveMapLink() { var lmLink = document.getElementById('livemap-link'); if(lmLink === null) { window.setTimeout(oslUpdateLiveMapLink,100); return; } // translate the zoom level between WME and live map. var livemap_zoom = parseInt(sessionStorage.zoom)+12; if (livemap_zoom > 17) livemap_zoom = 17; var livemap_url = 'https://www.waze.com/livemap/?'; livemap_url += 'lon='+sessionStorage.lon; livemap_url += '&lat='+sessionStorage.lat; livemap_url += '&zoom='+livemap_zoom; // Modify existing livemap link to reference current position in WME lmLink.href = livemap_url; lmLink.target = '_blank'; } function oslOSGridRefToPixel(osEast, osNorth) { var lonlat = new OpenLayers.LonLat(); lonlat.lon = parseFloat(osEast); lonlat.lat = parseFloat(osNorth); lonlat.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913")); return W.map.getPixelFromLonLat(lonlat); } function oslBoundsCheck(pix1, pix2, width, height) { var xmin = Math.min(pix1.x,pix2.x); var xmax = Math.max(pix1.x,pix2.x); var ymin = Math.min(pix1.y,pix2.y); var ymax = Math.max(pix1.y,pix2.y); var retval = ( (xmin <= width) && (xmax >= 0) && (ymin <= height) && (ymax >= 0) ); return retval; } function oslHighlightOpenRoads(oslEastings, oslNorthings, mode) { oslBlocksToLoad = []; if((mode === 0) || (mode == 1)) { var arrayName = 'locatorData_'+oslEastings+'_'+oslNorthings; // check to see if there's a corresponding array loaded already var oslEvalString = 'typeof '+arrayName; if(eval(oslEvalString) == "undefined") { // create a blank placeholder which will get replaced by the actual data if the array is present on the server... eval(arrayName+' = []'); oslBlocksToLoad.push(oslBlockPath+Math.floor(oslEastings / 100000)+'/'+Math.floor(oslNorthings / 100000)+'/'+arrayName+'.user.js'); oslBlocksToLoad.push(arrayName); oslBlocksToTest.push(arrayName); oslLoadBlocks(); } var divWidth = document.getElementById('WazeMap').offsetWidth; var divHeight = document.getElementById('WazeMap').offsetHeight; var displayPoints = false; if(mode === 0) { // initialise SVG container oslSegGeoDivInnerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="'+divWidth+'px" height="'+divHeight+'px" version="1.1">'; } // create local copy of array to avoid an eval() in each iteration of the loop if(eval('typeof '+arrayName) == "undefined") return; var oslOpenRoadsData; eval('oslOpenRoadsData = '+arrayName); // calculate an appropriate stroke width for the current zoom level var strokeWidth = W.map.getZoom(); if(strokeWidth < 2) strokeWidth = 2; if(strokeWidth > 9) strokeWidth = 9; var renderByFunction = []; renderByFunction.push(true); // Undefined roads always get rendered when the OpenRoads layer is enabled renderByFunction.push(document.getElementById('_cbSegGeoMotorway').checked); renderByFunction.push(document.getElementById('_cbSegGeoARoad').checked); renderByFunction.push(document.getElementById('_cbSegGeoBRoad').checked); renderByFunction.push(document.getElementById('_cbSegGeoMinor').checked); renderByFunction.push(document.getElementById('_cbSegGeoLocal').checked); if(oslAdvancedMode == true) { renderByFunction.push(document.getElementById('_cbSegGeoLocalAccess').checked); renderByFunction.push(document.getElementById('_cbSegGeoRestricted').checked); renderByFunction.push(document.getElementById('_cbSegGeoSecondary').checked); } else { renderByFunction.push(false); renderByFunction.push(false); renderByFunction.push(false); } var useFullGeo = document.getElementById('_cbOpenRoadsUseGeo').checked; var enhancePolylines = document.getElementById('_cbOpenRoadsEnhanceGeoVis').checked; var pix1; var pix2; var nameColour; for(var roadIdx = 0; roadIdx < oslOpenRoadsData.length; roadIdx++) { var roadEntry = oslOpenRoadsData[roadIdx]; var elements = roadEntry.split(':'); var roadFunction = parseInt(elements[OSL_ELM.Function]); if ((elements[OSL_ELM.RoadName] == '') && (elements[OSL_ELM.RoadNumber] == '')) { nameColour = 'cyan'; } else { nameColour = 'magenta'; } if(renderByFunction[roadFunction] == true) { pix1 = oslOSGridRefToPixel(elements[OSL_ELM.BoundW], elements[OSL_ELM.BoundS]); pix2 = oslOSGridRefToPixel(elements[OSL_ELM.BoundE], elements[OSL_ELM.BoundN]); if(oslBoundsCheck(pix1, pix2, divWidth, divHeight) == true) { if(useFullGeo == true) { var geoPairs = elements[OSL_ELM.Geometry].split(' '); var geoPoints = geoPairs[0].split(' '); var isTunnel = (elements[OSL_ELM.Structure] == OSL_ROADSTRUCTURES.Road_In_Tunnel); pix1 = oslOSGridRefToPixel(geoPoints[0], geoPoints[1]); var pline = ''; for(var pts=1; pts < geoPairs.length; pts++) { geoPoints = geoPairs[pts].split(' '); pix2 = oslOSGridRefToPixel(geoPoints[0],geoPoints[1]); if(oslBoundsCheck(pix1, pix2, divWidth, divHeight) == true) { if(displayPoints === false) { pline += '<polyline points="'; displayPoints = true; } pline += pix1.x+','+pix1.y+' '+pix2.x+','+pix2.y+' '; } pix1 = pix2; } if(displayPoints === true) { var strokeColour = oslStrokeColoursByFunction[roadFunction]; var strokeArray = ''; if(isTunnel == true) { strokeArray = 'stroke-dasharray:10,10;'; } if(enhancePolylines == true) { oslSegGeoDivInnerHTML += pline + '" style="stroke:'; oslSegGeoDivInnerHTML += nameColour; oslSegGeoDivInnerHTML += ';'+strokeArray+'stroke-width:'+(strokeWidth+11)+';stroke-linecap:round;fill:none"/>'; } oslSegGeoDivInnerHTML += pline + '" style="stroke:black;'+strokeArray+'stroke-width:'+(strokeWidth+2)+';stroke-linecap:round;fill:none"/>'; oslSegGeoDivInnerHTML += pline + '" style="stroke:'+strokeColour+';'+strokeArray+'stroke-width:'+strokeWidth+';stroke-linecap:round;fill:none"/>'; displayPoints = false; } } else { const minDim = 20; var bWidth = Math.abs(pix2.x-pix1.x); if(bWidth < minDim) bWidth = minDim; var bHeight = Math.abs(pix2.y-pix1.y); if(bHeight < minDim) bHeight = minDim; oslSegGeoDivInnerHTML += '<rect x="'+pix1.x+'" y="'+pix2.y+'" width="'+bWidth+'" height="'+bHeight+'" style="fill:'; oslSegGeoDivInnerHTML += nameColour; oslSegGeoDivInnerHTML += ';stroke:black;stroke-width:4;fill-opacity:0.25;stroke-opacity:0.25"/>'; } } } } } else if(mode == 2) { // finalise SVG oslSegGeoDivInnerHTML += '</svg>'; oslSegGeoDiv.innerHTML = oslSegGeoDivInnerHTML; } else if(mode == 3) { // erase SVG oslSegGeoDiv.innerHTML = ''; } return 1; } function oslRepositionOverlays(doBoth) { var divTop = (0 - parseInt(oslWazeMapElement.style.top.replace('px',''))); var divLeft = (0 - parseInt(oslWazeMapElement.style.left.replace('px',''))); oslBBDiv.style.top = divTop + 'px'; oslBBDiv.style.left = divLeft + 'px'; if(doBoth == true) { oslSegGeoDiv.style.top = divTop + 'px'; oslSegGeoDiv.style.left = divLeft + 'px'; } } function oslGetCorrectedLonLatFromPixelPos(px, py, toolbarCompensation) { if((toolbarCompensation) && (oslOffsetToolbar)) py -= document.getElementById('toolbar').clientHeight; py -= document.getElementById('topbar-container').clientHeight; var pixelPos = new OpenLayers.Pixel(px, py); return W.map.getLonLatFromPixel(pixelPos); } function oslGetOffsetMapCentre() { // get lon/lat of viewport centrepoint for modifying the livemap link and for passing to the external mapping sites. // shift the longitude pixel offset by half the width of the WME sidebar to account for the lateral offset that would // otherwise occur when switching between the WME tab and the other map tabs - all of those use a full-width map view, // so their map centre is further to the left within the browser window than the WME centrepoint... var mapVPX = (W.map.olMap.getViewport().clientWidth / 2) - (document.getElementById('sidebar').clientWidth / 2); var mapVPY = W.map.olMap.getViewport().clientHeight / 2; return oslGetCorrectedLonLatFromPixelPos(mapVPX, mapVPY, false); } function oslMouseMoveAndUp(e) { if(oslUserPrefs.ui.state == 'minimised') return; var mouseX = e.pageX - document.getElementById('map').getBoundingClientRect().left; var mouseY = e.pageY - document.getElementById('map').getBoundingClientRect().top; oslMousePixelpos = new OpenLayers.Pixel(mouseX, mouseY); oslMousepos = oslGetCorrectedLonLatFromPixelPos(mouseX, mouseY, true).transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326")); if((oslMousepos != sessionStorage.oslMousepos) || (oslLoadingMsg && (eval(oslEvalString) != "undefined"))) { oslLoadingMsg = false; sessionStorage.oslMousepos = oslMousepos; oslDoOSLUpdate = false; // update the OSL results if there are no selected segments, but there is a highlighted segment // which we haven't already done an update for oslSegmentHighlighted = false; var noneSelected = false; if(W.selectionManager.selectedItems !== undefined) { noneSelected = (W.selectionManager.selectedItems.length === 0); } else { noneSelected = (W.selectionManager._selectedFeatures.length === 0); } if(noneSelected === true) { for(var slIdx=0; slIdx < W.map.segmentLayer.features.length; slIdx++) { if(W.map.segmentLayer.features[slIdx].renderIntent == 'highlight') { if(slIdx != oslPrevHighlighted) { oslPrevHighlighted = slIdx; } oslDoOSLUpdate = true; oslSegmentHighlighted = true; } } } } var geoCenter = oslGetOffsetMapCentre(); var geoCenterTransform = oslGetOffsetMapCentre().transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326")); var lat = geoCenterTransform.lat; var lon = geoCenterTransform.lon; var zoom = W.map.getZoom(); // compare the new parameters against the persistent copies, and update the external links // only if there's a change required - the newly-inserted <a> element can't be clicked // on until the insertion process is complete, and if we were to re-insert it every timeout // then it'd spend a lot of its time giving the appearance of being clickable but without // actually doing anything... if((zoom != parseInt(sessionStorage.zoom))||(lat != parseFloat(sessionStorage.lat))||(lon != parseFloat(sessionStorage.lon))) { var country = null; if((W.model.countries.top === undefined)||(W.model.countries.top === null)) { if(W.model.countries.additionalInfo !== null) { country = W.model.countries.additionalInfo[0].name; } } else { country = W.model.countries.top.name; } if(country == "United Kingdom") { if (oslInUK === false) { oslAddLog('location is the UK, enabling full UI...'); oslInUK = true; document.getElementById('oslOSLDiv').style.display = "block"; document.getElementById('oslNCDiv').style.display = "block"; document.getElementById('oslSegGeoUIDiv').style.display = "block"; document.getElementById('_extlinksUK').style.display = "block"; } } else { // ...somewhere not yet supported, or WME isn't telling us just yet... oslAddLog('location not recognised, disabling UK-specific parts of UI...'); oslInUK = false; oslInLondon = false; document.getElementById('oslOSLDiv').style.display = "none"; document.getElementById('oslNCDiv').style.display = "none"; document.getElementById('oslSegGeoUIDiv').style.display = "none"; document.getElementById('_extlinksUK').style.display = "none"; } if(oslInUK === true) { // we're in the UK, so test to see if we're within the approximate Greater London bounding box if((lon >= -0.55) && (lon <= 0.30) && (lat >= 51.285) && (lat <= 51.695)) { oslInLondon = true; document.getElementById('lrrCtrls').style.display='inline'; } else { oslInLondon = false; document.getElementById('lrrCtrls').style.display='none'; } // also see if we're more or less within Wiltshire if((lon >= -2.33) && (lon <= -1.50) && (lat >= 50.94) && (lat <= 51.71)) { oslInWiltshire = true; document.getElementById('swgCtrls').style.display='inline'; } else { oslInWiltshire = false; document.getElementById('swgCtrls').style.display='none'; } } if(zoom != sessionStorage.zoom) { if(zoom < 4) document.getElementById('_cbNCEnabled').disabled = true; else document.getElementById('_cbNCEnabled').disabled = false; } // update the persistent vars with the new position sessionStorage.zoom = zoom; sessionStorage.lat = lat; sessionStorage.lon = lon; if(oslInUK === true) { // calculate the OS eastings/northings for the current WME centrepoint - this is required by the OpenData and London Roadworks sites... var osCoords = oslToOSGrid(lat,lon,OSL_MODE.Conversion); // translate the zoom level between WME and OpenData - the match here isn't quite so good... var odzoom = zoom + 8; if(odzoom < 6) odzoom = 6; if(odzoom > 12) odzoom = 12; // generate the OpenData URL oslOSOD_url = 'https://openspacewmb.ordnancesurvey.co.uk/osmapapi/mapbuilder?'+osCoords+'&z='+odzoom; // generate the one.network URL - no zoom translation required here oslRWO_url = 'https://one.network?lat='+lat+'&lon='+lon+'&z='+zoom+'&showlinks=true'; // generate the Wiltshire streetworks URL - use mapCenter() as is, but translate the zoom level var swgzoom = zoom + 2; if(swgzoom > 11) swgzoom = 11; oslSWG_url = 'http://streetworks.wiltshire.gov.uk/map.aspx?lat='+geoCenter.lat+'&lon='+geoCenter.lon+'&z='+swgzoom; // translate the zoom level between WME and London Roadworks Register - this gives reasonable results up to WME zoom of 5, beyond // which the LRR site can't zoom in any further... var lrrzoom = zoom; if(lrrzoom > 5) lrrzoom = 5; // generate the roadworks register URL oslLRR_url = 'http://public.londonworks.gov.uk/roadworks/home'+osCoords+'&z='+lrrzoom; } // wait to update the livemap link, as WME now does its own update after this point so any changes we make here // end up being wiped out... window.setTimeout(oslUpdateLiveMapLink,100); // update the link URLs if(oslInUK === true) { document.getElementById("_linkOSOD").href = oslOSOD_url; document.getElementById("_linkRWO").href = oslRWO_url; document.getElementById("_linkSWG").href = oslSWG_url; document.getElementById("_linkLRR").href = oslLRR_url; } document.getElementById('_linkPermalink').href = document.getElementsByClassName('WazeControlPermalink')[0].getElementsByTagName('a')[0].href; // refreshing the tabs within the event handler causes Chrome to switch focus to the tabs, so we // simply set the flag here and let the refresh occur within the 100ms tick handler as before oslRefreshAutoTrack = true; oslRadioClick(); } oslRepositionOverlays(false); if((e.type == "mouseup") || (e.type == "zoomend")) { oslMapIsStaticProcessing(false); } } var oslWaitingForMapToStopMoving = false; function oslMapIsStaticProcessing(forceUpdate) { if(oslUserPrefs.ui.state == 'maximised') { var tCenter = W.map.getCenter(); var tZoom = W.map.getZoom(); if ( (oslRORCenter == null) || (tCenter.lat != oslRORCenter.lat) || (tCenter.lon != oslRORCenter.lon) || (oslRORZoom == null) || (tZoom != oslRORZoom) ) { oslWaitingForMapToStopMoving = true; oslRORCenter = tCenter; oslRORZoom = tZoom; window.setTimeout(oslMapIsStaticProcessing, 250); return; } if((oslWaitingForMapToStopMoving == false) && (forceUpdate == false)) { return; } oslWaitingForMapToStopMoving = false; var geoCenter=new OpenLayers.LonLat(W.map.getCenter().lon,W.map.getCenter().lat); geoCenter.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326")); oslToOSGrid(geoCenter.lat, geoCenter.lon, OSL_MODE.Conversion); oslNameCheck(); if(oslInUK === true) { // recalculate the map viewport extents in terms of oslEastings/oslNorthings var vpHalfWidth = (W.map.getExtent().right-W.map.getExtent().left) / (2 * 1.61); var vpHalfHeight = (W.map.getExtent().top-W.map.getExtent().bottom) / (2 * 1.61); oslVPLeft = oslEastings - vpHalfWidth; oslVPRight = oslEastings + vpHalfWidth; oslVPBottom = oslNorthings - vpHalfHeight; oslVPTop = oslNorthings + vpHalfHeight; if(document.getElementById('_cbOpenRoadsEnabled').checked === true) { oslToOSGrid(oslEastings,oslNorthings,OSL_MODE.OpenRoads); } else { oslHighlightOpenRoads(0,0,3); } } else { oslHighlightOpenRoads(0,0,3); } oslRepositionOverlays(true); } } function oslTestPointerOutsideMap(mX, mY) { var mapElm = document.getElementById("map"); if(mapElm === undefined) return false; var bLeft = mapElm.parentElement.offsetLeft; var bRight = (bLeft + mapElm.offsetWidth); var bTop = (mapElm.parentElement.offsetTop + document.getElementById("topbar-container").clientHeight); var bBottom = (mapElm.parentElement.offsetTop + mapElm.offsetHeight + document.getElementById("topbar-container").clientHeight - document.getElementsByClassName("WazeMapFooter")[0].clientHeight); if((mX < bLeft) || (mX > bRight) || (mY < bTop) || (mY > bBottom)) return true; else return false; } function oslMouseOut(e) { if(oslTestPointerOutsideMap(e.clientX, e.clientY)) { // when the mouse pointer leaves the map area, WME treats it similarly to a mouseup // event without generating an actual mouseup event, so we need to do the same... oslMapIsStaticProcessing(false); } } function oslCancelEvent(e) { e = e ? e : window.event; if(e.stopPropagation) e.stopPropagation(); if(e.preventDefault) e.preventDefault(); e.cancelBubble = true; e.cancel = true; e.returnValue = false; return false; } function oslOSLDivMouseDown(e) { oslPrevMouseX = e.pageX; oslPrevMouseY = e.pageY; oslDivDragging = true; oslDragBar.style.cursor = 'move'; document.body.addEventListener('mousemove', oslOSLDivMouseMove, false); document.body.addEventListener('mouseup', oslOSLDivMouseUp, false); // lock the UI width during a drag so we can correctly detect for falling off the window edge oslWindow.style.width = oslWindow.getBoundingClientRect().width+'px'; return true; } function oslOSLDivMouseUp() { if(oslDivDragging) { oslDivDragging = false; oslUserPrefs.ui.x = oslOSLDivLeft; oslUserPrefs.ui.y = oslOSLDivTop; oslWriteUserPrefs(); // unlock the UI width again so we can expand/contract as required based on other script behaviour oslWindow.style.width = "auto"; } oslDragBar.style.cursor = 'auto'; document.body.removeEventListener('mousemove', oslOSLDivMouseMove, false); document.body.removeEventListener('mouseup', oslOSLDivMouseUp, false); return true; } function oslOSLDivMouseMove(e) { var vpHeight = window.innerHeight; var vpWidth = window.innerWidth; oslOSLDivTop = parseInt(oslOSLDivTop) + parseInt((e.pageY - oslPrevMouseY)); oslOSLDivLeft = parseInt(oslOSLDivLeft) + parseInt((e.pageX - oslPrevMouseX)); oslPrevMouseX = e.pageX; oslPrevMouseY = e.pageY; if(oslOSLDivTop < 0) oslOSLDivTop = 0; if(oslOSLDivTop + 16 >= vpHeight) oslOSLDivTop = vpHeight-16; if(oslOSLDivLeft < 0) oslOSLDivLeft = 0; if(oslOSLDivLeft + 32 >= vpWidth) oslOSLDivLeft = vpWidth-32; oslWindow.style.top = oslOSLDivTop+'px'; oslWindow.style.left = oslOSLDivLeft+'px'; return oslCancelEvent(e); } function oslKeepUIVisible() { var vpHeight = window.innerHeight; var vpWidth = window.innerWidth; var topbarHeight = document.getElementById('toolbar').offsetHeight; var maxUIHeight = (vpHeight - topbarHeight); // Restore auto-sizing so we can see the effect of whatever UI change caused us to get here... oslWindow.style.height = "auto"; oslWindow.style.overflow = "hidden"; // If the bottom edge of the ui would fall off the bottom edge of the map viewport, nudge // the UI up as far as required to keep the whole UI visible. If this would however require // the top edge of the UI to be pushed off the top of the map viewport, constrain the UI // height to the viewport height and enable a scrollbar... if(oslWindow.getBoundingClientRect().bottom >= maxUIHeight) { var newTop = (vpHeight-oslWindow.getBoundingClientRect().height); if(newTop < topbarHeight) { newTop = topbarHeight; oslWindow.style.height = maxUIHeight+'px'; oslWindow.style.overflow = "scroll"; } oslOSLDivTop = newTop; oslUserPrefs.ui.y = oslOSLDivTop; oslWindow.style.top = oslOSLDivTop+'px'; } } function oslMinimiseDiv(divID) { var tDiv = document.getElementById(divID); if(tDiv != null) { tDiv.style.height = '0px'; tDiv.style.padding = '0px'; tDiv.style.overflow = 'hidden'; } } function oslMaximiseDiv(divID) { var tDiv = document.getElementById(divID); if(tDiv != null) { tDiv.style.height = 'auto'; tDiv.style.padding = '2px'; tDiv.style.overflow = 'auto'; } } function oslWindowMaximise() { var tHTML = ''; tHTML += '<span style="float:left"><a href="'+oslUpdateURL+'" target="_blank"><b>WMEOpenData</a> v'+oslVersion+'</b></span>'; tHTML += '<span id="_minimax" style="float:right"><i class="fa fa-chevron-circle-up"></i></span>'; tHTML += '<br>'; oslDragBar.innerHTML = tHTML; document.getElementById('_minimax').addEventListener('click', oslWindowMinimise, false); oslMaximiseDiv('oslOSLDiv'); oslMaximiseDiv('oslNCDiv'); oslMaximiseDiv('oslSegGeoUIDiv'); oslMaximiseDiv('oslMLCDiv'); oslKeepUIVisible(); oslUserPrefs.ui.state = 'maximised'; oslWriteUserPrefs(); oslRepositionOverlays(true); oslMapIsStaticProcessing(true); } function oslWindowMinimise() { var tHTML = ''; tHTML += '<span style="float:left"><b>WMEOpenData v'+oslVersion+'</b></span>'; tHTML += '<span id="_minimax" style="float:right"><i class="fa fa-chevron-circle-down"></i></span>'; tHTML += '<br>'; oslDragBar.innerHTML = tHTML; document.getElementById('_minimax').addEventListener('click', oslWindowMaximise, false); oslMinimiseDiv('oslOSLDiv'); oslMinimiseDiv('oslNCDiv'); oslMinimiseDiv('oslSegGeoUIDiv'); oslMinimiseDiv('oslMLCDiv'); oslKeepUIVisible(); oslBBDiv.innerHTML = ''; oslSegGeoDiv.innerHTML = ''; oslUserPrefs.ui.state = 'minimised'; oslWriteUserPrefs(); } function oslSubDivSetState(divID, state) { var tSubDiv = document.getElementById(divID).children[1]; var tToggle = document.getElementById(divID).children[0].children[1].children[0]; if(state == 'minimised') { tSubDiv.style.height = "0px"; tSubDiv.style.padding = "0px"; tSubDiv.style.overflow = "hidden"; tToggle.className = "fa fa-chevron-circle-down"; } else { tSubDiv.style.height = "auto"; tSubDiv.style.width = "100%"; tSubDiv.style.padding = "2px"; tSubDiv.style.overflow = "auto"; tToggle.className = "fa fa-chevron-circle-up"; } } function oslUIMinMax(e) { var headerDivID = e.srcElement.parentElement.parentElement.parentElement.id; var tSubDiv = document.getElementById(headerDivID).children[1]; if(tSubDiv != null) { var newState; if(tSubDiv.style.height == "auto") { newState = 'minimised'; } else { newState = 'maximised'; } oslSubDivSetState(headerDivID, newState); oslUpdateMinMax(headerDivID, newState); } oslKeepUIVisible(); } function oslNestedTypeof(nestedObj) { var objFields = nestedObj.split("."); var retval = "unknown"; var fieldIdx = 0; var level = unsafeWindow; while((retval != "undefined") && (fieldIdx < objFields.length)) { level = level[objFields[fieldIdx++]]; retval = typeof(level); } return retval; } function oslEditPanelCheck() { if(document.getElementById('edit-panel').getElementsByClassName('map-comment-feature-editor').length) { document.body.style.overflow = "auto"; } else { document.body.style.overflow = "hidden"; } } function oslSetupBBDiv() { // add a new div to the map viewport, to hold the bounding box SVG oslAddLog('create bounding box DIV'); oslBBDiv = document.createElement('div'); oslBBDiv.id = "oslBBDiv"; oslBBDiv.style.position = 'absolute'; oslBBDiv.style.top = (0-parseInt(oslWazeMapElement.style.top.replace('px',''))) + 'px'; oslBBDiv.style.left = (0-parseInt(oslWazeMapElement.style.left.replace('px',''))) + 'px'; oslBBDiv.style.overflow = 'hidden'; oslBBDiv.style.width = window.innerWidth; oslBBDiv.style.height = window.innerHeight; oslWazeMapElement.appendChild(oslBBDiv); } function oslSetupORDiv() { // add a new div to the map viewport, to hold the OpenRoads SVG oslAddLog('create OpenRoads DIV'); oslSegGeoDiv = document.createElement('div'); oslSegGeoDiv.id = "oslSegGeoDiv"; oslSegGeoDiv.style.position = 'absolute'; oslSegGeoDiv.style.top = (0-parseInt(oslWazeMapElement.style.top.replace('px',''))) + 'px'; oslSegGeoDiv.style.left = (0-parseInt(oslWazeMapElement.style.left.replace('px',''))) + 'px'; oslSegGeoDiv.style.overflow = 'hidden'; oslSegGeoDiv.style.width = window.innerWidth; oslSegGeoDiv.style.height = window.innerHeight; oslWazeMapElement.appendChild(oslSegGeoDiv); } function oslGenerateOpenRoadsCBHTML(isStd, ID, label, indentLevel) { var tHTML = ''; var indent = 'padding-left: '+(indentLevel * 0.5)+'em;'; tHTML += '<label style="display: inline; '+indent+'">'; tHTML += '<input type="checkbox" name="oslOpenRoads_'; if(isStd == true) tHTML += 'std'; else tHTML += 'adv'; tHTML += '" id="' + ID + '" />'; tHTML += label + '</label>'; return tHTML; } function oslGenerateCollapsibleSubDiv(headerText, subDivHTML) { var tHTML; tHTML = '<div><span style="float:left"><b>'+headerText+'</b></span>'; tHTML += '<span name="oslMinMaxToggle" style="float:right"><i class="fa fa-chevron-circle-down"></i></span></div>'; tHTML += '<div style="height: 0px; padding: 0px; overflow: hidden;">'; tHTML += subDivHTML; tHTML += '</div>'; return tHTML; } function oslSetupUI() { var subDivHTML; // add a new div to hold the OS Locator results, in the form of a draggable window oslAddLog('create lookup results DIV'); oslWindow = document.createElement('div'); oslWindow.id = "oslWindow"; oslWindow.style.position = 'absolute'; oslWindow.style.border = '1px solid #BBDDBB'; oslWindow.style.borderRadius = '4px'; oslWindow.style.overflow = 'hidden'; oslWindow.style.zIndex = 2000; oslWindow.style.opacity = 0; oslWindow.style.transitionProperty = "opacity"; oslWindow.style.transitionDuration = "1000ms"; oslWindow.style.webkitTransitionProperty = "opacity"; oslWindow.style.webkitTransitionDuration = "1000ms"; oslWindow.style.boxShadow = '5px 5px 10px Silver'; document.body.appendChild(oslWindow); // dragbar div oslAddLog('create dragbar DIV'); oslDragBar = document.createElement('div'); oslDragBar.id = "oslDragBar"; oslDragBar.style.backgroundColor = '#D0D0D0'; oslDragBar.style.padding = '4px'; oslDragBar.style.fontSize = '16px'; oslDragBar.style.lineHeight = '18px'; oslWindow.appendChild(oslDragBar); // OS results div oslAddLog('create results DIV'); oslOSLDiv = document.createElement('div'); oslOSLDiv.id = "oslOSLDiv"; oslOSLDiv.style.backgroundColor = '#DDFFDD'; oslOSLDiv.style.padding = '2px'; oslOSLDiv.style.fontSize = '14px'; oslOSLDiv.style.lineHeight = '16px'; oslOSLDiv.style.display = 'none'; subDivHTML = "<div id='oslRoadNameMatches'></div>"; oslOSLDiv.innerHTML = oslGenerateCollapsibleSubDiv("OS Open Names", subDivHTML); oslWindow.appendChild(oslOSLDiv); // Segment geometry control div oslAddLog('create SegGeo control DIV'); oslSegGeoUIDiv = document.createElement('div'); oslSegGeoUIDiv.id = "oslSegGeoUIDiv"; oslSegGeoUIDiv.style.backgroundColor = '#40A040'; oslSegGeoUIDiv.style.padding = '2px'; oslSegGeoUIDiv.style.fontSize = '14px'; oslSegGeoUIDiv.style.lineHeight = '16px'; oslSegGeoUIDiv.style.display = 'none'; subDivHTML = oslGenerateOpenRoadsCBHTML(true, "_cbOpenRoadsEnabled", "Highlight by Classification:", 0) + '<br>'; subDivHTML += oslGenerateOpenRoadsCBHTML(true, "_cbSegGeoMotorway", "Motorway", 1) + '<br>'; subDivHTML += oslGenerateOpenRoadsCBHTML(true, "_cbSegGeoARoad", "A Road", 1) + '<br>'; subDivHTML += oslGenerateOpenRoadsCBHTML(true, "_cbSegGeoBRoad", "B Road", 1) + '<br>'; subDivHTML += oslGenerateOpenRoadsCBHTML(true, "_cbSegGeoMinor", "Minor Road", 1) + '<br>'; subDivHTML += oslGenerateOpenRoadsCBHTML(true, "_cbSegGeoLocal", "Local Road", 1) + '<br>'; if(oslAdvancedMode == true) { subDivHTML += oslGenerateOpenRoadsCBHTML(false, "_cbSegGeoLocalAccess", "Local Access Road", 1) + '<br>'; subDivHTML += oslGenerateOpenRoadsCBHTML(false, "_cbSegGeoRestricted", "Restricted Access Road", 1) + '<br>'; subDivHTML += oslGenerateOpenRoadsCBHTML(false, "_cbSegGeoSecondary", "Secondary Access Road", 1) + '<br>'; } subDivHTML += '<br>' + oslGenerateOpenRoadsCBHTML(true, "_cbOpenRoadsUseGeo", "Show as polylines", 0) + '<br>'; subDivHTML += oslGenerateOpenRoadsCBHTML(true, "_cbOpenRoadsEnhanceGeoVis", "Enhance polyline visibility", 1); oslSegGeoUIDiv.innerHTML = oslGenerateCollapsibleSubDiv("OS Open Roads", subDivHTML); oslWindow.appendChild(oslSegGeoUIDiv); // NameCheck div oslAddLog('create NameCheck DIV'); oslNCDiv = document.createElement('div'); oslNCDiv.id = "oslNCDiv"; oslNCDiv.style.backgroundColor = '#DDDDFF'; oslNCDiv.style.padding = '2px'; oslNCDiv.style.fontSize = '14px'; oslNCDiv.style.lineHeight = '16px'; oslNCDiv.style.display = 'none'; subDivHTML = '<label style="display:inline;"><input type="checkbox" id="_cbNCEnabled" />Highlight potential naming errors</label>'; subDivHTML += '<br><i>Note: only active at at zoom level 4 and above</i>'; oslNCDiv.innerHTML = oslGenerateCollapsibleSubDiv("NameCheck", subDivHTML); oslWindow.appendChild(oslNCDiv); // external links div oslAddLog('create extern links DIV'); oslMLCDiv = document.createElement('div'); oslMLCDiv.id = "oslMLCDiv"; oslMLCDiv.style.backgroundColor = '#EEFFEE'; oslMLCDiv.style.padding = '2px'; oslMLCDiv.style.fontSize = '14px'; oslMLCDiv.style.lineHeight = '16px'; // add the anchors and auto-track checkboxes for external sites. Note that the urls are blank at this stage, // they'll be filled in by oslMouseMoveAndUp()... subDivHTML = '<div id="_extlinksUK" style="display: none;">'; subDivHTML += '<a href="" id="_linkOSOD" target="_osopendata">OS OpenData</a> <input type="checkbox" id="_cbAutoTrackOSOD"></input> | '; subDivHTML += '<a href="" id="_linkRWO" target="_roadworksorg">one.network</a> <input type="checkbox" id="_cbAutoTrackRWO"></input><br>'; subDivHTML += '<div id="swgCtrls"><a href="" id="_linkSWG" target="_wiltshire">Wiltshire</a> <input type="checkbox" id="_cbAutoTrackSWG"></input></div>'; subDivHTML += '<div id="lrrCtrls"><a href="" id="_linkLRR" target="_londonregister">London Roadworks</a> <input type="checkbox" id="_cbAutoTrackLRR"></input></div>'; subDivHTML += '</div>'; subDivHTML += '<br>(Checkboxes enable auto-tracking)'; subDivHTML += '<br><br><a href="" id="_linkPermalink">Permalink</a>'; oslMLCDiv.innerHTML = oslGenerateCollapsibleSubDiv("External resources", subDivHTML); oslWindow.appendChild(oslMLCDiv); } function oslSetupEventListeners() { var idx; oslAddLog('adding event listeners'); oslDragBar.addEventListener('mousedown', oslOSLDivMouseDown, false); oslDragBar.addEventListener('mouseup', oslOSLDivMouseUp, false); W.map.events.register("zoomend", null, oslMouseMoveAndUp); W.map.events.register("mouseout", null, oslMouseOut); document.getElementById('_cbNCEnabled').addEventListener('click', oslNCStateChange, false); for(idx = 0; idx < document.getElementsByName('oslOpenRoads_std').length; ++idx) { document.getElementsByName('oslOpenRoads_std')[idx].addEventListener('click', oslOpenRoadsStateChange, false); } if(oslAdvancedMode == true) { for(idx = 0; idx < document.getElementsByName('oslOpenRoads_adv').length; ++idx) { document.getElementsByName('oslOpenRoads_adv')[idx].addEventListener('click', oslOpenRoadsStateChange, false); } } for(idx = 0; idx < document.getElementsByName('oslMinMaxToggle').length; ++idx) { document.getElementsByName('oslMinMaxToggle')[idx].addEventListener('click', oslUIMinMax, false); } W.map.events.register("mousemove", null, oslMouseMoveAndUp); W.map.events.register("mouseup", null, oslMouseMoveAndUp); W.map.segmentLayer.events.register("featuresadded", null, oslNameCheckTrigger); W.map.segmentLayer.events.register("featuresremoved", null, oslNameCheckTrigger); } function oslSetupUIPosition() { oslAddLog('adjusting UI position...'); document.body.style.overflow = 'hidden'; var vpHeight = window.innerHeight; var vpWidth = window.innerWidth; if ( (oslUserPrefs.ui.y === null)|| (oslUserPrefs.ui.x === null)|| (oslUserPrefs.ui.y > vpHeight)|| (oslUserPrefs.ui.x > vpWidth)|| (oslUserPrefs.ui.y < 0)|| (oslUserPrefs.ui.x < 0) ) { oslOSLDivTop = document.getElementById('sidebar').getBoundingClientRect().top + (document.getElementById('sidebar').getBoundingClientRect().height / 2); oslOSLDivLeft = 8; } else { oslOSLDivTop = oslUserPrefs.ui.y; oslOSLDivLeft = oslUserPrefs.ui.x; } if(oslUserPrefs.ui.state === undefined) oslUserPrefs.ui.state = 'maximised'; oslOSLDivTopMinimised = oslOSLDivTop; oslWindow.style.left = oslOSLDivLeft+'px'; oslWindow.style.top = oslOSLDivTop+'px'; if(oslUserPrefs.ui.state == 'maximised') oslWindowMaximise(); else oslWindowMinimise(); oslWindow.style.opacity = 1; } function oslSetLayerZIndices() { oslAddLog('setting layer zIndices...'); for(var i=0; i < W.map.layers.length; i++) { if(W.map.layers[i].uniqueName == 'satellite_imagery') { oslBBDiv.style.zIndex = parseInt(W.map.layers[i].div.style.zIndex) + 1; oslSegGeoDiv.style.zIndex = parseInt(W.map.layers[i].div.style.zIndex) + 2; } if(W.map.layers[i].name == 'Spotlight') oslOSLMaskLayer = W.map.layers[i].div; } } function oslCheckAccessKey() { var lastAccessKey = GM_getValue('_rwoAccessKey', null); var keyFound = false; if(lastAccessKey !== null) { lastAccessKey = parseInt(lastAccessKey); if((Date.now() - lastAccessKey) <= 10000) { keyFound = true; } } if(keyFound === false) { oslAddLog('No recent access key found, generating one for this tab and setting up message listener'); oslAccessKeyUpdate(); window.setInterval(oslAccessKeyUpdate,5000); GM_addValueChangeListener("_rwoPositionToWME", function() { if(arguments[3] === true) { oslAddLog('WME reposition request from one.network...'); var tPos = new OpenLayers.LonLat(); var posBits = arguments[2].split(','); tPos.lat = parseFloat(posBits[2]); tPos.lon = parseFloat(posBits[3]); tPos.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913")); W.map.setCenter(tPos); var tZoom = parseInt(posBits[4]); if(tZoom < 0) tZoom = 0; if(tZoom > 10) tZoom = 10; W.map.zoomTo(tZoom); } }); } } function oslLoadOrInitPrefs() { // See if this system already has something in localStorage var userPrefs = localStorage.oslUserPrefs; if(userPrefs != undefined) { oslUserPrefs = JSON.parse(userPrefs); } // Fill out any undefined parts of the prefs object with default values - this works both to initialise // the object if nothing at all is stored in localStorage, and can also be used to initialise any newer // parameters that might get added later on which aren't yet defined in the localStorage copy if(oslUserPrefs.minmax == undefined) oslUserPrefs.minmax = []; if(oslUserPrefs.openRoads == undefined) oslUserPrefs.openRoads = []; if(oslUserPrefs.ui == undefined) oslUserPrefs.ui = {}; if(oslUserPrefs.ui.x == undefined) oslUserPrefs.ui.x = null; if(oslUserPrefs.ui.y == undefined) oslUserPrefs.ui.y = null; if(oslUserPrefs.ui.state == undefined) oslUserPrefs.ui.state = null; // Import any older preferences set on this system, then remove from localStorage - this should only ever // occur the first time this version of the script is run after updating an existing setup, so there // wouldn't be anything already stored in these three properties that would get wiped out by the import. if(localStorage.oslOSLDivState != undefined) { oslUserPrefs.ui.state = localStorage.oslOSLDivState; localStorage.removeItem("oslOSLDivState"); } if(localStorage.oslOSLDivLeft != undefined) { oslUserPrefs.ui.x = localStorage.oslOSLDivLeft; localStorage.removeItem("oslOSLDivLeft"); } if(localStorage.oslOSLDivTop != undefined) { oslUserPrefs.ui.y = localStorage.oslOSLDivTop; localStorage.removeItem("oslOSLDivTop"); } } function oslApplyPrefs() { var i; // subDiv states for(i = 0; i < oslUserPrefs.minmax.length; ++i) { oslSubDivSetState(oslUserPrefs.minmax[i][0], oslUserPrefs.minmax[i][1]); } // Open Roads options for(i = 0; i < oslUserPrefs.openRoads.length; ++i) { var cbID = oslUserPrefs.openRoads[i][0]; if(document.getElementById(cbID) != undefined) { document.getElementById(cbID).checked = oslUserPrefs.openRoads[i][1]; } } // Force-disable Open Roads display on startup to avoid problems if the current WME viewport is // showing a more densely mapped area than before... document.getElementById('_cbOpenRoadsEnabled').checked = false; } function oslWriteUserPrefs() { localStorage.oslUserPrefs = JSON.stringify(oslUserPrefs); } function oslUpdateMinMax(key, value) { var found = false; for(var i = 0; i < oslUserPrefs.minmax.length; ++i) { if(oslUserPrefs.minmax[i][0] == key) { oslUserPrefs.minmax[i][1] = value; found = true; break; } } if(found == false) { oslUserPrefs.minmax.push([key, value]); } oslWriteUserPrefs(); } function oslUpdateHighlightCBs(key) { var found = false; var value = document.getElementById(key).checked; for(var i = 0; i < oslUserPrefs.openRoads.length; ++i) { if(oslUserPrefs.openRoads[i][0] == key) { oslUserPrefs.openRoads[i][1] = value; found = true; break; } } if(found == false) { oslUserPrefs.openRoads.push([key, value]); } oslWriteUserPrefs(); } function oslFinaliseSetup() { oslEnableAdvancedOptions(); oslLoadOrInitPrefs(); oslSetupBBDiv(); oslSetupORDiv(); oslSetupUI(); oslSetupEventListeners(); oslSetupUIPosition(); oslSetLayerZIndices(); oslCheckAccessKey(); oslApplyPrefs(); oslOffsetToolbar = document.getElementById('map').contains(document.getElementById('toolbar')); window.setInterval(oslTenthSecondTick,100); oslDoneOnload = true; } function oslWazeBits() { if(document.location.href.indexOf('user') !== -1) { oslAddLog('User profile page detected, script is disabled...'); return; } oslAddLog('adding WazeBits...'+oslWazeBitsPresent); if((oslWazeBitsPresent & 0x01) === 0) { if(oslNestedTypeof("W.selectionManager") != "undefined") { W = unsafeWindow.W; oslAddLog(' W.selectionManager OK'); oslWazeBitsPresent |= 0x01; } } if((oslWazeBitsPresent & 0x02) === 0) { if(typeof(OpenLayers) != "undefined") { oslAddLog(' OpenLayers OK'); oslWazeBitsPresent |= 0x02; } } if((oslWazeBitsPresent & 0x04) === 0) { if(oslNestedTypeof("W.map.segmentLayer.div.parentElement.id") != "undefined") { if(document.getElementById(W.map.segmentLayer.div.parentElement.id) !== null) { oslAddLog(' WazeMap OK'); oslWazeBitsPresent |= 0x04; oslWazeMapElement = document.getElementById(W.map.segmentLayer.div.parentElement.id); } } } if((oslWazeBitsPresent & 0x08) === 0) { if(oslNestedTypeof("W.model.countries") != "undefined") { oslAddLog(' W.model.countries OK'); oslWazeBitsPresent |= 0x08; } } if(oslWazeBitsPresent != 0x0F) { window.setTimeout(oslWazeBits,250); } else { oslFinaliseSetup(); } } function oslAccessKeyUpdate() { GM_setValue('_rwoAccessKey',Date.now()); } function oslInitialise() { oslAddLog('initialise()'); var nameTestMode = false; // oslWazeifyStreetName() functionality test code if(nameTestMode === true) { console.log(oslWazeifyStreetName("North Street", true)); console.log(oslWazeifyStreetName("South Street", true)); console.log(oslWazeifyStreetName("East Street", true)); console.log(oslWazeifyStreetName("West Street", true)); console.log(oslWazeifyStreetName("North Town Street", true)); console.log(oslWazeifyStreetName("South Town Street", true)); console.log(oslWazeifyStreetName("East Town Street", true)); console.log(oslWazeifyStreetName("West Town Street", true)); console.log(oslWazeifyStreetName("Green Street", true)); console.log(oslWazeifyStreetName("The Boulevard", true)); console.log(oslWazeifyStreetName("Aston Boulevard West", true)); console.log(oslWazeifyStreetName("Saint Albans Way", true)); console.log(oslWazeifyStreetName("Orchard On The Green", true)); console.log(oslWazeifyStreetName("The Orchard On The Green", true)); console.log(oslWazeifyStreetName("The Avenue", true)); console.log(oslWazeifyStreetName("High Road Ickenham", true)); console.log(oslWazeifyStreetName("Westway Avenue", true)); console.log(oslWazeifyStreetName("Parkway Park", true)); console.log(oslWazeifyStreetName("Parkway Crescent", true)); console.log(oslWazeifyStreetName("Breakspear Road North", true)); console.log(oslWazeifyStreetName("Breakspear Road South", true)); console.log(oslWazeifyStreetName("Breakspear Road East", true)); console.log(oslWazeifyStreetName("Breakspear Road West", true)); console.log(oslWazeifyStreetName("Kensal Green Way", true)); console.log(oslWazeifyStreetName("Great North Road", true)); return; } // inject gazetteer data var gazscript = document.createElement("script"); gazscript.setAttribute('type','text/javascript'); gazscript.setAttribute('charset','windows-1252'); gazscript.src = oslGazetteerURL; document.head.appendChild(gazscript); oslMergeGazData = true; // initialise persistent vars sessionStorage.zoom = 0; sessionStorage.lat = ''; sessionStorage.lon = ''; sessionStorage.myCity = ''; sessionStorage.prevCity = ''; sessionStorage.cityChangeEastings = 0; sessionStorage.cityChangeNorthings = 0; sessionStorage.cityNameRB = 'optUseExisting'; sessionStorage.oslTabCreated = 0; oslWazeBits(); } // External site helper functions const hlp_ONE = { // one.network helper functions addLog: function(logtext) { console.log('ONE: '+logtext); }, clickToWME: function() { var elginLat = Elgin.map.getCenter().lat(); var elginLon = Elgin.map.getCenter().lng(); var elginZoom = Elgin.map.getZoom() - 12; if(elginZoom < 0) elginZoom = 0; if(elginZoom > 10) elginZoom = 10; // check for an active WME tab... var tabFound = false; var lastAccessKey = GM_getValue('_rwoAccessKey', null); if(lastAccessKey !== null) { lastAccessKey = parseInt(lastAccessKey); if((Date.now() - lastAccessKey) <= 10000) { // the access key was written within the last 10s which implies an active tab, so send it the repositioning data var toWrite = Date.now()+','+lastAccessKey+','+elginLat+','+elginLon+','+elginZoom; GM_setValue('_rwoPositionToWME',toWrite); tabFound = true; } } if(tabFound === false) { // couldn't find a WME tab to reposition, so open a new one... var wmeURL = 'https://www.waze.com/editor?'; wmeURL += 'lon='+elginLon; wmeURL += '&lat='+elginLat; wmeURL += '&zoom='+elginZoom; window.open(wmeURL); } }, init: function() { hlp_ONE.addLog('initialise()'); hlp_ONE.addLog('waiting for map objects...'); var waitSomeMore = false; try { if(Elgin === undefined) { waitSomeMore = true; } else if (Elgin.map === undefined) { waitSomeMore = true; } if(google === undefined) { waitSomeMore = true; } else if(google.maps === undefined) { waitSomeMore = true; } } catch { waitSomeMore = true; } if(document.getElementById('map-canvas') === null) { waitSomeMore = true; } if(document.getElementsByClassName('gm-bundled-control-on-bottom').length == 0) { waitSomeMore = true; } if(waitSomeMore) { window.setTimeout(hlp_ONE.init,500); return; } hlp_ONE.addLog('all required objects found...'); // Add "open in WME" button... var tBtnDiv = document.createElement('div'); tBtnDiv.id = 'rwoWMELink'; var tHTML = '<div class="gmnoprint" draggable="false" controlwidth="40" controlheight="40" style="margin: 10px; user-select: none; position: absolute; bottom: 220px; right: 40px;">'; tHTML += '<div class="gmnoprint" controlwidth="40" controlheight="40" style="position: absolute; left: 0px; top: 0px;">'; tHTML += '<div draggable="false" style="user-select: none; box-shadow: rgba(0, 0, 0, 0.3) 0px 1px 4px -1px; border-radius: 2px; cursor: pointer; background-color: rgb(255, 255, 128); width: 40px; height: 40px;">'; tHTML += '<button draggable="false" title="Open in WME" aria-label="Open in WME" type="button" class="gm-control-active" style="background: none; display: block; border: 0px; margin: 0px; padding: 0px; position: relative; cursor: pointer; user-select: none; overflow: hidden; width: 40px; height: 40px; top: 0px; left: 0px;"><strong>WME</strong></button>'; tHTML += '</div></div></div>'; tBtnDiv.innerHTML = tHTML; document.getElementById('map-canvas').firstChild.appendChild(tBtnDiv); document.getElementById('rwoWMELink').addEventListener('click', hlp_ONE.clickToWME, false); // extract the coords/zoom from the url... var userloc = document.location.href; var latpos = userloc.indexOf("?lat="); var lonpos = userloc.indexOf("&lon="); var zpos = userloc.indexOf("&z="); if((latpos != -1)&&(lonpos != -1)&&(zpos != -1)) { var rwoLat = parseFloat(userloc.substr(latpos+5,lonpos-(latpos+5))); var rwoLon = parseFloat(userloc.substr(lonpos+5,zpos-(lonpos+5))); var rwoZoom = parseInt(userloc.substr(zpos+3,2))+12; Elgin.map.setCenter(new google.maps.LatLng(rwoLat,rwoLon)); Elgin.map.setZoom(rwoZoom); hlp_ONE.addLog('map repositioned'); } } }; const hlp_WSW = { // Wiltshire Streetworks helper functions addLog: function(logtext) { console.log('WSW: '+logtext); }, init: function() { hlp_WSW.addLog('initialise()'); hlp_WSW.addLog('waiting for map objects...'); var waitSomeMore = false; if((map === null) || (map === undefined)) { waitSomeMore = true; hlp_WSW.addLog('map not found...'); } else { if(map.setCenter === undefined) { waitSomeMore = true; hlp_WSW.addLog('map.setCenter not found...'); } if(map.zoomTo === undefined) { waitSomeMore = true; hlp_WSW.addLog('map.zoomTo not found...'); } } if((OpenLayers === null) || (OpenLayers === undefined)) { waitSomeMore = true; hlp_WSW.addLog('OpenLayers not found...'); } else { if(OpenLayers.LonLat === undefined) { waitSomeMore = true; hlp_WSW.addLog('OpenLayers.LonLat not found...'); } } if(waitSomeMore) { window.setTimeout(hlp_WSW.init,500); return; } hlp_WSW.addLog('all required objects found...'); // extract the coords/zoom from the url... var userloc = document.location.href; var latpos = userloc.indexOf("?lat="); var lonpos = userloc.indexOf("&lon="); var zpos = userloc.indexOf("&z="); if((latpos != -1)&&(lonpos != -1)&&(zpos != -1)) { var swgLat = parseFloat(userloc.substr(latpos+5,lonpos-(latpos+5))); var swgLon = parseFloat(userloc.substr(lonpos+5,zpos-(lonpos+5))); var swgZoom = parseInt(userloc.substr(zpos+3,2)); map.setCenter(new OpenLayers.LonLat(swgLon,swgLat)); map.zoomTo(swgZoom); hlp_WSW.addLog('map repositioned'); } } }; const hlp_LRR = { // London Roadworks Register helper functions addLog: function(logtext) { console.log('LRR: '+logtext); }, init: function() { // trap the page reload that occurs when the map view is generated... if(document.location.href.indexOf('home') == -1) { hlp_LRR.addLog('page reloaded during map generation - redirecting to second stage initialisation...'); hlp_LRR.initPartDeux(); return; } hlp_LRR.addLog('initialise()'); hlp_LRR.addLog('waiting for search page to load...'); var waitSomeMore = false; if(document.getElementsByName('mapResults')[0].length < 1) { waitSomeMore = true; } if(document.getElementsByName('postCode')[0].length < 1) { waitSomeMore = true; } if(waitSomeMore === true) { window.setTimeout(hlp_LRR.init,500); return; } // extract the coords/zoom from the url... var userloc = document.location.href; var epos = userloc.indexOf("?e="); var npos = userloc.indexOf("&n="); var zpos = userloc.indexOf("&z="); if((epos != -1)&&(npos != -1)&&(zpos != -1)) { var lrrLon = userloc.substr(epos+3,npos-(epos+3)); var lrrLat = userloc.substr(npos+3,zpos-(npos+3)); var lrrZoom = userloc.substr(zpos+3,2); sessionStorage.setItem('lrrLon',lrrLon); sessionStorage.setItem('lrrLat',lrrLat); sessionStorage.setItem('lrrZoom',lrrZoom); hlp_LRR.addLog('accessing map...'); // first set a "safe" postcode as the search criteria - whilst asking for the map view to be generated without any // search terms usually works OK, from time to time the site throws a wobbler and refuses to do anything without // having the search narrowed down a bit... document.getElementsByName('postCode')[0].value="EC1A 1AA"; document.getElementsByName('mapResults')[0].click(); } }, initPartDeux: function() { hlp_LRR.addLog('waiting for map objects...'); var waitSomeMore = false; if(map === undefined) { waitSomeMore = true; } if(OpenLayers === undefined) { waitSomeMore = true; } if(waitSomeMore) { window.setTimeout(hlp_LRR.initPartDeux,500); return; } hlp_LRR.addLog('all required objects found...'); var lrrLon = parseInt(sessionStorage.getItem('lrrLon')); var lrrLat = parseInt(sessionStorage.getItem('lrrLat')); var lrrZoom = parseInt(sessionStorage.getItem('lrrZoom')); map.setCenter(new OpenLayers.LonLat(lrrLon,lrrLat)); map.zoomTo(lrrZoom); hlp_LRR.addLog('map repositioned'); } }; const hlp_ODM = { // OS OpenData map helper functions eastings: 0, northings: 0, zoom: 0, addLog: function(logtext) { console.log('ODM: '+logtext); }, resizeMap: function() { hlp_ODM.addLog('resize'); // resizes map viewport whenever browser window changes size var newWidth = window.innerWidth - 10; var newHeight = window.innerHeight - 10; hlp_ODM.addLog(' '+newWidth+' x '+newHeight); osMap.size.w = newWidth; osMap.size.h = newHeight; var elm = document.getElementById("map"); // first we need to move the map DIV out of its original placement heirarchy, so that // it can flow to the left of the browser window rather than to the left of its // parent block... document.children[0].appendChild(elm); // then we resize it to fill the available space elm.style.height = newHeight+'px'; elm.style.width = newWidth+'px'; elm.style.left = "4px"; // force a redraw of the map object to use the resized viewport correctly osMap.render('map'); }, recentreMap: function() { // call the OS provided functions required to point the map at a // given grid ref and zoom level var mymapCenter = new OpenSpace.MapPoint(this.eastings, this.northings); osMap.setCenter(mymapCenter, this.zoom); }, hideThing: function(thing) { if((thing === null)||(thing === undefined)) { hlp_ODM.addLog(' not found'); } else { thing.style.visibility = "hidden"; thing.style.position = "absolute"; thing.style.top = "0px"; hlp_ODM.addLog(' hidden'); } }, hideElement: function(elmID) { hlp_ODM.addLog('hiding element '+elmID); var elm = document.getElementById(elmID); hlp_ODM.hideThing(elm); }, hideTagName: function(elmID) { hlp_ODM.addLog('hiding tag '+elmID); var elm = document.getElementsByTagName(elmID)[0]; hlp_ODM.hideThing(elm); }, fakeOnload: function() { // remove the non-map stuff from the page... hlp_ODM.hideElement("openspace.mapbuilder.header"); hlp_ODM.hideElement("col2"); hlp_ODM.hideTagName("h1"); hlp_ODM.hideElement("div1"); // reduce the width of the whitespace around the map viewport document.getElementById("wrapper").style.padding = '4px'; // resize the map viewport... hlp_ODM.resizeMap(); window.addEventListener('resize', hlp_ODM.resizeMap, true); // extract the starting coords/zoom from the url... var userloc = document.location.href; var epos = userloc.indexOf("?e="); var npos = userloc.indexOf("&n="); var zpos = userloc.indexOf("&z="); if((epos != -1)&&(npos != -1)&&(zpos != -1)) { this.eastings = userloc.substr(epos+3,npos-(epos+3)); this.northings = userloc.substr(npos+3,zpos-(npos+3)); this.zoom = userloc.substr(zpos+3,2); //...then recentre the map hlp_ODM.recentreMap(); } }, init: function() { hlp_ODM.addLog('initialise()'); if(osMap === undefined) window.setTimeout(hlp_ODM.init,500); else hlp_ODM.fakeOnload(); } }; oslBootstrap();