wLib

A WME developers library

Tính đến 11-05-2015. Xem phiên bản mới nhất.

Script này sẽ không được không được cài đặt trực tiếp. Nó là một thư viện cho các script khác để bao gồm các chỉ thị meta // @require https://update.greatest.deepsurf.us/scripts/9794/51374/wLib.js

// ==UserScript==
// @name            wLib
// @description     A WME developers library
// @version         0.1
// @author          SAR85
// @copyright       SAR85
// @license         CC BY-NC-ND
// @grant           none
// @include         https://www.waze.com/editor/*
// @include         https://www.waze.com/*/editor/*
// @include         https://editor-beta.waze.com/*
// @namespace       https://greatest.deepsurf.us/users/9321
// ==/UserScript==

(function () {
	/**
	* The wLib namespace.
	* @namespace
	* @global
	*/
	this.wLib = {VERSION: '0.1'};
}).call(this);

(function () {
	/*** GEOMETRY ***/
	/**
	* Namespace for functions related to geometry.
	* @memberof wLib
	* @namespace
	* @name wLib.Geometry
	*/
	this.Geometry = {
		/**
		* Determines if an {OpenLayers.Geometry} is within the map view.
		* @memberof wLib.Geometry
		* @param geometry {OpenLayers.Geometry}
		* @return {Boolean} Whether or not the geometry is in the map extent.
		*/
		isGeometryInMapExtent: function (geometry) {
			'use strict';
			return geometry && geometry.getBounds &&
			W.map.getExtent().intersectsBounds(geometry.getBounds())
		},
		/**
		 * Determines if an {OpenLayers.LonLat} is within the map view.
		 * @memberof wLib.Geometry
		 * @param {OpenLayers.LonLat} lonlat
		 * @return {Boolean} Whether or not the LonLat is in the map extent.
		 */
		isLonLatInMapExtent: function (lonlat) {
			'use strict';
			return lonlat && W.map.getExtent().containsLonLat(lonlat);
		}
	};
}).call(wLib);

