- // ==UserScript==
- // @name WME SC Emergency Management Closures
- // @namespace https://greatest.deepsurf.us/users/45389
- // @version 0.5
- // @description Adds a road closure layer for Sourth Carolina Emergency Management
- // @author MapOMatic
- // @include /^https:\/\/(www|beta)\.waze\.com\/(?!user\/)(.{2,6}\/)?editor\/?.*$/
- // @license GNU GPLv3
- // @grant GM_xmlhttpRequest
- // @connect arcgis.com
- // ==/UserScript==
-
- (function() {
- 'use strict';
-
- var _settingsStoreName = 'wme_sc_emergency_management_closures';
- var _alertUpdate = false;
- var _debugLevel = 0;
- var _scriptVersion = GM_info.script.version;
- var _scriptVersionChanges = [
- GM_info.script.name + '\nv' + _scriptVersion + '\n\nWhat\'s New\n------------------------------\n',
- '\n- .',
- ].join('');
- var _tabDiv = {}; // stores the user tab div so it can be restored after switching back from Events mode to Default mode
- var _mapLayer = null;
- var _styles = {};
- var _settings = {};
- var _statesHash = {
- 'Alabama': 'AL',
- 'Alaska': 'AK',
- 'American Samoa': 'AS',
- 'Arizona': 'AZ',
- 'Arkansas': 'AR',
- 'California': 'CA',
- 'Colorado': 'CO',
- 'Connecticut': 'CT',
- 'Delaware': 'DE',
- 'District Of Columbia': 'DC',
- 'Federated States Of Micronesia': 'FM',
- 'Florida': 'FL',
- 'Georgia': 'GA',
- 'Guam': 'GU',
- 'Hawaii': 'HI',
- 'Idaho': 'ID',
- 'Illinois': 'IL',
- 'Indiana': 'IN',
- 'Iowa': 'IA',
- 'Kansas': 'KS',
- 'Kentucky': 'KY',
- 'Louisiana': 'LA',
- 'Maine': 'ME',
- 'Marshall Islands': 'MH',
- 'Maryland': 'MD',
- 'Massachusetts': 'MA',
- 'Michigan': 'MI',
- 'Minnesota': 'MN',
- 'Mississippi': 'MS',
- 'Missouri': 'MO',
- 'Montana': 'MT',
- 'Nebraska': 'NE',
- 'Nevada': 'NV',
- 'New Hampshire': 'NH',
- 'New Jersey': 'NJ',
- 'New Mexico': 'NM',
- 'New York': 'NY',
- 'North Carolina': 'NC',
- 'North Dakota': 'ND',
- 'Northern Mariana Islands': 'MP',
- 'Ohio': 'OH',
- 'Oklahoma': 'OK',
- 'Oregon': 'OR',
- 'Palau': 'PW',
- 'Pennsylvania': 'PA',
- 'Puerto Rico': 'PR',
- 'Rhode Island': 'RI',
- 'South Carolina': 'SC',
- 'South Dakota': 'SD',
- 'Tennessee': 'TN',
- 'Texas': 'TX',
- 'Utah': 'UT',
- 'Vermont': 'VT',
- 'Virgin Islands': 'VI',
- 'Virginia': 'VA',
- 'Washington': 'WA',
- 'West Virginia': 'WV',
- 'Wisconsin': 'WI',
- 'Wyoming': 'WY'
- };
- var _stateSettings = {
- SC: {
- baseUrl: '',
- mapLayers: [
- { layerID:'https://services1.arcgis.com/VaY7cY9pvUYUP1Lf/ArcGIS/rest/services/CLOSURES_06_OCT_LINES/FeatureServer/0', outFields:[''] },
- { layerID:'https://services1.arcgis.com/VaY7cY9pvUYUP1Lf/arcgis/rest/services/Hurricane_Matthew_Closures_Lines/FeatureServer/0', outFields:[''] },
- ],
- colors: {closure:'#ff0000'}
- }
- };
-
- function log(message, level) {
- if (message && level <= _debugLevel) {
- console.log('WME SCEM: ' + message);
- }
- }
-
- function loadSettingsFromStorage() {
- var settings = $.parseJSON(localStorage.getItem(_settingsStoreName));
- if(!settings) {
- settings = {
- lastVersion:null,
- layerVisible:true
- };
- } else {
- settings.layerVisible = true; //(settings.layerVisible === true);
- }
- _settings = settings;
- }
-
- function saveSettingsToStorage() {
- if (localStorage) {
- var settings = {
- lastVersion: _scriptVersion,
- layerVisible: _mapLayer.visibility,
- };
- localStorage.setItem(_settingsStoreName, JSON.stringify(settings));
- log('Settings saved', 1);
- }
- }
-
- function getLineWidth() {
- return 8 * Math.pow(1.15, (W.map.getZoom()-1));
- }
-
- function draw(buckets) {
- _mapLayer.removeAllFeatures();
- for(var i=buckets.length-1; i>-1; i--) {
- _mapLayer.addFeatures(buckets[i]);
- }
- }
-
- function processFeatures(data,context) {
- var layer = context.layer;
- var stateSettings = context.stateSettings;
- var styles = {};
- for (var prefix in stateSettings.colors) {
- var color = stateSettings.colors[prefix];
- styles[prefix] = {
- strokeColor: color,
- strokeDashstyle: "solid",
- strokeOpacity: 0.6,
- strokeWidth: getLineWidth()
- };
- }
-
- data.features.forEach(function(feature) {
- var style = styles.closure;
- var lineFeatures = [];
- feature.geometry.paths.forEach(function(path){
- var pointList = [];
- var newPoint = null;
- path.forEach(function(point){
- pointList.push(new OpenLayers.Geometry.Point(point[0],point[1]));
- });
- context.buckets[0].push( new OpenLayers.Feature.Vector(
- new OpenLayers.Geometry.LineString(pointList),null,style
- ));
- });
- });
-
- context.callCount.count -= 1;
- if (context.callCount.count === 0) {
- //console.log(context.buckets);
- draw(context.buckets);
- }
- if (data.exceededTransferLimit) {
- log('Exceeded server\'s feature transfer limit. Some features may not be drawn.',0);
- }
- }
-
- function fetchFeatures() {
- var visibleStates = [];
- //debugger;
- console.log(W.model.states.additionalInfo);
- W.model.states.additionalInfo.forEach(function(state) {
- visibleStates.push(_statesHash[state.name]);
- });
-
- var zoom = W.map.getZoom();
- var ext = W.map.getExtent();
-
- var geometry = {
- xmin: ext.left,
- ymin: ext.bottom,
- xmax: ext.right,
- ymax: ext.top
- };
-
- var geometryStr = JSON.stringify(geometry).replaceAll('{','%7B').replaceAll('}','%7D').replaceAll('"','%22').replaceAll(':','%3A').replaceAll(',','%2C');
- var callCount = 0;
- var buckets = [];
- var urls = [];
- var contexts = [];
-
- visibleStates.forEach(function(stateAbbr) {
- var state = _stateSettings[stateAbbr];
- if (state) {
- for(var i=0; i<7; i++) {buckets.push([]);}
- state.mapLayers.forEach(function(layer) {
- if (!layer.zoomLevels || layer.zoomLevels.indexOf(zoom) !== -1) {
- var context = {
- stateSettings: state,
- layer: layer,
- buckets: buckets
- };
- var url = state.baseUrl + layer.layerID + '/query?';
- url += 'geometry=' + geometryStr;
- url += '&outFields=' + layer.outFields.join('%2C');
- url += '&returnGeometry=true&spatialRel=esriSpatialRelIntersects&geometryType=esriGeometryEnvelope&inSR=102100&outSR=3857&f=json';
- urls.push(url);
- console.log(url);
- contexts.push(context);
- callCount += 1;
-
- }
- });
- }
- });
- var countObj = {count: callCount};
- for (var j=0; j<urls.length; j++) {
- contexts[j].callCount = countObj;
- console.log(urls[j]);
- GM_xmlhttpRequest({
- context: contexts[j],
- method: "GET",
- url: urls[j],
- onload: function(res) {
- processFeatures($.parseJSON(res.responseText), res.context);
- }
- });
- }
- }
-
- function onLayerVisibilityChanged(evt) {
- saveSettingsToStorage();
- }
-
- function restoreUserTab() {
- // $('#user-tabs > .nav-tabs').append(_tabDiv.tab);
- // $('#user-info > .flex-parent > .tab-content').append(_tabDiv.panel);
- // $('#fcl-state-select').change(function () {
- // _settings.activeStateAbbr = this.value;
- // saveSettingsToStorage();
- // fetchFeatures();
- // });
- }
-
- function onModeChanged(model, modeId, context) {
- if(!modeId || modeId === 1) {
- restoreUserTab();
- }
- }
-
- function showScriptInfoAlert() {
- /* Check version and alert on update */
- if (_alertUpdate && _scriptVersion !== _settings.lastVersion) {
- alert(_scriptVersionChanges);
- }
- }
-
- function initLayer(){
- var mapLayerZIndex = 334;
- _mapLayer = new OpenLayers.Layer.Vector("SC Emergency Closures ", {
- uniqueName: "__SCECRoadsLayer",
- displayInLayerSwitcher: false
- });
- I18n.translations[W.location.locale].layers.name.__FCLayer = "SC Emergency Closures";
- W.map.addLayer(_mapLayer);
- _mapLayer.setZIndex(mapLayerZIndex);
-
- _mapLayer.displayInLayerSwitcher = true;
- _mapLayer.events.register('visibilitychanged',null,onLayerVisibilityChanged);
- _mapLayer.setVisibility(_settings.layerVisible);
- // Hack to fix layer zIndex. Some other code is changing it sometimes but I have not been able to figure out why.
- // It may be that the FC layer is added to the map before some Waze code loads the base layers and forces other layers higher.
- var checkLayerZIndex = function(layerZIndex) {
- if (_mapLayer.getZIndex() != mapLayerZIndex) {
- //log("ADJUSTED LAYER Z-INDEX",1);
- _mapLayer.setZIndex(mapLayerZIndex);
- }
- };
-
- setInterval(function(){checkLayerZIndex(mapLayerZIndex);}, 200);
-
- W.map.events.register("moveend",W.map,function(e){
- fetchFeatures();
- return true;
- },true);
-
- // for(var i=0; i<_activeState.defaultColors.length; i++) {
- // var color = _activeState.defaultColors[i];
- // var fc = i + 1;
- // _styles[fc] = {
- // strokeColor: color,
- // strokeDashstyle: "solid",
- // strokeOpacity: 0.5,
- // strokeWidth: getLineWidth()
- // };
- // }
- }
-
- function initUserPanel() {
- // _tabDiv.tab = $('<li>').append(
- // $('<a>', {'data-toggle':'tab', href:'#sidepanel-fc-layer'}).text('FC Layer')
- // );
-
- // _tabDiv.panel = $('<div>', {class:'tab-pane', id:'sidepanel-fc-layer'});/*.append(
- // $('<div>', {class:'side-panel-section>'}).append(
- // $('<div>', {class:'form-group'}).append(
- // $('<label>', {class:'control-label'}).text('Select a state')
- // ).append(
- // $('<div>', {class:'controls', id:'fcl-state-select-container'}).append(
- // $('<div>').append(
- // $('<select>', {id:'fcl-state-select',class:'form-control disabled',style:'disabled'})
- // .append($('<option>', {value:'IN'}).text('Indiana'))
- // //.append($('<option>', {value:'KY'}).text('Kentucky'))
- // .append($('<option>', {value:'MD'}).text('Maryland'))
- // .append($('<option>', {value:'MI'}).text('Michigan'))
- // .append($('<option>', {value:'NC'}).text('North Carolina'))
- // .append($('<option>', {value:'VA'}).text('Virginia'))
- // .val(_settings.activeStateAbbr)
- // // ).append(
- // // $('<div>',{class:'controls-container'})
- // // .append($('<input>', {type:'checkbox',class:'csSettingsCheckBox',name:'csDirectionButtonsCheckBox',id:'csDirectionButtonsCheckBox'}))
- // // .append($('<label>', {for:'csDirectionButtonsCheckBox'}).text('Add road direction buttons'))
- // // ).append(
- // // $('<input class="jscolor" value="ab2567">').change(function(evt) {console.log(evt);})
- // )
- // )
- // )
- // )
- // );*/
-
- // restoreUserTab();
- }
-
- function initGui() {
- initLayer();
- initUserPanel();
- showScriptInfoAlert();
- }
-
- function init() {
- loadSettingsFromStorage();
- String.prototype.replaceAll = function(search, replacement) {
- var target = this;
- return target.replace(new RegExp(search, 'g'), replacement);
- };
- //_activeState = _stateSettings[_settings.activeStateAbbr];
- initGui();
- unsafeWindow.addEventListener('beforeunload', function saveOnClose() { saveSettingsToStorage(); }, false);
- Waze.app.modeController.model.bind('change:mode', onModeChanged);
- fetchFeatures();
- log('Initialized.', 0);
- }
-
- function bootstrap() {
- if (W && W.loginManager &&
- W.loginManager.events.register && W.model && W.model.states && W.model.states.additionalInfo &&
- W.map && W.loginManager.isLoggedIn()) {
- log('Initializing...', 0);
- init();
- } else {
- log('Bootstrap failed. Trying again...', 0);
- setTimeout(function () {
- bootstrap();
- }, 1000);
- }
- }
-
- log('Bootstrap...', 0);
- bootstrap();
- })();