This is the .user.js file from the distribution.
Code: Select all
// ==UserScript==
// @name WME Junction Node Fixer
// @description Creates a new editor hotkey to lock turns, fix reverse connectivity, and restore original restricted turns.
// @include https://*.waze.com/editor/*
// @version 0.0.9.1
// ==/UserScript==
WME_JNF_Version = "v0.0.9.1";
function WME_JNF_Bootstrap()
{
var bGreasemonkeyServiceDefined = false;
try {
bGreasemonkeyServiceDefined = (typeof Components.interfaces.gmIGreasemonkeyService === "object");
}
catch (err) { /* Ignore */ }
if (typeof unsafeWindow === "undefined" || ! bGreasemonkeyServiceDefined) {
unsafeWindow = ( function () {
var dummyElem = document.createElement('p');
dummyElem.setAttribute('onclick', 'return window;');
return dummyElem.onclick();
}) ();
}
/* begin running the code! */
setTimeout(WME_JNF_Init, 500);
}
var matched = false;
var WME_Version = undefined;
// Feature detect + local reference
var storage, fail, uid;
var options = {};
var WCENC = null;
var WCSAVE = null;
var WCCHAT = null;
var WCLU = null;
var WCUR = null;
var WCMP = null;
function WME_JNF_PatchAndReload() {
var patch;
}
function WME_JNF_SaveEnd(b) {
console.log("WME-JNF: Save %s", b.success ? "succeeded" : "failed");
if (b.success) {
WCSAVE.controller.reload();
}
}
function WME_JNF_smn(s1, s2)
{
var pmap = [0, 10, 11, 15, 14, 1, 13, 12, 8, 0, 3, 0, 0, 0, 0, 0, 2, 7, 5, 4, 6, 9];
var mod = null;
if (s1.isGeometryEditable() && !s2.isGeometryEditable()) {
console.log("only s1 can be modified");
mod = s1;
} else if (!s1.isGeometryEditable() && s2.isGeometryEditable()) {
console.log("only s2 can be modified");
mod = s2;
} else if (s1.isGeometryEditable() && s2.isGeometryEditable()) {
/* pick one */
if (pmap[s1.attributes.roadType] < pmap[s2.attributes.roadType]) {
console.log("s1 lower type");
mod = s1;
} else if (pmap[s1.attributes.roadType] > pmap[s2.attributes.roadType]) {
console.log("s2 lower type");
mod = s2;
} else {
if (s1.attributes.length > s2.attributes.length) {
console.log("s1 longer");
mod = s1;
} else if (s1.attributes.length < s2.attributes.length) {
console.log("s2 longer");
mod = s2;
} else {
if (s1.attributes.createdOn > s2.attributes.createdOn) {
console.log("s1 newer");
mod = s1;
} else if (s1.attributes.createdOn < s2.attributes.createdOn) {
console.log("s2 newer");
mod = s2;
} else {
if (s1.getID() > s2.getID()) {
console.log("s1 higher id");
mod = s1;
} else {
console.log("s2 higher id");
mod = s2;
}
}
}
}
} else {
console.log("cannot modify either.");
}
if (mod) {
var point;
if (mod.geometry.components.length > 2) {
console.log("Splitting: " + mod.getID() + " on geo point " + (Math.ceil(mod.geometry.components.length / 2) - 1) + " of " + mod.geometry.components.length);
point = mod.geometry.components[Math.ceil(mod.geometry.components.length / 2) - 1];
} else {
point = mod.getCenter();
console.log("Splitting:", mod.getID(), "at center.");
}
W.model.actionManager.add(new Waze.Action.SplitSegments(mod, {splitAtPoint: point}));
}
}
function WME_JNF_CleanRBT(jct) {
var roadTypes = { "street": 1, "primary": 2, "freeway": 3, "ramp": 4,
"trail": 5, "major": 6, "minor": 7, "dirt": 8,
"boardwalk": 10, "stairway": 16, "private": 17, "railroad": 18,
"runway": 19, "parking": 20, "service": 21};
var typenames = { 1: "street", 2: "primary", 3: "freeway", 4: "ramp",
5: "trail", 6: "major", 7: "minor", 8: "dirt",
10: "boardwalk", 16: "stairway", 17: "private", 18: "railroad",
19: "runway", 20: "parking", 21: "service"};
var prec = [4, 6, 7, 2, 1, 21, 17, 20, 8];
if (jct.valid == true) {
var types = {};
var roadtype = false;
var cities = {};
var i = 0;
var cityid = 0;
var street = null;
var city = null;
var state = null;
var country = null;
var update = true;
var street_updated = false;
var type_updated = false;
var nodes = {};
jct.segIDs.forEach(function(segid) {
var seg = W.model.segments.get(segid);
for (var i = 0; i < seg.geometry.components.length; i++)
if (!onScreen(seg))
update = false;
});
if (update == false)
return;
jct.segIDs.forEach(function(segid) {
var seg = W.model.segments.get(segid);
if (seg.attributes.primaryStreetID) {
street = W.model.streets.get(seg.attributes.primaryStreetID);
city = W.model.cities.get(street.cityID);
if (city) {
if (!cities[street.cityID])
cities[street.cityID] = 0;
if (!city.isEmpty)
cities[street.cityID] += 100;
}
}
nodes[seg.attributes.toNodeID] = W.model.nodes.get(seg.attributes.toNodeID);
nodes[seg.attributes.fromNodeID] = W.model.nodes.get(seg.attributes.fromNodeID);
});
Object.forEach(nodes, function(k, node) {
node.attributes.segIDs.forEach(function(csegid) {
var cseg = W.model.segments.get(csegid);
if (!cseg.attributes.junctionID) {
if (cseg.attributes.roadType != roadTypes["freeway"]) {
if (!types[cseg.attributes.roadType])
types[cseg.attributes.roadType] = 0;
if (cseg.attributes.fwdDirection)
types[cseg.attributes.roadType] += 1;
if (cseg.attributes.revDirection)
types[cseg.attributes.roadType] += 1;
if (cseg.attributes.primaryStreetID) {
street = W.model.streets.get(cseg.attributes.primaryStreetID);
city = W.model.cities.get(street.cityID);
if (city) {
if (!cities[street.cityID])
cities[street.cityID] = 0;
if (city.isEmpty) {
cities[street.cityID] += 1;
} else {
cities[street.cityID] += 2;
}
}
}
}
}
});
});
i = 0;
Object.forEach(cities, function(k, v) {
if (i < v) {
i = v;
cityid = k;
}
});
street = W.model.streets.getByAttributes({isEmpty: true, cityID: cityid}).first();
city = W.model.cities.get(cityid);
if (city)
country = W.model.countries.get(city.countryID);
state = null;
if (city && city.stateID)
state = W.model.states.get(city.stateID);
var j;
for (i = 0; i < prec.length && !roadtype; i++) {
if (city.countryID == 234 && prec[i] == 4)
continue;
if (prec[i] in types) {
if (types[prec[i]] > 3 || (types[prec[i]] && city.countryID == 234)) {
roadtype = prec[i];
} else {
for (j = i+1; j < prec.length && !roadtype; j++) {
if (types[prec[j]] > 1) {
roadtype = prec[j];
}
}
}
if (!roadtype)
roadtype = prec[i];
}
}
jct.segIDs.forEach(function(segid) {
var seg = W.model.segments.get(segid);
if (seg.attributes.roadType != roadtype) {
W.model.actionManager.add(new W.Action.UpdateObject(seg, {roadType: roadtype}));
if (!type_updated) {
console.log("JNF_RBT: road type: " + roadtype + " " + typenames[roadtype]);
type_updated = true;
}
}
if (!seg.attributes.primaryStreetID || (street && seg.attributes.primaryStreetID != street.id)) {
W.model.actionManager.add(new W.Action.UpdateSegmentAddress(seg, {countryID: city.countryID, stateID: city.stateID, cityName: city.name, emptyStreet: true}));
if (!street_updated) {
if (state.name != "Other")
console.log("JNF_RBT: " + city.name + ", " + state.name + ", " + country.name);
else
console.log("JNF_RBT: " + city.name + ", " + country.name);
street = W.model.streets.getByAttributes({isEmpty: true, cityID: cityid}).first();
console.log("JNF_RBT: street: %o ", street);
street_updated = true;
}
}
});
Object.forEach(nodes, function(k, node) {
WME_JNF_FixNode(node, false);
});
}
}
function WME_JNF_DAT(a) {
if (!a.enabled)
return;
WME_JNF_FixNode(a.selectedFeature, true);
}
function onScreen(obj) {
if (obj.geometry) {
return(W.map.getExtent().intersectsBounds(obj.geometry.getBounds()));
}
return(false);
}
WME_JNF_FixNode = function(node, doJunctions) {
if (!node)
return;
if (!node.type)
return;
if (node.type != "node")
return;
if (node.areConnectionsEditable() && onScreen(node)) {
connections = {};
junctions = {};
for (var i = 0; i < node.attributes.segIDs.length; i++) {
var seg = W.model.segments.get(node.attributes.segIDs[i]);
if (seg) {
if (seg.attributes.toNodeID == seg.attributes.fromNodeID) {
if (seg.attributes.junctionID) {
console.log("single node rb");
} else {
console.log("single node loop");
}
var seg1geo = seg.geometry.clone();
var seg2geo = seg.geometry.clone();
var seg3geo = seg.geometry.clone();
var mod3 = seg.geometry.components.length % 3;
for (var i = 0; i < seg.geometry.components.length / 3 - 1; i++) {
seg1geo.components.pop();
seg1geo.components.pop();
seg2geo.components.pop();
seg2geo.components.shift();
seg3geo.components.shift();
seg3geo.components.shift();
}
if (mod3 == 2) {
seg1geo.components.pop();
seg3geo.components.shift();
}
if (mod3 == 0) {
seg1geo.components.pop();
seg1geo.components.pop();
seg3geo.components.shift();
seg3geo.components.shift();
}
var newseg1, newseg3, ns1ls, ns3ls;
if (node.attributes.connections) {
newseg1 = new Waze.Feature.Vector.Segment(seg1geo);
newseg3 = new Waze.Feature.Vector.Segment(seg3geo);
} else {
ns1ls = new OpenLayers.Geometry.LineString(seg1geo.getVertices());
ns3ls = new OpenLayers.Geometry.LineString(seg3geo.getVertices());
newseg1 = new Waze.Feature.Vector.Segment;
newseg3 = new Waze.Feature.Vector.Segment;
}
newseg1.copyAttributes(seg);
newseg3.copyAttributes(seg);
newseg1.attributes.junctionID = null;
newseg3.attributes.junctionID = null;
newseg1.attributes.fromNodeID = null;
newseg3.attributes.fromNodeID = null;
newseg1.attributes.toNodeID = null;
newseg3.attributes.toNodeID = null;
if (!node.attributes.connections) {
newseg1.geometry = ns1ls;
newseg3.geometry = ns3ls;
newseg1.setID(null);
newseg3.setID(null);
console.log("ns1:", newseg1);
console.log("ns3:", newseg3);
}
var joinsegs = [];
joinsegs.push(newseg1);
joinsegs.push(seg);
console.log("Disconnect:", seg.getID(), seg, "from:", node.getID(), node);
W.model.actionManager.add(new W.Action.DisconnectSegment(seg, node));
console.log("Disconnect:", seg.getID(), seg, "from:", node.getID(), node);
W.model.actionManager.add(new W.Action.DisconnectSegment(seg, node));
console.log("W.A.AddSegment(W.F.V.S(seg1geo))");
W.model.actionManager.add(new W.Action.AddSegment(newseg1));
console.log("W.A.AddSegment(W.F.V.S(seg3geo))");
W.model.actionManager.add(new W.Action.AddSegment(newseg3));
console.log("ns1:", newseg1);
console.log("ns3:", newseg3);
console.log("UpdateSegmentGeometry:", seg.getID(), seg);
W.model.actionManager.add(new W.Action.UpdateSegmentGeometry(seg, seg.geometry, seg2geo));
W.model.actionManager.add(new W.Action.ConnectSegment(node, newseg1));
W.model.actionManager.add(new W.Action.ConnectSegment(node, newseg3));
console.log("Add Node at", seg1geo.components.last());
W.model.actionManager.add(new W.Action.AddNode(seg1geo.components.last(), joinsegs));
joinsegs = []
joinsegs.push(seg);
joinsegs.push(newseg3);
console.log("Add Node at", seg3geo.components.first());
W.model.actionManager.add(new W.Action.AddNode(seg3geo.components.first(), joinsegs));
W.model.actionManager.add(new W.Action.UpdateObject(newseg1, {fwdTurnsLocked: true, revTurnsLocked: true}));
W.model.actionManager.add(new W.Action.UpdateObject(seg, {fwdTurnsLocked: true, revTurnsLocked: true}));
W.model.actionManager.add(new W.Action.UpdateObject(newseg3, {fwdTurnsLocked: true, revTurnsLocked: true}));
W.model.actionManager.add(new W.Action.ModifyAllConnections(newseg1.getToNode(), true));
W.model.actionManager.add(new W.Action.ModifyAllConnections(newseg1.getFromNode(), true));
W.model.actionManager.add(new W.Action.ModifyAllConnections(seg.getToNode(), true));
W.model.actionManager.add(new W.Action.ModifyAllConnections(seg.getFromNode(), true));
W.model.actionManager.add(new W.Action.ModifyAllConnections(newseg3.getToNode(), true));
W.model.actionManager.add(new W.Action.ModifyAllConnections(newseg3.getFromNode(), true));
}
if (!seg.isDeleted()) {
// store any roundabouts we see
if (seg.attributes.junctionID) {
junctions[seg.attributes.junctionID] = W.model.junctions.get(seg.attributes.junctionID);
}
// terminate unterminated dead-ends
var segments = [];
segments.push(seg);
if (seg.attributes.toNodeID == null) {
W.model.actionManager.add(new W.Action.AddNode(seg.geometry.components.last(), segments));
}
if (seg.attributes.fromNodeID == null) {
W.model.actionManager.add(new W.Action.AddNode(seg.geometry.components.first(), segments));
}
var toNode = seg.getToNode();
var fromNode = seg.getFromNode();
if (toNode && fromNode && !toNode.isDeleted() && !fromNode.isDeleted()) {
if (onScreen(toNode) && onScreen(fromNode)) {
if ((seg.attributes.fwdDirection == false || seg.attributes.revDirection == false) && (toNode.attributes.segIDs.length < 2 || fromNode.attributes.segIDs.length < 2))
{
console.log("JNF: updating dead-end segment " + seg.getID() + " to two-way");
W.model.actionManager.add(new W.Action.UpdateObject(seg, {fwdDirection: true, revDirection: true}));
}
if (toNode.attributes.connections) {
// old editor
if (toNode.attributes.segIDs.length < 2 && !toNode.isTurnAllowed(seg, seg)) {
console.log("Enabling dead-end u-turn at", toNode.getID(), "on", seg.getID());
W.model.actionManager.add(new W.Action.ModifyConnection(seg.getID(), toNode, seg.getID(), true));
if (!seg.attributes.fwdTurnsLocked) {
W.model.actionManager.add(new W.Action.UpdateObject(seg, {fwdTurnsLocked: true}));
}
}
if (fromNode.attributes.segIDs.length < 2 && !fromNode.isTurnAllowed(seg, seg)) {
console.log("Enabling dead-end u-turn at", toNode.getID(), "on", seg.getID());
W.model.actionManager.add(new W.Action.ModifyConnection(seg.getID(), fromNode, seg.getID(), true));
if (!seg.attributes.revTurnsLocked) {
W.model.actionManager.add(new W.Action.UpdateObject(seg, {revTurnsLocked: true}));
}
}
} else {
// beta editor
if (toNode.attributes.segIDs.length < 2 && !seg.isTurnAllowed(seg, toNode)) {
console.log("Enabling dead-end u-turn at", toNode.getID(), "on", seg.getID());
W.model.actionManager.add(new W.Action.ModifyConnection(seg.getID(), toNode, seg.getID(), true));
}
if (fromNode.attributes.segIDs.length < 2 && !seg.isTurnAllowed(seg, fromNode)) {
console.log("Enabling dead-end u-turn at", toNode.getID(), "on", seg.getID());
W.model.actionManager.add(new W.Action.ModifyConnection(seg.getID(), fromNode, seg.getID(), true));
}
}
}
if (node.attributes.segIDs.length > 1) {
// disable u-turns
var turnAllowed;
if (node.attributes.connections) {
// old editor
turnAllowed = node.isTurnAllowed(seg, seg);
} else {
// beta editor
turnAllowed = seg.isTurnAllowed(seg, node);
}
if (turnAllowed) {
console.log("Disabling U-Turn at", node.getID(), "on", seg.getID());
W.model.actionManager.add(new W.Action.ModifyConnection(seg.getID(), node, seg.getID(), false));
}
}
}
}
}
}
if (node.attributes.segIDs.length > 1) {
var seg1, seg2;
for (var i = 0; i < node.attributes.segIDs.length - 1; i++) {
seg1 = W.model.segments.get(node.attributes.segIDs[i]);
for (var j = i + 1; j < node.attributes.segIDs.length; j++) {
seg2 = W.model.segments.get(node.attributes.segIDs[j]);
if (seg1.isDeleted() == false && seg2.isDeleted() == false) {
var fwd_t;
var rev_t;
var fwd_a;
var rev_a;
if (node.attributes.connections) {
fwd_t = node.isTurnAllowed(seg1, seg2);
rev_t = node.isTurnAllowed(seg2, seg1);
} else {
fwd_t = seg1.isTurnAllowed(seg2, node);
rev_t = seg2.isTurnAllowed(seg1, node);
}
fwd_a = node.isTurnAllowedBySegDirections(seg1, seg2);
rev_a = node.isTurnAllowedBySegDirections(seg2, seg1);
if (fwd_t && !fwd_a) {
console.log("Disabling RevCon at", node.getID(), "into", seg2.getID());
W.model.actionManager.add(new W.Action.ModifyConnection(seg1.getID(), node, seg2.getID(), false));
}
if (rev_t && !rev_a) {
console.log("Disabling RevCon at", node.getID(), "into", seg1.getID());
W.model.actionManager.add(new W.Action.ModifyConnection(seg2.getID(), node, seg1.getID(), false));
}
if ((seg1.attributes.fromNodeID == seg2.attributes.fromNodeID && seg1.attributes.toNodeID == seg2.attributes.toNodeID) ||
(seg1.attributes.fromNodeID == seg2.attributes.toNodeID && seg1.attributes.toNodeID == seg2.attributes.fromNodeID)) {
console.log("sid:", seg1.getID(), "and sid:", seg2.getID(), "connected to same nodes:", seg1.attributes.fromNodeID, seg1.attributes.toNodeID);
WME_JNF_smn(seg1, seg2);
}
}
}
if (!seg1.isDeleted() && !seg1.areTurnsLocked(node)) {
var attr = seg1.getTurnsLockAttribute(node);
var dict = {}
dict[attr] = true;
console.log("Locking Turns at", node.getID(), "on", seg1.getID());
W.model.actionManager.add(new W.Action.UpdateObject(seg1, dict));
}
}
if (!seg2.isDeleted() && !seg2.areTurnsLocked(node)) {
var attr = seg2.getTurnsLockAttribute(node);
var dict = {}
dict[attr] = true;
console.log("Locking Turns at", node.getID(), "on", seg2.getID());
W.model.actionManager.add(new W.Action.UpdateObject(seg2, dict));
}
}
if (doJunctions) {
// clean up roundabouts
Object.forEach(junctions, function(i, j) {
WME_JNF_CleanRBT(j);
});
}
// refresh turn arrows
WCENC.toggleShowAllArrows();
WCENC.toggleShowAllArrows();
}
}
function WME_JNF_CheckAPI() {
if (typeof(Waze) != "object") {
matched = "Waze";
return false;
}
if (typeof(W.model) != "object") {
matched = "W.model";
return false;
}
if (typeof(W.map) != "object") {
matched = "W.map";
return false;
}
if (typeof(W.map.controls) != "object") {
matched = "W.map.controls";
return false;
}
if (typeof(W.map.controls[0]) != "object") {
matched = "W.map.controls[0]";
return false;
}
if (typeof(W.map.controls[0].displayClass) != "string") {
matched = "W.map.controls[0].displayClass";
return false;
}
Object.forEach(W.map.controls, function(k, v) {
if (v.displayClass == "WazeControlEditNodeConnections") {
WCENC = v;
}
if (v.displayClass == "WazeControlSave") {
WCSAVE = v;
}
if (v.displayClass == "WazeControlChat") {
WCCHAT = v;
}
if (v.displayClass == "WazeControlMapProblems") {
WCMP = v;
}
if (v.displayClass == "WazeControlUpdateRequests") {
WCUR = v;
}
if (v.displayClass == "WazeControlLiveUsers") {
WCLU = v;
}
});
if (typeof(WCENC) != "object") {
matched = "WCENC";
return false;
}
if (typeof(WCSAVE) != "object") {
matched = "WCSAVE";
return false;
}
if (typeof(WCCHAT) != "object") {
matched = "WCCHAT";
return false;
}
if (typeof(WCMP) != "object") {
matched = "WCMP";
return false;
}
if (typeof(WCUR) != "object") {
matched = "WCUR";
return false;
}
if (typeof(WCLU) != "object") {
matched = "WCLU";
return false;
}
if (typeof(Waze.Config) != "object") {
matched = "Waze.Config";
return false;
}
if (typeof(Waze.Config.cameras) != "object") {
matched = "Waze.Config.cameras";
return false;
}
if (typeof(Waze.Config.cameras.minDisplayZoom) != "number") {
matched = "Waze.Config.cameras.minDisplayZoom";
return false;
}
if (typeof(W.model.cameras) != "object") {
matched = "W.model.cameras";
return false;
}
if (typeof(W.model.cameras.minZoom) != "number") {
matched = "W.model.cameras.minZoom";
return false;
}
if (typeof(W.map.toggleFullscreen) != "function") {
matched = "W.map.toggleFullscreen";
return false;
}
if (typeof(WCENC.showAllArrows) != "boolean") {
matched = "WCENC.showAllArrows";
return false;
}
if (typeof(WCENC.showArrows) != "boolean") {
matched = "WCENC.showArrows";
return false;
}
if (typeof(WCENC.toggleShowAllArrows) != "function") {
matched = "WCENC.toggleShowAllArrows";
return false;
}
if (typeof(WCSAVE.controller) != "object") {
matched = "WCSAVE.controller";
return false;
}
if (typeof(WCSAVE.controller.events) != "object") {
matched = "WCSAVE.controller.events";
return false;
}
if (typeof(WCSAVE.controller.events.register) != "function") {
matched = "WCSAVE.controller.events.register";
return false;
}
if (typeof(W.map.DefaultPanInPixel) != "number") {
matched = "W.map.DefaultPanInPixel";
return false;
}
if (typeof(Waze.accelerators) != "object") {
if (typeof(Waze.Accelerators) != "object") {
matched = "Waze.accelerators";
return false;
} else {
Waze.accelerators = Waze.Accelerators;
}
}
if (typeof(Waze.accelerators.events) != "object") {
matched = "Waze.accelerators.events";
return false;
}
if (typeof(Waze.accelerators.events.listeners) != "object") {
matched = "Waze.accelerators.events.listeners";
return false;
}
if (typeof(Waze.accelerators.events.listeners.disallowAllConnections) != "object") {
matched = "Waze.accelerators.events.listeners.disallowAllConnections";
return false;
}
if (typeof(Waze.accelerators.events.listeners.disallowAllConnections[0]) != "object") {
matched = "Waze.accelerators.events.listeners.disallowAllConnections[0]";
return false;
}
if (typeof(Waze.accelerators.events.listeners.disallowAllConnections[0].func) != "function") {
matched = "Waze.accelerators.events.listeners.disallowAllConnections[0].func";
return false;
}
if (typeof(Waze.accelerators.events.listeners.allowAllConnections) != "object") {
matched = "Waze.accelerators.events.listeners.allowAllConnections";
return false;
}
if (typeof(Waze.accelerators.events.listeners.allowAllConnections[0]) != "object") {
matched = "Waze.accelerators.events.listeners.allowAllConnections[0]";
return false;
}
if (typeof(Waze.accelerators.events.listeners.allowAllConnections[0].func) != "function") {
matched = "Waze.accelerators.events.listeners.allowAllConnections[0].func";
return false;
}
if (typeof(W.map.getExtent) != "function") {
matched = "W.map.getExtent";
return false;
}
var tstvar = W.map.getExtent();
if (typeof(tstvar) != "object") {
matched = "W.map.getExtent()";
return false;
}
if (typeof(tstvar.toGeometry) != "function") {
matched = "W.map.getExtent().toGeometry";
return false;
}
var tstvar = tstvar.toGeometry();
if (typeof(tstvar) != "object") {
matched = "W.map.getExtent().toGeometry() == object";
return false;
}
if (typeof(tstvar.containsPoint) != "function") {
matched = "W.map.getExtent().toGeometry().containsPoint";
return false;
}
if (typeof(W.model.segments) != "object") {
matched = "W.model.segments";
return false;
}
if (typeof(W.model.segments.get) != "function") {
matched = "W.model.segments.get";
return false;
}
if (typeof(W.model.nodes) != "object") {
matched = "W.model.nodes";
return false;
}
if (typeof(W.model.nodes.get) != "function") {
matched = "W.model.nodes.get";
return false;
}
if (typeof(W.model.junctions) != "object") {
matched = "W.model.junctions";
return false;
}
if (typeof(W.model.junctions.get) != "function") {
matched = "W.model.junctions.get";
return false;
}
if (typeof(W.model.streets) != "object") {
matched = "W.model.streets";
return false;
}
if (typeof(W.model.streets.get) != "function") {
matched = "W.model.streets.get";
return false;
}
if (typeof(W.model.streets.getByAttributes) != "function") {
matched = "W.model.streets.getByAttributes";
return false;
}
if (typeof(W.model.cities) != "object") {
matched = "W.model.cities";
return false;
}
if (typeof(W.model.cities.get) != "function") {
matched = "W.model.cities.get";
return false;
}
if (typeof(W.model.countries) != "object") {
matched = "W.model.countries";
return false;
}
if (typeof(W.model.countries.get) != "function") {
matched = "W.model.countries.get";
return false;
}
if (typeof(W.model.actionManager) != "object") {
matched = "W.model.actionManager";
return false;
}
if (typeof(W.model.actionManager.add) != "function") {
matched = "W.model.actionManager.add";
return false;
}
if (typeof(W.Action) != "function") {
matched = "W.Action";
return false;
}
if (typeof(W.Action.UpdateObject) != "function") {
matched = "W.Action.UpdateObject";
return false;
}
if (typeof(W.Action.UpdateSegmentAddress) != "function") {
matched = "W.Action.UpdateSegmentAddress";
return false;
}
if (typeof(W.Action.DisconnectSegment) != "function") {
matched = "W.Action.DisconnectSegment";
return false;
}
if (typeof(W.Action.UpdateSegmentGeometry) != "function") {
matched = "W.Action.UpdateSegmentGeometry";
return false;
}
if (typeof(W.Action.AddSegment) != "function") {
matched = "W.Action.AddSegment";
return false;
}
if (typeof(W.Action.AddNode) != "function") {
matched = "W.Action.AddNode";
return false;
}
if (typeof(W.Action.ConnectSegment) != "function") {
matched = "W.Action.ConnectSegment";
return false;
}
if (typeof(W.Action.ModifyAllConnections) != "function") {
matched = "W.Action.ModifyAllConnections";
return false;
}
if (typeof(Waze.Feature) != "object") {
matched = "Waze.Feature";
return false;
}
if (typeof(Waze.Feature.Vector) != "function") {
matched = "Waze.Feature.Vector";
return false;
}
if (typeof(Waze.Feature.Vector.Segment) != "function") {
matched = "Waze.Feature.Vector.Segment";
return false;
}
if (typeof(W.model.nodes.objects) != "object") {
matched = "W.model.nodes.objects";
return false;
}
tstvar = Object.keys(W.model.nodes.objects);
if (typeof(tstvar) != "object") {
matched = "W.model.nodes.objects keys";
return false;
}
return true;
}
function WME_JNF_RestoreSettings() {
// restore saved setting
if (storage) {
console.log("WME-JNF: loading options");
options = JSON.parse(storage.getItem('WME_JNF'));
if (options == null) {
console.log("no options");
return;
}
if (WCENC) {
WCENC.showAllArrows = options['showallarrows'];
WCENC.showArrows = options['showarrows'];
WCENC.toggleShowAllArrows();
WCENC.toggleShowAllArrows();
} else {
console.log("no WCENC");
}
if (WCSAVE) {
WCSAVE.controller.events.register("saveend", this, WME_JNF_SaveEnd);
WME_JNF_PatchAndReload();
} else {
console.log("no WCSAVE");
}
if (options['fullscreen']) {
if (options['fullscreen'] == "fullscreen" && document.body.className != "fullscreen") {
console.log("going fullscreen");
W.map.toggleFullscreen();
}
}
}
// W.model.events.unregister("mergeend", this, WME_JNF_RestoreSettings);
}
function WME_JNF_OnUnload() {
if (storage) {
console.log("WME-JNF: saving options");
options = {};
// options['hotkey'] = getId('_cbJNF_Hotkey');
Object.forEach(W.map.controls, function(k, v) {
if (v.displayClass == "WazeControlEditNodeConnections") {
options['showallarrows'] = v.showAllArrows;
options['showarrows'] = v.showArrows;
}
});
options['fullscreen'] = document.body.className;
storage.setItem('WME_JNF', JSON.stringify(options));
}
}
function WME_JNF_Hook() {
console.log("WME-JNF: Hook");
// make cameras visible at zoom 0 and load at zoom 1
Waze.Config.cameras.minDisplayZoom = 0;
W.model.cameras.minZoom = 0;
// update pan amount so keyboard panning is useful
W.map.DefaultPanInPixel = W.map.size.h / 4;
$(window).on("beforeunload", WME_JNF_OnUnload);
// hook 'q'
Waze.accelerators.events.listeners.disallowAllConnections[0].func = function() {
WME_JNF_DAT(this);
}
// hook 'w'
Waze.accelerators.events.listeners.allowAllConnections[0].func = function() {
if (typeof(allowAllConnections) == 'function') {
allowAllConnections();
} else {
this.setAllConnections(true);
}
// refresh turn arrows
WCENC.toggleShowAllArrows();
WCENC.toggleShowAllArrows();
}
// W.model.events.unregister("mergeend", this, WME_JNF_Hook);
}
var init_tries = 0;
function WME_JNF_Init() {
console.log("WME-JNF: " + WME_JNF_Version + " starting");
try {
uid = new Date;
(storage = window.localStorage).setItem(uid, uid);
fail = storage.getItem(uid) != uid;
storage.removeItem(uid);
fail && (storage = false);
} catch(e) {}
console.log("WME-JNF: Checking API");
if (WME_JNF_CheckAPI()) {
WME_JNF_RestoreSettings();
WME_JNF_Hook();
} else {
console.log("WME-JNF: failed API check, exiting. " + matched);
alert("WME Junction Node Fixer has failed to load due to API check: " + matched);
WME_JNF_FixNode = undefined;
return;
}
}
$(document).ready(WME_JNF_Bootstrap);