(function() {
	/*** MODEL ***/
	/**
	* Namespace for functions related to the model.
	* @memberof wLib
	* @namespace
	* @name wLib.Model
	*/
	this.Model = {};
	
	/**
	* Gets the IDs of any selected segments.
	* @memberof wLib.Model
	* @return {Array} Array containing the IDs of selected segments.
	*/
	this.Model.getSelectedSegmentIDs = function () {
		'use strict';
		var i, n, selectedItems, item, segments = [];
		if (!W.selectionManager.hasSelectedItems()) {
			return false;
		} else {
			selectedItems = W.selectionManager.selectedItems;
			for (i = 0, n = selectedItems.length; i < n; i++) {
				item = selectedItems[i].model;
				if ('segment' === item.type) {
					segments.push(item.attributes.id);
				}
			}
			return segments.length === 0 ? false : segments;
		}
	};	
	
	/**
	 * Retrives a route from the Waze Live Map.
	 * @class
	 * @name wLib.Model.RouteSelection
	 * @param firstSegment The segment to use as the start of the route.
	 * @param lastSegment The segment to use as the destination for the route.
	 * @param {Object} options A hash of options for determining route. Valid options are:
	 * fastest: {Boolean} Whether or not the fastest route should be used. Default is false,
	 * which selects the shortest route.
	 * freeways: {Boolean} Whether or not to avoid freeways. Default is false.
	 * dirt: {Boolean} Whether or not to avoid dirt roads. Default is false.
	 * uturns: {Boolean} Whether or not to allow U-turns. Default is true.
	 * @return {wLib.Model.RouteSelection} The new RouteSelection object.
	 */
	this.Model.RouteSelection = function (firstSegment, lastSegment, options) {
	    var startLonLat = this.getSegmentCenterLonLat(firstSegment);
	    var endLonLat = this.getSegmentCenterLonLat(lastSegment);
	    this.options = {
	        fastest: options && options.fastest || false,
	        freeways: options && options.freeways || false,
	        dirt: options && options.dirt || false,
	        uturns: options && options.uturns || true
	    };
	    this.requestData = {
	        from: 'x:' + startLonLat.lon + ' y:' + startLonLat.lat + ' bd:true',
	        to: 'x:' + endLonLat.lon + ' y:' + endLonLat.lat + ' bd:true',
	        returnJSON: true,
	        returnGeometries: true,
	        returnInstructions: false,
	        type: this.options.fastest ? 'HISTORIC_TIME' : 'DISTANCE',
	        clientVersion: '4.0.0',
	        timeout: 60000,
	        nPaths: 3,
	        options: this.setRequestOptions(this.options)
	    };
	    this.routeData = null;
		this.getRouteData();
		return this;
	};
	this.Model.RouteSelection.prototype = 
		/** @lends wLib.Model.RouteSelection.prototype */ {
		/**
		 * Formats the routing options string for the ajax request.
		 * @private
		 * @param {Object} options Object containing the routing options.
		 * @return {String} String containing routing options.
		 */
	    setRequestOptions: function (options) {
	        return 'AVOID_TOLL_ROADS:' + (options.tolls ? 't' : 'f') + ',' +
	      'AVOID_PRIMARIES:' + (options.freeways ? 't' : 'f') + ',' +
	      'AVOID_TRAILS:' + (options.dirt ? 't' : 'f') + ',' +
	      'ALLOW_UTURNS:' + (options.uturns ? 't' : 'f');
	    },
		/**
		 * Gets the center of a segment in LonLat form.
		 * @private
		 * @param segment A Waze model segment object.
		 * @return {OpenLayers.LonLat} The LonLat object corresponding to the
		 * center of the segment.
		 */
	    getSegmentCenterLonLat: function (segment) {
	        return segment && segment.geometry.getCentroid()
				.transform(W.map.getProjectionObject(), 'EPSG:4326').toLonLat();
	    },
		/**
		 * Gets the route from Live Map
		 * @private
		 * @returns The ajax request object. The responseJSON property of the returned object
		 * contains the route information.
		 * 
		 */
	    getRouteData: function () {
			var that = this;
	        return $.ajax({
	            dataType: "json",
	            url: this.getURL(),
	            data: this.requestData,
	            dataFilter: function (data, dataType) {
	                return data.replace(/NaN/g, '0');
	            },
				success: function(data) {
					that.routeData = data;
					that.selectRouteSegments();
				}
	        });
	    },
		/**
		 * Extracts the IDs from all segments on the route.
		 * @private
		 * @return {Array} Array containing an array of segment IDs for
		 * each route alternative.
		 */
	    getRouteSegmentIDs: function () {
	        var segIDs = [], 
	            routeArray = [],
	            data = this.routeData;
	        if ('undefined' !== typeof data.alternatives) {
	            for (i = 0 , len1 = data.alternatives.length; i < len1; i++) {
	                route = data.alternatives[i].response.results;
	                for (j = 0, len2 = route.length; j < len2; j++) {
	                    routeArray.push(route[j].path.segmentId);
	                }
	                segIDs.push(routeArray);
	                routeArray = [];
	            }
	        } else {
	            route = data.response.results;
	            for (i = 0 , len1 = route.length; i < len1; i++) {
	                routeArray.push(route[i].path.segmentId);
	            }
	            segIDs.push(routeArray);
	        }
	        return segIDs;
	    },
		/**
		 * Gets the URL to use for the ajax request based on country.
		 * @private
		 * @return {String} Relative URl to use for route ajax request.
		 */
	    getURL: function () {
	        if (Waze.model.countries.get(235) || Waze.model.countries.get(40)) {
	            return '/RoutingManager/routingRequest';
	        } else if (Waze.model.countries.get(106)) {
	            return '/il-RoutingManager/routingRequest';
	        } else {
	            return '/row-RoutingManager/routingRequest';
	        }
	    },
		/**
		 * Selects all segments on the route in the editor.
		 * @param {Integer} routeIndex The index of the alternate route.
		 * Default route to use is the first one, which is 0.
		 */
	    selectRouteSegments: function (routeIndex) {
	        var seg,
			segIDs = this.getRouteSegmentIDs()[routeIndex || 0],
	        segments = [];
	        if (undefined === typeof segIDs) {
	            return;
	        }
	        for (i = 0, n = segIDs.length; i < n; i++) {
				seg = W.model.segments.get(segIDs[i])
	            if (undefined !== seg) {
					segments.push(seg);
				}
	        }
	        return W.selectionManager.select(segments);
	    }
	};
}).call(wLib);

