WME Keep My Layers

Automatically detects when you've clicked on a layer-infected PL and resets layers in WME to previously saved state.

当前为 2015-12-29 提交的版本,查看 最新版本

// ==UserScript==
// @name 			WME Keep My Layers
// @description 	Automatically detects when you've clicked on a layer-infected PL and resets layers in WME to previously saved state.
// @namespace       https://greasyfork.org/users/11629-TheLastTaterTot
// @version 		0.1.1
// @grant           none
// @match           https://editor-beta.waze.com/*editor/*
// @match           https://www.waze.com/*editor/*
// @author			TheLastTaterTot
// ==/UserScript==
(function() {
	// -----------------------------------------------------------------------------
	//Waze.map.layers.forEach(function(a){console.debug(a["name"] + ': ' + a["visibility"])})
	function GetWazeMapLayersFromSwitcher(L) { // get OL layers that show up under the WME Layer switcher panel
		var l, numTotalLayers = L.length,
			layerName, layerUniqName,
			layerSwitcherPanel = {
				accelerator: {},
				uniqueName: {}
			};

		for (l = numTotalLayers; l--;) {
			layerName = L[l].accelerator;
			layerUniqName = L[l].uniqueName;
			if (layerName !== undefined) { // we check the accelerator name bc it is a marker with high specificity and selectivity of whether the layer appears in the layer switcher menu
				if (layerUniqName !== undefined) { // however, we actually want the uniqueName since that matches the name saved in localStorage by WME
					//L[layerName] = Waze.map.layers[l].name;  //not sure if I want this, so saving it here just in case...
					layerSwitcherPanel.uniqueName[layerUniqName] = l; //name the property by its uniqueName and save its index for Waze.map.layers
					layerSwitcherPanel.accelerator[layerName] = l;
				} else {
					console.log('WMEKML: No uniqueName found for "' + L[l].name + '"');
					console.log('WMEKML: Relying on accelerator id, "' + layerName + '"');
					layerSwitcherPanel.accelerator[layerName] = l;
				}
			}
		}
		return layerSwitcherPanel
	}
	// -----------------------------------------------------------------------------

	function ResetLayersToSaved() { // TODO: Add option of restoring add'l layers
		// not saved by WME in localStorage.
		// Fix saved WME layers settings in localStorage
		var L = Waze.map.layers,
			j, layerNames, numLayers, lname,
			layerSwitcherPanel = GetWazeMapLayersFromSwitcher(L),
			uniqueNames = layerSwitcherPanel.uniqueName,
			visibilityFromWazeLocalStorage;

		visibilityFromWazeLocalStorage = JSON.parse(localStorage.layerVisibility); // TODO: maybe add a check for this... tho it's probably unlikely for it to not exist...
		$.extend(true, visibilityFromWazeLocalStorage, KML_myLayers.visibilityFromWazeLocalStorage);
		// Save it
		localStorage.layerVisibility = JSON.stringify(visibilityFromWazeLocalStorage);

		// Now fix layer visibility on the map
		layerNames = Object.keys(visibilityFromWazeLocalStorage);
		numLayers = layerNames.length;

		for (j = numLayers; j--;) {
			lname = layerNames[j];
			// Check that this layer exists in WME...
			/*  [Note]: Checking from the layerSwitcherPanel object bc that one
				as just built, whereas visibilityFromWazeLocalStorage is mixed
				with settings saved by WMEKML... which potentially could be
				outdated. TODO: check if WME will automatically update the
				localStorage to remove layer visibility settings that are no
				longer relevant to WME. If this ends up being true, this may
				also mean it is unnecessary to update the object and save it
				back into localStorage... TBD... */
			if (uniqueNames[lname] !== undefined) {
				L[uniqueNames[lname]].setVisibility(visibilityFromWazeLocalStorage[lname]);
			} // TODO: might want to consider removing layers from localStorage
			// or maybe alerting the editor to suggest resaving their layer
			// presets in WMEKML....
		}
	}

	// -------------------------------------------------------------------------
	/* The following block of code currently has not been implemented.
		It will eventually be used to temporarily prevent disabling of those
		layers for the duration of the _session_	*/

	// "satellite_imagery", "cities", "roads", "gps_points", "area_managers", "landmarks",
	// "place_updates", "big_junctions", "speed_cameras", "problems", "update_requests",
	// "editable_areas", "closures", "live_users", "junctions"
	function CheckForNeededLayers() {
		switch (true) {
			case permalink.search(/&mapUpdateRequest/) > 0:
				return "update_requests"
			case permalink.search(/&venues/) > 0:
				return "landmarks"
			case permalink.search(/&mapProblem/) > 0:
				return "problems"
			default:
				return false
		}
	}
	// -------------------------------------------------------------------------
	// TODO: Remove KML_myLayers from global later
	// TODO: function for temporarily reverting to the layers provided by PL
	// TODO: Settings panel for WMEKML that will allow disabling of auto-layers in PL detection
	// TODO: Manual trigger of layer reset
	// -------------------------------------------------------------------------
	function SaveMyVisibleLayers() {
		//KML_myLayers = {};

		var L = Waze.map.layers,
			j, lname,
			layerSwitcherPanel = GetWazeMapLayersFromSwitcher(L),
			layerNames = Object.keys(layerSwitcherPanel.accelerator),
			numLayers = layerNames.length,
			visibleLayersInSwitcherPanel = [],
			visibleLayersSavedByWaze = [],
			visibilityFromWazeLocalStorage;


		// Get names of visible menu layers
		for (j = numLayers; j--;) {
			lname = layerNames[j];
			if (L[layerSwitcherPanel.accelerator[lname]].getVisibility()) {
				visibleLayersInSwitcherPanel.push(lname);
			}
		}

		// Get names of visible layers saved by WME in localStorage
		visibilityFromWazeLocalStorage = JSON.parse(localStorage.layerVisibility);
		layerNames = Object.keys(visibilityFromWazeLocalStorage);
		numLayers = layerNames.length;

		for (j = numLayers; j--;) {
			lname = layerNames[j];
			if (visibilityFromWazeLocalStorage[lname]) {
				visibleLayersSavedByWaze.push(lname);
			}
		}

		// Save to localStorage
		KML_myLayers = {
			visibleLayersInSwitcherPanel: visibleLayersInSwitcherPanel,
			visibleLayersSavedByWaze: visibleLayersSavedByWaze,
			visibilityFromWazeLocalStorage: visibilityFromWazeLocalStorage
		};

		localStorage.WME_KeepMyLayers = JSON.stringify(KML_myLayers);
	}
	/*
	function KMLSettingsPanel() {

		// get dimensions of waze map area
		wazeMapHeight = $("#WazeMap").height();
		wazeMapWidth = $("#WazeMap").width();

		// Expect height of LR panel to be (numLayers*18px)+200px top and bottom
		minHeight = 400; //px

		lineHeight = 18; //px
		headerHeight = 100; //px
		footerHeight = 100; //px
		listHeight = lineHeight*numLayers;
		panelHeight = listHeight + footerHeight + headerHeight;
		panelHalfHeight = parseInt(panelHeight/2);
		panelWidth = 500;
		panelHalfWidth = parseInt(panelWidth/2);

		panelTop = parseInt(wazeMapHeight/2)-panelHalfHeight;
		panelLeft = parseInt(wazeMapWidth/2)-panelHalfWidth;

		layerResetPanelCSS =
			'.kml-panel { position: fixed; top: ' + panelTop + '; left: ' + panelLeft +
				'; width: ' + panelWidth + '; height: ' + panelHeight + '; ' +
				'overflow-y: auto; overflow-x: hidden;' +
				'background-color: white; border: 0; border-radius: 10px; box-shadow: 0px 5px 10px #000000; }'

		// setup checkbox list for UI
		for (l = 0; l < numLayers; l++) {
			layersListUI += '<input type="checkbox" id="cbLR_"' + l + '>' +
							layerNames[l] + '<br>';
		}
	}
	*/
	// -----------------------------------------------------------------------------

	function LookForSavedLayerSettings() {
		switch (true) {
			case typeof KML_myLayers !== "undefined":
				console.debug('WMEKML: Found KML_myLayers already declared.')
				break;
				return true
			case localStorage.WME_KeepMyLayers !== undefined:
				console.debug('WMEKML: Found saved settings to load!')
				KML_myLayers = JSON.parse(localStorage.WME_KeepMyLayers);
				return true
			default:
				/* TODO: Call to popup of instructions for saving default layers set will maybe go here */
				return false
		}
	}

	function UserResetOfLayersToSaved() {}


	function AutoDetectLayersInPermalink() {
		permalink = location.href;
		if (permalink.search(/&layers=/) > 0) {
			if (LookForSavedLayerSettings()) {
				ResetLayersToSaved(CheckForNeededLayers());
			}
		}
	}

	function InitKMLButtons() {
		// CSS for WMEKML
		saveIconCSS =
			'i.kml-icn { position: relative; display: inline-block; padding-left: 3px;; padding-right: 3px; }' + //right: 30px; top: 10px; 'width: 12px; height: 12px;
			'div.kml-icn { position: absolute; display: inline-block;  bottom: 10px; right: 0px; padding: 0; margin: 0px 10px 0px 0px; }' +
			'.kml-icn:active, .kml-icn:focus, .kml-icn:hover, .kml-icn.active { text-decoration: none; background-image: none; outline: 0; -webkit-box-shadow: none; box-shadow: none; }';

		var kmlCSS = document.createElement("style");
		kmlCSS.type = "text/css";
		kmlCSS.innerHTML = saveIconCSS;
		document.body.appendChild(kmlCSS);

		// Add save layers icon to Layers switcher dropdown panel
		$("#layer-switcher-list").after('<div class="kml-icn">' +
			'<a id="aKMLsettings" href="javascript:void(0)" class="kml-icn"><i id="iKMLsettings" class="icon-fixed-width icon-cogs reload-button"></i></a>' +
			'<a id="aKMLsaveLayers" href="javascript:void(0)" class="kml-icn"><i id="iKMLsaveLayers" class="icon-fixed-width icon-save reload-button"></i></a>' +
			'</div>');


		// Setup event listeners
		$("a#aKMLsaveLayers").click(SaveMyVisibleLayers);

	}

	// =============================================================================
	var initCount = 0;

	function Init_WMEKML() {
		if (initCount < 20) {
			initCount++;
			try {
				if ("undefined" !== typeof Waze && Waze.map && Waze.map.layers) {
					console.debug('WMEKML: WME Keep My Layers is initializing...')
					AutoDetectLayersInPermalink();
					InitKMLButtons();
				} else {
					setTimeout(Init_WMEKML, 500);
				}
			} catch (err) {
				console.warn(
					'WMEKML: Initialization of WME Keep My Layers has been unsuccessful. Trying again... ' +
					err);
				setTimeout(Init_WMEKML, 3000);
			}
		} else {
			console.error(
				'WMEKML: WME Keep My Layers failed to load. :( Giving up.');
		}
	}

	function Bootstrap_WMEKML() {
		var bGreasemonkeyServiceDefined = false;

		try {
			bGreasemonkeyServiceDefined = ("object" === typeof Components.interfaces.gmIGreasemonkeyService)
		} catch (err) { /* Ignore */ }

		if ("undefined" === typeof unsafeWindow || !bGreasemonkeyServiceDefined) {
			unsafeWindow = (function() {
				var dummyElem = document.createElement('p');
				dummyElem.setAttribute('onclick', 'return window;');
				return dummyElem.onclick();
			})();
		}
		setTimeout(Init_WMEKML, 500);
	}

	Bootstrap_WMEKML();
})();