(function() {
	/*** INTERFACE ***/
	/**
	* Namespace for functions related to the WME interface
	* @memberof wLib
	* @namespace
	* @name wLib.Interface
	*/
	this.Interface = {};

	this.Interface.Shortcut = OL.Class(this.Interface,
		/** @lends wLib.Interface.Shortcut.prototype */
		{name: null,
		group: null,
		shortcut: {},
		callback: null,
		scope: null,
		groupExists: false,
		actionExists: false,
		eventExists: false,
		/**
		* Creates a new {wLib.Interface.Shortcut}.
		* @class
		* @name wLib.Interface.Shortcut
		* @param name {String} The name of the shortcut.
		* @param group {String} The name of the shortcut group.
		* @param shortcut {String} The shortcut key(s). The shortcut should be of the form
		* 'i' where i is the keyboard shortuct or include modifier keys such as'CSA+i',
		* where C = the control key, S = the shift key, A = the alt key, and
		* i = the desired keyboard shortcut. The modifier keys are optional.
		* @param callback {Function} The function to be called by the shortcut.
		* @param scope {Object} The object to be used as this by the callback.
		* @return {wLib.Interface.Shortcut} The new shortcut object.
		* @example //Creates new shortcut and adds it to the map.
		* shortcut = new wLib.Interface.Shortcut('myName', 'myGroup', 'C+p', callbackFunc, null).add();
		*/
		initialize: function (name, group, shortcut, callback, scope) {
			var defaults = {group: 'default'};
			this.CLASS_NAME = 'wLib Shortcut';
			if ('string' === typeof name && name.length > 0 &&
				'string' === typeof shortcut && shortcut.length > 0 &&
				'function' === typeof callback) {
				this.name = name;
				this.group = group || defaults.group;
				this.callback = callback;
				this.shortcut[shortcut] = name;
				if ('object' !== typeof scope) {
					this.scope = null;
				} else {
					this.scope = scope;
				}
				return this;
			}
		},
		/**
		* Determines if the shortcut's group already exists.
		* @private
		*/
		doesGroupExist: function () {
			this.groupExists = 'undefined' !== typeof W.accelerators.Groups[this.group] &&
			undefined !== typeof W.accelerators.Groups[this.group].members &&
			W.accelerators.Groups[this.group].length > 0;
			return this.groupExists;
		},
		/**
		* Determines if the shortcut's action already exists.
		* @private
		*/
		doesActionExist: function () {
			this.actionExists = 'undefined' !== typeof W.accelerators.Actions[this.name];
			return this.actionExists;
		},
		/**
		* Determines if the shortcut's event already exists.
		* @private
		*/
		doesEventExist: function () {
			this.eventExists = 'undefined' !== typeof W.accelerators.events.listeners[this.name] &&
				W.accelerators.events.listeners[this.name].length > 0 &&
				this.callback === W.accelerators.events.listeners[this.name][0].func &&
				this.scope === W.accelerators.events.listeners[this.name][0].obj;
			return this.eventExists;
		},
		/**
		* Creates the shortcut's group.
		* @private
		*/
		createGroup: function () {
			W.accelerators.Groups[this.group] = [];
			W.accelerators.Groups[this.group].members = [];
		},
		/**
		* Registers the shortcut's action.
		* @private
		*/
		addAction: function () {
			W.accelerators.addAction(this.name, {group: this.group});
		},
		/**
		* Registers the shortcut's event.
		* @private
		*/
		addEvent: function () {
			W.accelerators.events.register(this.name, this.scope, this.callback);
		},
		/**
		* Registers the shortcut's keyboard shortcut.
		* @private
		*/
		registerShortcut: function () {
			W.accelerators.registerShortcuts(this.shortcut);
		},
		/**
		* Adds the keyboard shortcut to the map.
		* @return {wLib.Interface.Shortcut} The keyboard shortcut.
		*/
		add: function () {
			/* If the group is not already defined, initialize the group. */
			if (!this.doesGroupExist()) {
				this.createGroup();
			}

			/* Clear existing actions with same name */
			if (this.doesActionExist()) {
				W.accelerators.Actions[this.name] = null;
			}
			this.addAction();

			/* Register event only if it's not already registered */
			if (!this.doesEventExist()) {
				this.addEvent();
			}

			/* Finally, register the shortcut. */
			this.registerShortcut();
			return this;
		},
		/**
		* Removes the keyboard shortcut from the map.
		* @return {wLib.Interface.Shortcut} The keyboard shortcut.
		*/
		remove: function () {
			if (this.doesEventExist()) {
				W.accelerators.events.unregister(this.name, this.scope, this.callback);
			}
			if (this.doesActionExist()) {
				delete W.accelerators.Actions[this.name];
			}
			//remove shortcut?
			return this;
		},
		/**
		* Changes the keyboard shortcut and applies changes to the map.
		* @return {wLib.Interface.Shortcut} The keyboard shortcut.
		*/
		change: function (shortcut) {
			if (shortcut) {
				this.shortcut = {};
				this.shortcut[shortcut] = this.name;
				this.registerShortcut();
			}
			return this;
		}
	});
}).call(wLib);