· 8 years ago · Jun 17, 2018, 12:14 AM
1// ==UserScript==
2// @id iitc-plugin-arc
3// @name IITC plugin: Arc
4// @category Layer
5// @version 1.62
6// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
7// @updateURL http://ingress.wolflight.us/Arcs/arc.meta.js
8// @downloadURL http://ingress.wolflight.us/Arcs/arc.user.js
9// @description Allows you to create Great Circle arcs to plan long links safely
10// @include *://*.ingress.com/intel*
11// @include *://*.ingress.com/mission/*
12// @match *://*.ingress.com/intel*
13// @match *://*.ingress.com/mission/*
14// @grant none
15// ==/UserScript==
16
17function wrapper() {
18// ensure plugin framework is there, even if iitc is not yet loaded
19if(typeof window.plugin !== 'function') window.plugin = function() {};
20
21// PLUGIN START ////////////////////////////////////////////////////////
22// use own namespace for plugin
23/* jshint shadow:true */
24window.plugin.arcs = function() {};
25window.plugin.arcs.loadExternals = function() {
26 try { console.log('Loading arc.js now'); } catch(e) {}
27
28 //Lets create an independent layer for this hey?
29 //create a leaflet FeatureGroup to hold arcs
30 window.plugin.arcs.drawlayer = new L.FeatureGroup();
31
32 window.addLayerGroup('Arcs', window.plugin.arcs.drawlayer, true);
33
34 /* jshint ignore:start */
35 /* arc.js by Dane Springmeyer, https://github.com/springmeyer/arc.js */
36 var D2R=Math.PI/180,R2D=180/Math.PI,Coord=function(c,e){this.lon=c;this.lat=e;this.x=D2R*c;this.y=D2R*e;};Coord.prototype.view=function(){return String(this.lon).slice(0,4)+","+String(this.lat).slice(0,4);};Coord.prototype.antipode=function(){return new Coord(0>this.lon?180+this.lon:-1*(180-this.lon),-1*this.lat);};var LineString=function(){this.coords=[];this.length=0;};LineString.prototype.move_to=function(c){this.length++;this.coords.push(c);};
37 var Arc=function(c){this.properties=c||{};this.geometries=[];};
38 Arc.prototype.json=function(){if(0>=this.geometries.length)return{geometry:{type:"LineString",coordinates:null},type:"Feature",properties:this.properties};if(1==this.geometries.length)return{geometry:{type:"LineString",coordinates:this.geometries[0].coords},type:"Feature",properties:this.properties};var c=[];for(i=0;i<this.geometries.length;i++)c.push(this.geometries[i].coords);return{geometry:{type:"MultiLineString",coordinates:c},type:"Feature",properties:this.properties};};
39 Arc.prototype.wkt=function(){var c="";for(i=0;i<this.geometries.length;i++){if(0===this.geometries[i].coords.length)return"LINESTRING(empty)";var e="LINESTRING(";this.geometries[i].coords.forEach(function(a,c){e+=a[0]+" "+a[1]+",";});c+=e.substring(0,e.length-1)+")";}return c;};
40 var GreatCircle=function(c,e,a){this.start=c;this.end=e;this.properties=a||{};a=this.start.x-this.end.x;a=Math.pow(Math.sin((this.start.y-this.end.y)/2),2)+Math.cos(this.start.y)*Math.cos(this.end.y)*Math.pow(Math.sin(a/2),2);this.g=2*Math.asin(Math.sqrt(a));if(this.g==Math.PI)throw Error("it appears "+c.view()+" and "+e.view()+" are 'antipodal', e.g diametrically opposite, thus there is no single route but rather infinite");if(isNaN(this.g))throw Error("could not calculate great circle between "+
41 c+" and "+e);};
42 GreatCircle.prototype.interpolate=function(c){var e=Math.sin((1-c)*this.g)/Math.sin(this.g),a=Math.sin(c*this.g)/Math.sin(this.g);c=e*Math.cos(this.start.y)*Math.cos(this.start.x)+a*Math.cos(this.end.y)*Math.cos(this.end.x);var g=e*Math.cos(this.start.y)*Math.sin(this.start.x)+a*Math.cos(this.end.y)*Math.sin(this.end.x),e=e*Math.sin(this.start.y)+a*Math.sin(this.end.y),e=R2D*Math.atan2(e,Math.sqrt(Math.pow(c,2)+Math.pow(g,2)));return[R2D*Math.atan2(g,c),e];};
43 GreatCircle.prototype.Arc=function(c,e){var a=[];if(2>=c)a.push([this.start.lon,this.start.lat]),a.push([this.end.lon,this.end.lat]);else for(var g=1/(c-1),b=0;b<c;b++){var k=this.interpolate(g*b);a.push(k)}for(var d=!1,h=0,b=1;b<a.length;b++){var g=a[b-1][0],k=a[b][0],m=Math.abs(k-g);350<m&&(170<k&&-170>g||170<g&&-170>k)?d=!0:m>h&&(h=m)}g=[];if(d&&10>h)for(d=[],g.push(d),b=0;b<a.length;b++)if(k=parseFloat(a[b][0]),0<b&&350<Math.abs(k-a[b-1][0])){var f=parseFloat(a[b-1][0]),h=parseFloat(a[b-1][1]),
44 l=parseFloat(a[b][0]),m=parseFloat(a[b][1]);if(-180<f&&-170>f&&180==l&&b+1<a.length&&-180<a[b-1][0]&&-170>a[b-1][0])d.push([-180,a[b][1]]),b++,d.push([a[b][0],a[b][1]]);else if(170<f&&180>f&&-180==l&&b+1<a.length&&170<a[b-1][0]&&180>a[b-1][0])d.push([180,a[b][1]]),b++,d.push([a[b][0],a[b][1]]);else{if(-170>f&&170<l)var n=f,f=l,l=n,n=h,h=m,m=n;170<f&&-170>l&&(l+=360);180>=f&&180<=l&&f<l?(f=(180-f)/(l-f),h=f*m+(1-f)*h,d.push([170<a[b-1][0]?180:-180,h]),d=[],d.push([170<a[b-1][0]?-180:180,h])):d=[];
45 g.push(d);d.push([k,a[b][1]])}}else d.push([a[b][0],a[b][1]]);else for(d=[],g.push(d),b=0;b<a.length;b++)d.push([a[b][0],a[b][1]]);a=new Arc(this.properties);for(b=0;b<g.length;b++)for(k=new LineString,a.geometries.push(k),d=g[b],h=0;h<d.length;h++)k.move_to(d[h]);return a};if("undefined"===typeof window)module.exports.Coord=Coord,module.exports.Arc=Arc,module.exports.GreatCircle=GreatCircle;else{var arc={};arc.Coord=Coord;arc.Arc=Arc;arc.GreatCircle=GreatCircle};
46 /* jshint ignore:end */
47
48 window.plugin.arcs.arc = arc;
49 $('#toolbox').append(' <a id="arcButton" onclick="window.plugin.arcs.draw()" title="Start an arc from this portal">Start arc</a>');
50 $('#toolbox').append(' <a id="recButton" onclick="window.plugin.arcs.crosslinkRecord()" title="Toggle crosslink recording">Arc REC xlinks</a>');
51 $('#toolbox').append(' <a onclick="window.plugin.arcs.list()" title="Arc details">Arc List</a>');
52 $('#toolbox').append(' <a onclick="window.plugin.arcs.dialogDrawer()" title="Draw lines/triangles between bookmarked portals">Arc Auto Draw</a>');
53 $('#toolbox').append(' <a id="anchorButton" onclick="window.plugin.arcs.anchorShift()" title="Shift all arcs from one portal to another">Anchor Shift Start</a>');
54 $('#toolbox').append(' <a id="arcRangeButton" onclick="window.plugin.arcs.rangePopup()" title="Range Calculator">Arc Range</a>');
55
56 //list of all links on map
57 window.plugin.arcs.link_list = [];
58 window.plugin.arcs.blockerRecording = false;
59
60
61 var version_number = 12;
62 var update_message = 'Added colour choice and persistent Xlinks.<br/>--Remember this tool is enlightened only.';
63 var arc_version = JSON.parse(localStorage.getItem('arc_version' ));
64 if (arc_version===null||arc_version<version_number)
65 {
66 dialog({
67 html:'<div>'+update_message+'</div>',
68 dialogClass:'ui-dialog-update',
69 title:'Arcs Update',
70 width: 500
71 });
72 localStorage.setItem( 'arc_version', JSON.stringify(version_number) );
73 }
74
75
76
77 var arc_list = JSON.parse(localStorage.getItem('arc_list' ));
78 if (arc_list===null)
79 {
80 arc_list = [];
81 localStorage.setItem( 'arc_list', JSON.stringify(arc_list) );
82 }
83 else
84 {
85 //cycle through and print them on load.
86 for (var m=0;m<arc_list.length;m++)
87 {
88 var link = arc_list[m];
89 var startCoord = new window.plugin.arcs.arc.Coord(link.startPortal.lon, link.startPortal.lat);
90 var stopCoord = new window.plugin.arcs.arc.Coord(link.endPortal.lon, link.endPortal.lat);
91 window.plugin.arcs.create(startCoord, stopCoord, link);
92 }
93 }
94 //Lets make our table pretty CSS!!!
95 $('head').append('<style>' +
96 '#linkslist table {margin-top:5px; border-collapse: collapse; empty-cells: show; width:100%; clear: both;}' +
97 '#linkslist table td { text-align: left;}' +
98 '#linkslist table td:nth-child(3) { text-align: right;}' +
99 '#linkslist .portalTitle { display: inline-block; width: 160px !important; min-width: 160px !important; max-width: 160px !important; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }' +
100 '#rangecalc table {margin-top:5px; border-collapse: collapse; empty-cells: show; width:100%; clear: both;}' +
101 '#rangecalc table td { text-align: center; user-select: none; -webkit-user-select: none;}' +
102 '#leftarcbutton a {display: block;} #arcbutton a.active { background-color: #BBB;}' +
103 '</style>');
104
105 //add a nice pretty buttons
106 var parent = $(".leaflet-top.leaflet-left", window.map.getContainer());
107
108 var button = document.createElement("a");
109 button.className = "leaflet-bar-part";
110 button.addEventListener("click", function(){window.plugin.arcs.draw();});
111 button.title = 'Arc control';
112 button.innerHTML = 'A';
113 button.id='leftarcbutton';
114
115 var container = document.createElement("div");
116 container.className = "leaflet-bar leaflet-control";
117 container.appendChild(button);
118 parent.append(container);
119
120 var button = document.createElement("a");
121 button.className = "leaflet-bar-part";
122 button.addEventListener("click", function(){window.plugin.arcs.checkAllLinks();});
123 button.title = 'Arc Crosslink Check';
124 button.innerHTML = 'X';
125
126 var container = document.createElement("div");
127 container.className = "leaflet-bar leaflet-control";
128 container.appendChild(button);
129 parent.append(container);
130
131 var button = document.createElement("a");
132 button.className = "leaflet-bar-part";
133 button.addEventListener("click", function(){window.plugin.arcs.list();});
134 button.title = 'Arc List';
135 button.innerHTML = 'L';
136
137 var container = document.createElement("div");
138 container.className = "leaflet-bar leaflet-control";
139 container.appendChild(button);
140 parent.append(container);
141
142
143 //Popups for errors
144 var ARCNotifcation = '.ARCNotifcation{width:200px;height:20px;height:auto;position:absolute;left:50%;margin-left:-100px;top:50%;z-index:10000;background-color: #EE3838;color: #F0F0F0;font-family: Calibri;font-size: 20px;padding:10px;text-align:center;border-radius: 2px;-webkit-box-shadow: 0px 0px 24px -1px rgba(56, 56, 56, 1);-moz-box-shadow: 0px 0px 24px -1px rgba(56, 56, 56, 1);box-shadow: 0px 0px 24px -1px rgba(56, 56, 56, 1);}';
145 $('head').append("<style>" + ARCNotifcation + "</style>");
146 $('body').append("<div id='ArcError1' class='ARCNotifcation' style='display:none'>Portal Details Not Yet Loaded</div>");
147 $('body').append("<div id='ArcError2' class='ARCNotifcation' style='display:none'>Same Start And End Portal</div>");
148 $('body').append("<div id='ArcRefresh' class='ARCNotifcation' style='display:none'>Building Request</div>");
149
150 $('head').append('<style type="text/css">.plugin-arcs-crosslinks-stats {background-color: rgba(8, 48, 78, 0.9);border-bottom: 0;border-top: 1px solid #20A8B1;border-left: 1px solid #20A8B1;top: 0;color: #ffce00;font-size: 13px;padding: 4px;position: fixed; left: 47%; z-index: 3002;box-sizing: border-box;margin-right: 312px;text-overflow: ellipsis;white-space: nowrap;overflow: hidden;}</style>');
151 $('body').append('<div class="plugin-arcs-crosslinks-stats"></div>');
152 $('.plugin-arcs-crosslinks-stats').html("Arcs Blockers - R: -- E: --").hide();
153
154 // Check if Arc Cross Links group is turned on or first time user. If either one of them is true, show crosslink counter
155 if(JSON.parse(localStorage['ingress.intelmap.layergroupdisplayed'])["Arc Cross Links"] || typeof JSON.parse(localStorage['ingress.intelmap.layergroupdisplayed'])["Arc Cross Links"] == "undefined"){
156 $('.plugin-arcs-crosslinks-stats').show();
157 }
158
159 $(document).ready(function() {
160 console.log('Loading Arcs Hooks');
161 if(window.plugin.bookmarks){
162 window.addHook('pluginBkmrksEdit', arc_hook_pluginBkmrksEdit );
163 window.addHook('pluginBkmrksSyncEnd', arc_hook_pluginBkmrksSyncEnd );
164 }
165 console.log('Done Loading Arcs Hooks');
166 });
167 window.plugin.arcs.createLayer();
168 console.log('Done');
169
170};
171
172function arc_hook_pluginBkmrksEdit(data){
173 //Update Bookmarklist on BkmrksEdit
174 if(window.DIALOGS['dialog-arcs-dialog-window']){
175 window.plugin.arcs.dialogDrawer();
176 }
177}
178
179function arc_hook_pluginBkmrksSyncEnd(data){
180 //Update Bookmarklist on BkmrksSyncEnd
181 if(window.DIALOGS['dialog-arcs-dialog-window']){
182 window.plugin.arcs.dialogDrawer();
183 }
184}
185
186// hotkey
187function doc_keyUp(e) {
188
189 // this would test for whichever key is 40 and the ctrl key at the same time
190 if (e.altKey && e.keyCode == 65) {
191 // call your function to do the thing
192 window.plugin.arcs.draw();
193 }
194}
195// register the handler
196document.addEventListener('keyup', doc_keyUp, false);
197
198
199window.plugin.arcs.clear = function() {
200 //clears storage array and refreshes page
201 if (confirm('Are you sure you want to remove all arcs')) {
202 arc_list =[];
203 localStorage.setItem( 'arc_list', JSON.stringify(arc_list) );
204 //refresh the layer group
205 window.plugin.arcs.drawlayer.clearLayers();
206 window.plugin.arcs.link_list = [];
207 // Run a crosslink check to remove all crossing links
208 window.plugin.arcs.checkAllLinks();
209 //now to close the dialogue
210 window.plugin.arcs.list();
211 }
212};
213
214window.plugin.arcs.distance = function(link) {
215 //How far between portals.
216 var R = 6367; // km
217
218 lat1 = link.startPortal.lat;
219 lon1 = link.startPortal.lon;
220 lat2 = link.endPortal.lat;
221 lon2 = link.endPortal.lon;
222
223 var dLat = (lat2-lat1) * Math.PI / 180;
224 var dLon = (lon2-lon1) * Math.PI / 180;
225 var lat1 = lat1 * Math.PI / 180;
226 var lat2 = lat2 * Math.PI / 180;
227 var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
228 Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
229 var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
230 var d = R * c;
231 d = Math.round(d * 1000) / 1000;
232 return d;
233};
234
235window.plugin.arcs.create = function(startCoord, stopCoord, link, xLink) {
236 //draws the link on the map
237 if (typeof xLink === 'undefined') { xLink = false; }
238 //if colour is set use that else use red as default
239 //this preserves old plans
240 if (link.color)
241 {
242 colour = link.color;
243 }
244 else
245 {
246 colour = "#ff0000";
247 }
248
249
250 if (xLink)
251 {
252 myStyle = {
253 "color": colour,
254 "weight": 5,
255 "opacity": 0.7,
256 "dashArray": [10, 10, 1, 10]
257 };
258 }
259 else
260 {
261 myStyle = {
262 "color": colour,
263 "weight": 5,
264 "opacity": 0.7
265 };
266 }
267 var gc = new window.plugin.arcs.arc.GreatCircle(startCoord, stopCoord);
268 var geojson_feature = gc.Arc(Math.round(link.distance)).json();
269 var line = new L.geoJson(geojson_feature,{style: myStyle}).addTo(window.plugin.arcs.drawlayer);
270 //map.addLayer(line);
271 window.plugin.arcs.link_list.push(line);
272 bindString='';
273 bindString+='<div>Length: <a onclick="window.plugin.arcs.rangePopup('+link.distance+')">'+link.distance+'</a>km<br/>';
274 bindString+='Start: '+window.plugin.arcs.getPortalLink(link.startPortal);
275 bindString+='End: '+window.plugin.arcs.getPortalLink(link.endPortal);
276 bindString+='<hr/><a onclick="window.plugin.arcs.extend('+link.endPortal.lat+','+link.endPortal.lon+','+link.startPortal.lat+','+link.startPortal.lon+')">Great Circle</a>';
277 bindString+='<hr/><a id="arc_remove">Remove Arc</a></div>';
278
279 line.bindPopup(bindString);
280 line.on('contextmenu', function() { window.plugin.arcs.kill_line(line,link); } );
281 line.on('popupopen', function() { document.getElementById("arc_remove").onclick = function () {window.plugin.arcs.kill_line(line,link);map.closePopup();} ;} );
282};
283
284window.plugin.arcs.kill_line = function(line,link) {
285 map.removeLayer(line);
286 //remove from storage
287 var arc_list = JSON.parse(localStorage.getItem('arc_list' ));
288 for (var i=0;i<arc_list.length;i++)
289 {
290 var link_test = arc_list[i];
291 if (JSON.stringify(link_test) === JSON.stringify(link))
292 {
293 j=i;
294 }
295 }
296 arc_list.splice(j,1);
297 localStorage.setItem( 'arc_list', JSON.stringify(arc_list) );
298};
299
300window.plugin.arcs.getPortalLink = function(portal) {
301 var latlng = [portal.lat, portal.lon].join();
302 var jsSingleClick = 'window.renderPortalDetails(\''+portal.guid+'\');return false';
303 var jsDoubleClick = 'window.zoomToAndShowPortal(\''+portal.guid+'\', ['+latlng+']);return false';
304 var perma = '/intel?ll='+portal.lat+','+portal.lon+'&z=17&pll='+portal.lat+','+portal.lon;
305
306 //Use Jquery to create the link, which escape characters in TITLE and ADDRESS of portal
307 var a = $('<a>',{
308 "class": 'help',
309 text: portal.title,
310 //title: portal.address,
311 href: perma,
312 onClick: jsSingleClick,
313 onDblClick: jsDoubleClick
314 })[0].outerHTML;
315 var div = '<div class="portalTitle">'+a+'</div>';
316 return div;
317};
318
319window.plugin.arcs.getRange = function() {
320 //select mods
321 var mod_handicap_effect = [1, 0.25, 0.125, 0.125];
322 var link_amp_multiplier = 0;
323 var countVRLA = parseInt(document.getElementById('VRLA').innerHTML, 10);
324 var countSBULA = parseInt(document.getElementById('SBULA').innerHTML, 10);
325 var countRLA = parseInt(document.getElementById('RLA').innerHTML, 10);
326
327 for (i=0;i<4;i++)
328 {
329 if (countVRLA>0)
330 {
331 link_amp_multiplier += mod_handicap_effect[i]*7;
332 countVRLA--;
333 continue;
334 }
335 if (countSBULA>0)
336 {
337 link_amp_multiplier += mod_handicap_effect[i]*5;
338 countSBULA--;
339 continue;
340 }
341 if (countRLA>0)
342 {
343 link_amp_multiplier += mod_handicap_effect[i]*2;
344 countRLA--;
345 continue;
346 }
347 //console.log(link_amp_multiplier);
348 }
349 if (link_amp_multiplier===0)
350 {
351 link_amp_multiplier=1;
352 }
353
354 var portalLevel = 0;
355 for (i=1;i<=8;i++)
356 {
357 portalLevel = portalLevel + parseInt(document.getElementById('R'+i).innerHTML, 10)/8;
358 }
359 //console.log(portalLevel);
360 var portalRange = Math.pow(portalLevel,4)*0.16*link_amp_multiplier;
361 portalRange = Math.floor(portalRange * 1000) / 1000;
362 //console.log(portalRange);
363 document.getElementById("portalLevel").innerHTML =portalLevel;
364 document.getElementById("portalRange").innerHTML =portalRange;
365 if (portalRange>document.getElementById("linkDistance").innerHTML)
366 {
367 document.getElementById("inRange").innerHTML ='YES';
368 document.getElementById("inRange").style.color="green";
369 }
370 else
371 {
372 document.getElementById("inRange").innerHTML ='NO';
373 document.getElementById("inRange").style.color="red";
374 }
375};
376
377window.plugin.arcs.rangePopup = function(d) {
378 //select mods
379 html = 'Mods:';
380 html += '<table><tr><td>RLA</td><td>SBULA</td><td>VRLA</td></tr>';
381 html += '<tr><td><a onclick=\'window.plugin.arcs.incrementValue("RLA",-1);\'>-</a><span id="RLA"> 0 </span><a onclick=\'window.plugin.arcs.incrementValue("RLA",1);\'>+</a></td>';
382 html += '<td><a onclick=\'window.plugin.arcs.incrementValue("SBULA",-1);\'>-</a><span id="SBULA"> 0 </span><a onclick=\'window.plugin.arcs.incrementValue("SBULA",1);\'>+</a></td>';
383 html += '<td><a onclick=\'window.plugin.arcs.incrementValue("VRLA",-1);\'>-</a><span id="VRLA"> 0 </span><a onclick=\'window.plugin.arcs.incrementValue("VRLA",1);\'>+</a></td></tr></table>';
384 html +='<hr/>Resonators:<table>';
385 html += '<tr><td><a onclick=\'window.plugin.arcs.incrementRes("R1",1);\'>+</a></td><td><a onclick=\'window.plugin.arcs.incrementRes("R2",1);\'>+</a></td><td><a onclick=\'window.plugin.arcs.incrementRes("R3",1);\'>+</a></td><td><a onclick=\'window.plugin.arcs.incrementRes("R4",1);\'>+</a></td><td><a onclick=\'window.plugin.arcs.incrementRes("R5",1);\'>+</a></td><td><a onclick=\'window.plugin.arcs.incrementRes("R6",1);\'>+</a></td><td><a onclick=\'window.plugin.arcs.incrementRes("R7",1);\'>+</a></td><td><a onclick=\'window.plugin.arcs.incrementRes("R8",1);\'>+</a></td></tr>';
386 html += '<tr><td><div id="R1">4</div></td><td><div id="R2">4</div></td><td><div id="R3">5</div></td><td><div id="R4">5</div></td><td><div id="R5">6</div></td><td><div id="R6">6</div></td><td><div id="R7">7</div></td><td><div id="R8">8</div></td></tr>';
387 html += '<tr><td><a onclick=\'window.plugin.arcs.incrementRes("R1",-1);\'>-</a></td><td><a onclick=\'window.plugin.arcs.incrementRes("R2",-1);\'>-</a></td><td><a onclick=\'window.plugin.arcs.incrementRes("R3",-1);\'>-</a></td><td><a onclick=\'window.plugin.arcs.incrementRes("R4",-1);\'>-</a></td><td><a onclick=\'window.plugin.arcs.incrementRes("R5",-1);\'>-</a></td><td><a onclick=\'window.plugin.arcs.incrementRes("R6",-1);\'>-</a></td><td><a onclick=\'window.plugin.arcs.incrementRes("R7",-1);\'>-</a></td><td><a onclick=\'window.plugin.arcs.incrementRes("R8",-1);\'>-</a></td></tr></table>';
388 html +='<hr/>Portal Level: <span id="portalLevel"></span></br>Portal Range: <span id="portalRange"></span>km</br>Link: <span id="linkDistance">'+d+'</span>km</br>Success: <span id="inRange"></span>';
389
390 dialog({
391 html: '<div id="rangecalc">' + html + '</div>',
392 dialogClass: 'ui-dialog-portal',
393 title: 'Range',
394 id: 'portal-arc-range',
395 width: 300
396 });
397 window.plugin.arcs.getRange();
398};
399
400window.plugin.arcs.incrementValue = function(id,amount)
401{
402 var total = parseInt(document.getElementById("RLA").innerHTML, 10)+parseInt(document.getElementById("SBULA").innerHTML, 10)+parseInt(document.getElementById("VRLA").innerHTML, 10);
403 var value = parseInt(document.getElementById(id).innerHTML, 10);
404 if((total<4&&amount==1)||(total>0&&amount==-1&&value>0))
405 {
406 value=value+amount;
407 document.getElementById(id).innerHTML = ' '+value+' ';
408 }
409 window.plugin.arcs.getRange();
410};
411window.plugin.arcs.incrementRes = function(id,amount)
412{
413 var value = parseInt(document.getElementById(id).innerHTML, 10);
414 if((value<8&&amount==1)||(value>1&&amount==-1))
415 {
416 value=value+amount;
417 document.getElementById(id).innerHTML = value;
418 }
419 window.plugin.arcs.getRange();
420};
421
422window.plugin.arcs.drawToolsExport = function() {
423 var arc_list = JSON.parse(localStorage.getItem('arc_list' ));
424 var data = [];
425 for (var i=0;i<arc_list.length;i++)
426 {
427 var link = arc_list[i];
428 var item = {};
429 item.type = 'polyline';
430
431 a= {};
432 a.lat=link.startPortal.lat;
433 a.lng=link.startPortal.lon;
434
435 b= {};
436 b.lat=link.endPortal.lat;
437 b.lng=link.endPortal.lon;
438
439 temp = [a,b];
440 //temp[0]['lat']=link.startPortal.lat;
441 //temp[0]['lng']=link.startPortal.lon;
442 //temp[1]['lat']=link.endPortal.lat;
443 //temp[1]['lng']=link.endPortal.lon;
444 item.latLngs = temp;
445 item.color = link.color;
446
447 data.push(item);
448 //console.log(data);
449 }
450
451 return JSON.stringify(data);
452};
453
454window.plugin.arcs.edit =function(position,operation) {
455 //edit the local storage and redraw everything is the only way to be safe.
456 //this is expensive but shouldn't be a big issue
457 //Lets create an independent layer for this hey?
458
459 var arc_list = JSON.parse(localStorage.getItem('arc_list' ));
460 var link = arc_list[position];
461
462 if (operation=='swap')
463 {
464 window.plugin.arcs.link = {};
465 window.plugin.arcs.link.color = link.color;
466 window.plugin.arcs.link.startPortal = link.endPortal;
467 window.plugin.arcs.link.endPortal = link.startPortal;
468 window.plugin.arcs.link.distance = window.plugin.arcs.distance(window.plugin.arcs.link);
469 arc_list[position]=window.plugin.arcs.link;
470 }
471 if (operation=='delete')
472 {
473 arc_list.splice(position,1);
474 }
475 if (operation=='color')
476 {
477 link.color=arcColor;
478 arc_list[position]=link;
479 }
480
481 //save changes
482 localStorage.setItem( 'arc_list', JSON.stringify(arc_list) );
483
484 //refresh the layer group
485 window.plugin.arcs.drawlayer.clearLayers();
486 window.plugin.arcs.link_list = [];
487 //redraw all lines
488 for (var m=0;m<arc_list.length;m++)
489 {
490 var link = arc_list[m];
491 var startCoord = new window.plugin.arcs.arc.Coord(link.startPortal.lon, link.startPortal.lat);
492 var stopCoord = new window.plugin.arcs.arc.Coord(link.endPortal.lon, link.endPortal.lat);
493 window.plugin.arcs.create(startCoord, stopCoord, link);
494 }
495 //refresh list
496 arcslist_top = $('#dialog-portal-arc').dialog('widget').position().top;
497 arcslist_left= $('#dialog-portal-arc').dialog('widget').position().left;
498 arcslist_scroll= document.getElementById('dialog-portal-arc').scrollTop;
499 window.plugin.arcs.list();
500};
501
502window.plugin.arcs.arcsparsing = function() {
503 //make form
504 var arcForm = document.createElement("form");
505 arcForm.target = "_blank";
506 arcForm.method = "POST";
507 arcForm.name = "form1";
508 arcForm.action = "http://ingress.sebbens.com/arcsparsing.php";
509 //add data
510 var arcInput = document.createElement("input");
511 arcInput.type = "text";
512 arcInput.name = "arcslist";
513 arcInput.value = localStorage.getItem('arc_list');
514 arcForm.appendChild(arcInput);
515 var arcInput = document.createElement("input");
516 arcInput.type = "text";
517 arcInput.name = "Submit";
518 arcInput.value = 'Submit';
519 arcForm.appendChild(arcInput);
520 document.body.appendChild(arcForm);
521
522 arcForm.submit();
523};
524
525//list box positions
526var arcslist_scroll=0;
527var arcslist_top=window.innerHeight/2-544/2;
528var arcslist_left=window.innerWidth/2-550/2;
529
530
531window.plugin.arcs.list = function() {
532 var arc_list = JSON.parse(localStorage.getItem('arc_list' ));
533 //lets create a table
534 var html = '<table class="arc-link-table"><thead style="text-align: left;"><tr><th style="width:5px;"></th><th>Start Portal</th><th></th><th>End Portal</th><th>Distance(km)</th><th></th><th></th></tr></thead><tbody>';
535 for (var i=0;i<arc_list.length;i++)
536 {
537 var link = arc_list[i];
538 html +='<tr><td style="background-color:'+link.color+';" onclick="window.plugin.arcs.edit('+i+',\'color\')"> </td>';
539 html +='<td>'+window.plugin.arcs.getPortalLink(link.startPortal)+'</td>';
540 html +='<td><a onclick="window.plugin.arcs.edit('+i+',\'swap\')">«»</a></td>';
541 html +='<td>'+window.plugin.arcs.getPortalLink(link.endPortal)+'</td>';
542 html +='<td><a onclick="window.plugin.arcs.rangePopup('+link.distance+')">'+link.distance+'</a></td>';
543 html +='<td><a onclick="window.plugin.arcs.edit('+i+',\'delete\')">X</a></td>';
544 html +='<td><span class="link-drag-handle" style="cursor:move;">=</span></td></tr>';
545
546 }
547 html +='</tbody></table>';
548 //color select
549 html +='<hr/>Arc Colour: <form method="POST" action="" onsubmit="window.plugin.arcs.changeColor(\'\');return false;"><input style="color:'+arcColor+';" type="text" onclick="this.focus();this.select()" id="colorString" name="Arc Color" cols="7" rows="1" value="'+arcColor+'">';
550 html +='<button type="button" onclick="window.plugin.arcs.changeColor(\'\');">Set</button> <button type="button" style="background-color:#ff0000;min-height:19px;" onclick="window.plugin.arcs.changeColor(\'#ff0000\');"></button>';
551 html +='<button type="button" style="background-color:#00ff77;min-height:19px;" onclick="window.plugin.arcs.changeColor(\'#00ff77\');"></button>';
552 html +='<button type="button" style="background-color:#ff00ff;min-height:19px;" onclick="window.plugin.arcs.changeColor(\'#ff00ff\');"></button>';
553 html +='<button type="button" style="background-color:#ffff00;min-height:19px;" onclick="window.plugin.arcs.changeColor(\'#ffff00\');"></button>';
554 html +='<button type="button" style="background-color:#ffffff;min-height:19px;" onclick="window.plugin.arcs.changeColor(\'#ffffff\');"></button>';
555 html +='</form>';
556
557 html +='<hr/>Import/Export (copy out to share links or paste in to add links)<br/>';
558 //Lets add in the JSON text for storage and shareing.
559 html += '<form method="POST" action=""><textarea onclick="this.focus();this.select()" id="JSONstring" name="jsondata" cols="50" rows="1">'+localStorage.getItem('arc_list')+'</textarea></form><button type="button" onclick="window.plugin.arcs.list.addJSONdata()">Add Data</button>';
560 html +='<hr/><div>DRAW TOOLS EXPORT: For lowly users that only have draw tools give them this to import your plan</div><textarea onclick="this.focus();this.select()" id="JSONstring" name="jsondata" cols="50" rows="1">'+window.plugin.arcs.drawToolsExport()+'</textarea>';
561 //Link to Darryls parser
562 html +='<hr/><div><a onclick="window.plugin.arcs.arcsparsing()" title="Send to http://ingress.sebbens.com/arcsparsing.php">Export to parser</a><br/>Gives a summary including key counts and csv exports. [[ALLOW POPUPS]]</div>';
563 //small readme
564 html +='<hr/><div><p>';
565 html +='You can left click a link to get details about it on the map.<br/>';
566 html +='If you right click the link it will remove it.<br/>';
567 html +='Click a distance to see the range calculator.<br/>';
568 html +='Alt+A is the start stop arc shortcut.<br/>';
569 html +='The A, X and L buttons on the left control arc creation, check for cross links and display this list.<br/>';
570 html +='Chat about Arcs here: <a target="_blank" href="https://telegram.me/joinchat/AucXcz0XP34Rc8mQr8Oxzg">Telegram Link</a><br/>';
571 html +='Please feel free to share to any confirmed enlightened player. This plugin is <u><b>not</b></u> considered highly secure: <a target="_blank" href="http://ingress.wolflight.us/Arcs/arc.user.js">Arcs Plugin Link</a><br/>';
572 html +='Resistance agents: Use at your own risk.<br/>';
573 html +='</p></div><hr/><a onclick="window.plugin.arcs.clear()" title="Delete EVERYTHING FOREVER!">Clear arcs</a>';
574
575 dialog({
576 //html: '<div id="linkslist">' + html + '</div>',
577 html:'<div id="linkslist">test</div>',
578 dialogClass: 'ui-dialog-portal-arcs',
579 title: 'Links',
580 id: 'portal-arc',
581 width: 550,
582 position: { my: "left top", at: "left+"+arcslist_left+" top+"+arcslist_top},
583 beforeClose: function(event, ui) {
584 //$('#dialog-portal-arc').dialog('widget').position().top
585 arcslist_top = $('#dialog-portal-arc').dialog('widget').position().top;
586 arcslist_left= $('#dialog-portal-arc').dialog('widget').position().left;
587 arcslist_scroll= document.getElementById('dialog-portal-arc').scrollTop;
588 },
589 dragStop: function( event, ui ) {
590 //$('#dialog-portal-arc').dialog('widget').position().top
591 arcslist_top = $('#dialog-portal-arc').dialog('widget').position().top;
592 arcslist_left= $('#dialog-portal-arc').dialog('widget').position().left;
593 arcslist_scroll= document.getElementById('dialog-portal-arc').scrollTop;
594 }
595 });
596
597 //change the html of the dialog box.
598 document.getElementById('linkslist').innerHTML=html;
599
600
601 //lets move this to any previous scroll or position
602 //document.getElementById('dialog-portal-arc').scrollTop;
603 document.getElementById('dialog-portal-arc').scrollTop=arcslist_scroll;
604 //also the on page position
605 //save when closed
606 //local varible (no change when page reset)
607
608
609 $('.arc-link-table > tbody').sortable({
610 axis: 'y',
611 handle: '.link-drag-handle',
612 helper: function(e, ui) {
613 ui.children().each(function() {
614 $(this).width($(this).width());
615 });
616 return ui;
617 },
618 start: function(event, ui){
619 // Stores the position the link is coming from
620 ui.item.fromIndex = ui.item.index();
621 },
622 stop: function(event, ui){
623 // Gets new position of the link
624 var index = ui.item.index();
625 // Reorder json
626 window.plugin.arcs.list.reorder(ui.item.fromIndex, index);
627 }
628 });
629};
630
631window.plugin.arcs.list.reorder = function(fromIndex, newIndex){
632
633 // Load arc_list
634 var arc_list = JSON.parse(localStorage.getItem('arc_list' ));
635
636 // Re-orders json
637 if (newIndex >= arc_list.length) {
638 var k = newIndex - arc_list.length;
639 while ((k--) + 1) {
640 arc_list.push(undefined);
641 }
642 }
643 arc_list.splice(newIndex, 0, arc_list.splice(fromIndex, 1)[0]);
644
645 // save changes
646 localStorage.setItem( 'arc_list', JSON.stringify(arc_list));
647
648 //refresh the layer group
649 window.plugin.arcs.drawlayer.clearLayers();
650 window.plugin.arcs.link_list = [];
651
652 //redraw all lines
653 for (var m=0;m<arc_list.length;m++)
654 {
655 var link = arc_list[m];
656 var startCoord = new window.plugin.arcs.arc.Coord(link.startPortal.lon, link.startPortal.lat);
657 var stopCoord = new window.plugin.arcs.arc.Coord(link.endPortal.lon, link.endPortal.lat);
658 window.plugin.arcs.create(startCoord, stopCoord, link);
659 }
660 //refresh list
661 arcslist_top = $('#dialog-portal-arc').dialog('widget').position().top;
662 arcslist_left= $('#dialog-portal-arc').dialog('widget').position().left;
663 arcslist_scroll= document.getElementById('dialog-portal-arc').scrollTop;
664 window.plugin.arcs.list();
665};
666
667//schema validation program
668/* jshint ignore:start */
669!function(a,b){"function"==typeof define&&define.amd?define([],b):"undefined"!=typeof module&&module.exports?module.exports=b():a.tv4=b()}(this,function(){function a(b,c){if(b===c)return!0;if("object"==typeof b&&"object"==typeof c){if(Array.isArray(b)!==Array.isArray(c))return!1;if(Array.isArray(b)){if(b.length!==c.length)return!1;for(var d=0;d<b.length;d++)if(!a(b[d],c[d]))return!1}else{var e;for(e in b)if(void 0===c[e]&&void 0!==b[e])return!1;for(e in c)if(void 0===b[e]&&void 0!==c[e])return!1;for(e in b)if(!a(b[e],c[e]))return!1}return!0}return!1}function b(a){var b=String(a).replace(/^\s+|\s+$/g,"").match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);return b?{href:b[0]||"",protocol:b[1]||"",authority:b[2]||"",host:b[3]||"",hostname:b[4]||"",port:b[5]||"",pathname:b[6]||"",search:b[7]||"",hash:b[8]||""}:null}function c(a,c){function d(a){var b=[];return a.replace(/^(\.\.?(\/|$))+/,"").replace(/\/(\.(\/|$))+/g,"/").replace(/\/\.\.$/,"/../").replace(/\/?[^\/]*/g,function(a){"/.."===a?b.pop():b.push(a)}),b.join("").replace(/^\//,"/"===a.charAt(0)?"/":"")}return c=b(c||""),a=b(a||""),c&&a?(c.protocol||a.protocol)+(c.protocol||c.authority?c.authority:a.authority)+d(c.protocol||c.authority||"/"===c.pathname.charAt(0)?c.pathname:c.pathname?(a.authority&&!a.pathname?"/":"")+a.pathname.slice(0,a.pathname.lastIndexOf("/")+1)+c.pathname:a.pathname)+(c.protocol||c.authority||c.pathname?c.search:c.search||a.search)+c.hash:null}function d(a){return a.split("#")[0]}function e(a,b){if(a&&"object"==typeof a)if(void 0===b?b=a.id:"string"==typeof a.id&&(b=c(b,a.id),a.id=b),Array.isArray(a))for(var d=0;d<a.length;d++)e(a[d],b);else{"string"==typeof a.$ref&&(a.$ref=c(b,a.$ref));for(var f in a)"enum"!==f&&e(a[f],b)}}function f(a,b,c,d,e){if(Error.call(this),void 0===a)throw new Error("No code supplied for error: "+b);this.message=b,this.code=a,this.dataPath=c||"",this.schemaPath=d||"",this.subErrors=e||null;var f=new Error(this.message);if(this.stack=f.stack||f.stacktrace,!this.stack)try{throw f}catch(f){this.stack=f.stack||f.stacktrace}}function g(a,b){if(b.substring(0,a.length)===a){var c=b.substring(a.length);if(b.length>0&&"/"===b.charAt(a.length-1)||"#"===c.charAt(0)||"?"===c.charAt(0))return!0}return!1}function h(a){var b=new i,f=a||"en",g={addFormat:function(){b.addFormat.apply(b,arguments)},language:function(a){return a?(n[a]||(a=a.split("-")[0]),n[a]?(f=a,a):!1):f},addLanguage:function(a,b){var c;for(c in j)b[c]&&!b[j[c]]&&(b[j[c]]=b[c]);var d=a.split("-")[0];if(n[d]){n[a]=Object.create(n[d]);for(c in b)"undefined"==typeof n[d][c]&&(n[d][c]=b[c]),n[a][c]=b[c]}else n[a]=b,n[d]=b;return this},freshApi:function(a){var b=h();return a&&b.language(a),b},validate:function(a,c,d,e){var g=new i(b,!1,n[f],d,e);"string"==typeof c&&(c={$ref:c}),g.addSchema("",c);var h=g.validateAll(a,c,null,null,"");return!h&&e&&(h=g.banUnknownProperties()),this.error=h,this.missing=g.missing,this.valid=null===h,this.valid},validateResult:function(){var a={};return this.validate.apply(a,arguments),a},validateMultiple:function(a,c,d,e){var g=new i(b,!0,n[f],d,e);"string"==typeof c&&(c={$ref:c}),g.addSchema("",c),g.validateAll(a,c,null,null,""),e&&g.banUnknownProperties();var h={};return h.errors=g.errors,h.missing=g.missing,h.valid=0===h.errors.length,h},addSchema:function(){return b.addSchema.apply(b,arguments)},getSchema:function(){return b.getSchema.apply(b,arguments)},getSchemaMap:function(){return b.getSchemaMap.apply(b,arguments)},getSchemaUris:function(){return b.getSchemaUris.apply(b,arguments)},getMissingUris:function(){return b.getMissingUris.apply(b,arguments)},dropSchemas:function(){b.dropSchemas.apply(b,arguments)},defineKeyword:function(){b.defineKeyword.apply(b,arguments)},defineError:function(a,b,c){if("string"!=typeof a||!/^[A-Z]+(_[A-Z]+)*$/.test(a))throw new Error("Code name must be a string in UPPER_CASE_WITH_UNDERSCORES");if("number"!=typeof b||b%1!==0||1e4>b)throw new Error("Code number must be an integer > 10000");if("undefined"!=typeof j[a])throw new Error("Error already defined: "+a+" as "+j[a]);if("undefined"!=typeof k[b])throw new Error("Error code already used: "+k[b]+" as "+b);j[a]=b,k[b]=a,m[a]=m[b]=c;for(var d in n){var e=n[d];e[a]&&(e[b]=e[b]||e[a])}},reset:function(){b.reset(),this.error=null,this.missing=[],this.valid=!0},missing:[],error:null,valid:!0,normSchema:e,resolveUrl:c,getDocumentUri:d,errorCodes:j};return g}Object.keys||(Object.keys=function(){var a=Object.prototype.hasOwnProperty,b=!{toString:null}.propertyIsEnumerable("toString"),c=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],d=c.length;return function(e){if("object"!=typeof e&&"function"!=typeof e||null===e)throw new TypeError("Object.keys called on non-object");var f=[];for(var g in e)a.call(e,g)&&f.push(g);if(b)for(var h=0;d>h;h++)a.call(e,c[h])&&f.push(c[h]);return f}}()),Object.create||(Object.create=function(){function a(){}return function(b){if(1!==arguments.length)throw new Error("Object.create implementation only accepts one parameter.");return a.prototype=b,new a}}()),Array.isArray||(Array.isArray=function(a){return"[object Array]"===Object.prototype.toString.call(a)}),Array.prototype.indexOf||(Array.prototype.indexOf=function(a){if(null===this)throw new TypeError;var b=Object(this),c=b.length>>>0;if(0===c)return-1;var d=0;if(arguments.length>1&&(d=Number(arguments[1]),d!==d?d=0:0!==d&&1/0!==d&&d!==-1/0&&(d=(d>0||-1)*Math.floor(Math.abs(d)))),d>=c)return-1;for(var e=d>=0?d:Math.max(c-Math.abs(d),0);c>e;e++)if(e in b&&b[e]===a)return e;return-1}),Object.isFrozen||(Object.isFrozen=function(a){for(var b="tv4_test_frozen_key";a.hasOwnProperty(b);)b+=Math.random();try{return a[b]=!0,delete a[b],!1}catch(c){return!0}});var i=function(a,b,c,d,e){if(this.missing=[],this.missingMap={},this.formatValidators=a?Object.create(a.formatValidators):{},this.schemas=a?Object.create(a.schemas):{},this.collectMultiple=b,this.errors=[],this.handleError=b?this.collectError:this.returnError,d&&(this.checkRecursive=!0,this.scanned=[],this.scannedFrozen=[],this.scannedFrozenSchemas=[],this.scannedFrozenValidationErrors=[],this.validatedSchemasKey="tv4_validation_id",this.validationErrorsKey="tv4_validation_errors_id"),e&&(this.trackUnknownProperties=!0,this.knownPropertyPaths={},this.unknownPropertyPaths={}),this.errorMessages=c,this.definedKeywords={},a)for(var f in a.definedKeywords)this.definedKeywords[f]=a.definedKeywords[f].slice(0)};i.prototype.defineKeyword=function(a,b){this.definedKeywords[a]=this.definedKeywords[a]||[],this.definedKeywords[a].push(b)},i.prototype.createError=function(a,b,c,d,e){var g=this.errorMessages[a]||m[a];if("string"!=typeof g)return new f(a,"Unknown error code "+a+": "+JSON.stringify(b),c,d,e);var h=g.replace(/\{([^{}]*)\}/g,function(a,c){var d=b[c];return"string"==typeof d||"number"==typeof d?d:a});return new f(a,h,c,d,e)},i.prototype.returnError=function(a){return a},i.prototype.collectError=function(a){return a&&this.errors.push(a),null},i.prototype.prefixErrors=function(a,b,c){for(var d=a;d<this.errors.length;d++)this.errors[d]=this.errors[d].prefixWith(b,c);return this},i.prototype.banUnknownProperties=function(){for(var a in this.unknownPropertyPaths){var b=this.createError(j.UNKNOWN_PROPERTY,{path:a},a,""),c=this.handleError(b);if(c)return c}return null},i.prototype.addFormat=function(a,b){if("object"==typeof a){for(var c in a)this.addFormat(c,a[c]);return this}this.formatValidators[a]=b},i.prototype.resolveRefs=function(a,b){if(void 0!==a.$ref){if(b=b||{},b[a.$ref])return this.createError(j.CIRCULAR_REFERENCE,{urls:Object.keys(b).join(", ")},"","");b[a.$ref]=!0,a=this.getSchema(a.$ref,b)}return a},i.prototype.getSchema=function(a,b){var c;if(void 0!==this.schemas[a])return c=this.schemas[a],this.resolveRefs(c,b);var d=a,e="";if(-1!==a.indexOf("#")&&(e=a.substring(a.indexOf("#")+1),d=a.substring(0,a.indexOf("#"))),"object"==typeof this.schemas[d]){c=this.schemas[d];var f=decodeURIComponent(e);if(""===f)return this.resolveRefs(c,b);if("/"!==f.charAt(0))return void 0;for(var g=f.split("/").slice(1),h=0;h<g.length;h++){var i=g[h].replace(/~1/g,"/").replace(/~0/g,"~");if(void 0===c[i]){c=void 0;break}c=c[i]}if(void 0!==c)return this.resolveRefs(c,b)}void 0===this.missing[d]&&(this.missing.push(d),this.missing[d]=d,this.missingMap[d]=d)},i.prototype.searchSchemas=function(a,b){if(a&&"object"==typeof a){"string"==typeof a.id&&g(b,a.id)&&void 0===this.schemas[a.id]&&(this.schemas[a.id]=a);for(var c in a)if("enum"!==c)if("object"==typeof a[c])this.searchSchemas(a[c],b);else if("$ref"===c){var e=d(a[c]);e&&void 0===this.schemas[e]&&void 0===this.missingMap[e]&&(this.missingMap[e]=e)}}},i.prototype.addSchema=function(a,b){if("string"!=typeof a||"undefined"==typeof b){if("object"!=typeof a||"string"!=typeof a.id)return;b=a,a=b.id}a===d(a)+"#"&&(a=d(a)),this.schemas[a]=b,delete this.missingMap[a],e(b,a),this.searchSchemas(b,a)},i.prototype.getSchemaMap=function(){var a={};for(var b in this.schemas)a[b]=this.schemas[b];return a},i.prototype.getSchemaUris=function(a){var b=[];for(var c in this.schemas)(!a||a.test(c))&&b.push(c);return b},i.prototype.getMissingUris=function(a){var b=[];for(var c in this.missingMap)(!a||a.test(c))&&b.push(c);return b},i.prototype.dropSchemas=function(){this.schemas={},this.reset()},i.prototype.reset=function(){this.missing=[],this.missingMap={},this.errors=[]},i.prototype.validateAll=function(a,b,c,d,e){var g;if(b=this.resolveRefs(b),!b)return null;if(b instanceof f)return this.errors.push(b),b;var h,i=this.errors.length,j=null,k=null;if(this.checkRecursive&&a&&"object"==typeof a){if(g=!this.scanned.length,a[this.validatedSchemasKey]){var l=a[this.validatedSchemasKey].indexOf(b);if(-1!==l)return this.errors=this.errors.concat(a[this.validationErrorsKey][l]),null}if(Object.isFrozen(a)&&(h=this.scannedFrozen.indexOf(a),-1!==h)){var m=this.scannedFrozenSchemas[h].indexOf(b);if(-1!==m)return this.errors=this.errors.concat(this.scannedFrozenValidationErrors[h][m]),null}if(this.scanned.push(a),Object.isFrozen(a))-1===h&&(h=this.scannedFrozen.length,this.scannedFrozen.push(a),this.scannedFrozenSchemas.push([])),j=this.scannedFrozenSchemas[h].length,this.scannedFrozenSchemas[h][j]=b,this.scannedFrozenValidationErrors[h][j]=[];else{if(!a[this.validatedSchemasKey])try{Object.defineProperty(a,this.validatedSchemasKey,{value:[],configurable:!0}),Object.defineProperty(a,this.validationErrorsKey,{value:[],configurable:!0})}catch(n){a[this.validatedSchemasKey]=[],a[this.validationErrorsKey]=[]}k=a[this.validatedSchemasKey].length,a[this.validatedSchemasKey][k]=b,a[this.validationErrorsKey][k]=[]}}var o=this.errors.length,p=this.validateBasic(a,b,e)||this.validateNumeric(a,b,e)||this.validateString(a,b,e)||this.validateArray(a,b,e)||this.validateObject(a,b,e)||this.validateCombinations(a,b,e)||this.validateFormat(a,b,e)||this.validateDefinedKeywords(a,b,e)||null;if(g){for(;this.scanned.length;){var q=this.scanned.pop();delete q[this.validatedSchemasKey]}this.scannedFrozen=[],this.scannedFrozenSchemas=[]}if(p||o!==this.errors.length)for(;c&&c.length||d&&d.length;){var r=c&&c.length?""+c.pop():null,s=d&&d.length?""+d.pop():null;p&&(p=p.prefixWith(r,s)),this.prefixErrors(o,r,s)}return null!==j?this.scannedFrozenValidationErrors[h][j]=this.errors.slice(i):null!==k&&(a[this.validationErrorsKey][k]=this.errors.slice(i)),this.handleError(p)},i.prototype.validateFormat=function(a,b){if("string"!=typeof b.format||!this.formatValidators[b.format])return null;var c=this.formatValidators[b.format].call(null,a,b);return"string"==typeof c||"number"==typeof c?this.createError(j.FORMAT_CUSTOM,{message:c}).prefixWith(null,"format"):c&&"object"==typeof c?this.createError(j.FORMAT_CUSTOM,{message:c.message||"?"},c.dataPath||null,c.schemaPath||"/format"):null},i.prototype.validateDefinedKeywords=function(a,b){for(var c in this.definedKeywords)if("undefined"!=typeof b[c])for(var d=this.definedKeywords[c],e=0;e<d.length;e++){var f=d[e],g=f(a,b[c],b);if("string"==typeof g||"number"==typeof g)return this.createError(j.KEYWORD_CUSTOM,{key:c,message:g}).prefixWith(null,"format");if(g&&"object"==typeof g){var h=g.code||j.KEYWORD_CUSTOM;if("string"==typeof h){if(!j[h])throw new Error("Undefined error code (use defineError): "+h);h=j[h]}var i="object"==typeof g.message?g.message:{key:c,message:g.message||"?"},k=g.schemaPath||"/"+c.replace(/~/g,"~0").replace(/\//g,"~1");return this.createError(h,i,g.dataPath||null,k)}}return null},i.prototype.validateBasic=function(a,b,c){var d;return(d=this.validateType(a,b,c))?d.prefixWith(null,"type"):(d=this.validateEnum(a,b,c))?d.prefixWith(null,"type"):null},i.prototype.validateType=function(a,b){if(void 0===b.type)return null;var c=typeof a;null===a?c="null":Array.isArray(a)&&(c="array");var d=b.type;"object"!=typeof d&&(d=[d]);for(var e=0;e<d.length;e++){var f=d[e];if(f===c||"integer"===f&&"number"===c&&a%1===0)return null}return this.createError(j.INVALID_TYPE,{type:c,expected:d.join("/")})},i.prototype.validateEnum=function(b,c){if(void 0===c["enum"])return null;for(var d=0;d<c["enum"].length;d++){var e=c["enum"][d];if(a(b,e))return null}return this.createError(j.ENUM_MISMATCH,{value:"undefined"!=typeof JSON?JSON.stringify(b):b})},i.prototype.validateNumeric=function(a,b,c){return this.validateMultipleOf(a,b,c)||this.validateMinMax(a,b,c)||null},i.prototype.validateMultipleOf=function(a,b){var c=b.multipleOf||b.divisibleBy;return void 0===c?null:"number"==typeof a&&a%c!==0?this.createError(j.NUMBER_MULTIPLE_OF,{value:a,multipleOf:c}):null},i.prototype.validateMinMax=function(a,b){if("number"!=typeof a)return null;if(void 0!==b.minimum){if(a<b.minimum)return this.createError(j.NUMBER_MINIMUM,{value:a,minimum:b.minimum}).prefixWith(null,"minimum");if(b.exclusiveMinimum&&a===b.minimum)return this.createError(j.NUMBER_MINIMUM_EXCLUSIVE,{value:a,minimum:b.minimum}).prefixWith(null,"exclusiveMinimum")}if(void 0!==b.maximum){if(a>b.maximum)return this.createError(j.NUMBER_MAXIMUM,{value:a,maximum:b.maximum}).prefixWith(null,"maximum");if(b.exclusiveMaximum&&a===b.maximum)return this.createError(j.NUMBER_MAXIMUM_EXCLUSIVE,{value:a,maximum:b.maximum}).prefixWith(null,"exclusiveMaximum")}return null},i.prototype.validateString=function(a,b,c){return this.validateStringLength(a,b,c)||this.validateStringPattern(a,b,c)||null},i.prototype.validateStringLength=function(a,b){return"string"!=typeof a?null:void 0!==b.minLength&&a.length<b.minLength?this.createError(j.STRING_LENGTH_SHORT,{length:a.length,minimum:b.minLength}).prefixWith(null,"minLength"):void 0!==b.maxLength&&a.length>b.maxLength?this.createError(j.STRING_LENGTH_LONG,{length:a.length,maximum:b.maxLength}).prefixWith(null,"maxLength"):null},i.prototype.validateStringPattern=function(a,b){if("string"!=typeof a||void 0===b.pattern)return null;var c=new RegExp(b.pattern);return c.test(a)?null:this.createError(j.STRING_PATTERN,{pattern:b.pattern}).prefixWith(null,"pattern")},i.prototype.validateArray=function(a,b,c){return Array.isArray(a)?this.validateArrayLength(a,b,c)||this.validateArrayUniqueItems(a,b,c)||this.validateArrayItems(a,b,c)||null:null},i.prototype.validateArrayLength=function(a,b){var c;return void 0!==b.minItems&&a.length<b.minItems&&(c=this.createError(j.ARRAY_LENGTH_SHORT,{length:a.length,minimum:b.minItems}).prefixWith(null,"minItems"),this.handleError(c))?c:void 0!==b.maxItems&&a.length>b.maxItems&&(c=this.createError(j.ARRAY_LENGTH_LONG,{length:a.length,maximum:b.maxItems}).prefixWith(null,"maxItems"),this.handleError(c))?c:null},i.prototype.validateArrayUniqueItems=function(b,c){if(c.uniqueItems)for(var d=0;d<b.length;d++)for(var e=d+1;e<b.length;e++)if(a(b[d],b[e])){var f=this.createError(j.ARRAY_UNIQUE,{match1:d,match2:e}).prefixWith(null,"uniqueItems");if(this.handleError(f))return f}return null},i.prototype.validateArrayItems=function(a,b,c){if(void 0===b.items)return null;var d,e;if(Array.isArray(b.items)){for(e=0;e<a.length;e++)if(e<b.items.length){if(d=this.validateAll(a[e],b.items[e],[e],["items",e],c+"/"+e))return d}else if(void 0!==b.additionalItems)if("boolean"==typeof b.additionalItems){if(!b.additionalItems&&(d=this.createError(j.ARRAY_ADDITIONAL_ITEMS,{}).prefixWith(""+e,"additionalItems"),this.handleError(d)))return d}else if(d=this.validateAll(a[e],b.additionalItems,[e],["additionalItems"],c+"/"+e))return d}else for(e=0;e<a.length;e++)if(d=this.validateAll(a[e],b.items,[e],["items"],c+"/"+e))return d;return null},i.prototype.validateObject=function(a,b,c){return"object"!=typeof a||null===a||Array.isArray(a)?null:this.validateObjectMinMaxProperties(a,b,c)||this.validateObjectRequiredProperties(a,b,c)||this.validateObjectProperties(a,b,c)||this.validateObjectDependencies(a,b,c)||null},i.prototype.validateObjectMinMaxProperties=function(a,b){var c,d=Object.keys(a);return void 0!==b.minProperties&&d.length<b.minProperties&&(c=this.createError(j.OBJECT_PROPERTIES_MINIMUM,{propertyCount:d.length,minimum:b.minProperties}).prefixWith(null,"minProperties"),this.handleError(c))?c:void 0!==b.maxProperties&&d.length>b.maxProperties&&(c=this.createError(j.OBJECT_PROPERTIES_MAXIMUM,{propertyCount:d.length,maximum:b.maxProperties}).prefixWith(null,"maxProperties"),this.handleError(c))?c:null},i.prototype.validateObjectRequiredProperties=function(a,b){if(void 0!==b.required)for(var c=0;c<b.required.length;c++){var d=b.required[c];if(void 0===a[d]){var e=this.createError(j.OBJECT_REQUIRED,{key:d}).prefixWith(null,""+c).prefixWith(null,"required");if(this.handleError(e))return e}}return null},i.prototype.validateObjectProperties=function(a,b,c){var d;for(var e in a){var f=c+"/"+e.replace(/~/g,"~0").replace(/\//g,"~1"),g=!1;if(void 0!==b.properties&&void 0!==b.properties[e]&&(g=!0,d=this.validateAll(a[e],b.properties[e],[e],["properties",e],f)))return d;if(void 0!==b.patternProperties)for(var h in b.patternProperties){var i=new RegExp(h);if(i.test(e)&&(g=!0,d=this.validateAll(a[e],b.patternProperties[h],[e],["patternProperties",h],f)))return d}if(g)this.trackUnknownProperties&&(this.knownPropertyPaths[f]=!0,delete this.unknownPropertyPaths[f]);else if(void 0!==b.additionalProperties){if(this.trackUnknownProperties&&(this.knownPropertyPaths[f]=!0,delete this.unknownPropertyPaths[f]),"boolean"==typeof b.additionalProperties){if(!b.additionalProperties&&(d=this.createError(j.OBJECT_ADDITIONAL_PROPERTIES,{}).prefixWith(e,"additionalProperties"),this.handleError(d)))return d}else if(d=this.validateAll(a[e],b.additionalProperties,[e],["additionalProperties"],f))return d}else this.trackUnknownProperties&&!this.knownPropertyPaths[f]&&(this.unknownPropertyPaths[f]=!0)}return null},i.prototype.validateObjectDependencies=function(a,b,c){var d;if(void 0!==b.dependencies)for(var e in b.dependencies)if(void 0!==a[e]){var f=b.dependencies[e];if("string"==typeof f){if(void 0===a[f]&&(d=this.createError(j.OBJECT_DEPENDENCY_KEY,{key:e,missing:f}).prefixWith(null,e).prefixWith(null,"dependencies"),this.handleError(d)))return d}else if(Array.isArray(f))for(var g=0;g<f.length;g++){var h=f[g];if(void 0===a[h]&&(d=this.createError(j.OBJECT_DEPENDENCY_KEY,{key:e,missing:h}).prefixWith(null,""+g).prefixWith(null,e).prefixWith(null,"dependencies"),this.handleError(d)))return d}else if(d=this.validateAll(a,f,[],["dependencies",e],c))return d}return null},i.prototype.validateCombinations=function(a,b,c){return this.validateAllOf(a,b,c)||this.validateAnyOf(a,b,c)||this.validateOneOf(a,b,c)||this.validateNot(a,b,c)||null},i.prototype.validateAllOf=function(a,b,c){if(void 0===b.allOf)return null;for(var d,e=0;e<b.allOf.length;e++){var f=b.allOf[e];if(d=this.validateAll(a,f,[],["allOf",e],c))return d}return null},i.prototype.validateAnyOf=function(a,b,c){if(void 0===b.anyOf)return null;var d,e,f=[],g=this.errors.length;this.trackUnknownProperties&&(d=this.unknownPropertyPaths,e=this.knownPropertyPaths);for(var h=!0,i=0;i<b.anyOf.length;i++){this.trackUnknownProperties&&(this.unknownPropertyPaths={},this.knownPropertyPaths={});var k=b.anyOf[i],l=this.errors.length,m=this.validateAll(a,k,[],["anyOf",i],c);if(null===m&&l===this.errors.length){if(this.errors=this.errors.slice(0,g),this.trackUnknownProperties){for(var n in this.knownPropertyPaths)e[n]=!0,delete d[n];for(var o in this.unknownPropertyPaths)e[o]||(d[o]=!0);h=!1;continue}return null}m&&f.push(m.prefixWith(null,""+i).prefixWith(null,"anyOf"))}return this.trackUnknownProperties&&(this.unknownPropertyPaths=d,this.knownPropertyPaths=e),h?(f=f.concat(this.errors.slice(g)),this.errors=this.errors.slice(0,g),this.createError(j.ANY_OF_MISSING,{},"","/anyOf",f)):void 0},i.prototype.validateOneOf=function(a,b,c){if(void 0===b.oneOf)return null;var d,e,f=null,g=[],h=this.errors.length;this.trackUnknownProperties&&(d=this.unknownPropertyPaths,e=this.knownPropertyPaths);for(var i=0;i<b.oneOf.length;i++){this.trackUnknownProperties&&(this.unknownPropertyPaths={},this.knownPropertyPaths={});var k=b.oneOf[i],l=this.errors.length,m=this.validateAll(a,k,[],["oneOf",i],c);if(null===m&&l===this.errors.length){if(null!==f)return this.errors=this.errors.slice(0,h),this.createError(j.ONE_OF_MULTIPLE,{index1:f,index2:i},"","/oneOf");if(f=i,this.trackUnknownProperties){for(var n in this.knownPropertyPaths)e[n]=!0,delete d[n];for(var o in this.unknownPropertyPaths)e[o]||(d[o]=!0)}}else m&&g.push(m.prefixWith(null,""+i).prefixWith(null,"oneOf"))}return this.trackUnknownProperties&&(this.unknownPropertyPaths=d,this.knownPropertyPaths=e),null===f?(g=g.concat(this.errors.slice(h)),this.errors=this.errors.slice(0,h),this.createError(j.ONE_OF_MISSING,{},"","/oneOf",g)):(this.errors=this.errors.slice(0,h),null)},i.prototype.validateNot=function(a,b,c){if(void 0===b.not)return null;var d,e,f=this.errors.length;this.trackUnknownProperties&&(d=this.unknownPropertyPaths,e=this.knownPropertyPaths,this.unknownPropertyPaths={},this.knownPropertyPaths={});var g=this.validateAll(a,b.not,null,null,c),h=this.errors.slice(f);return this.errors=this.errors.slice(0,f),this.trackUnknownProperties&&(this.unknownPropertyPaths=d,this.knownPropertyPaths=e),null===g&&0===h.length?this.createError(j.NOT_PASSED,{},"","/not"):null};var j={INVALID_TYPE:0,ENUM_MISMATCH:1,ANY_OF_MISSING:10,ONE_OF_MISSING:11,ONE_OF_MULTIPLE:12,NOT_PASSED:13,NUMBER_MULTIPLE_OF:100,NUMBER_MINIMUM:101,NUMBER_MINIMUM_EXCLUSIVE:102,NUMBER_MAXIMUM:103,NUMBER_MAXIMUM_EXCLUSIVE:104,STRING_LENGTH_SHORT:200,STRING_LENGTH_LONG:201,STRING_PATTERN:202,OBJECT_PROPERTIES_MINIMUM:300,OBJECT_PROPERTIES_MAXIMUM:301,OBJECT_REQUIRED:302,OBJECT_ADDITIONAL_PROPERTIES:303,OBJECT_DEPENDENCY_KEY:304,ARRAY_LENGTH_SHORT:400,ARRAY_LENGTH_LONG:401,ARRAY_UNIQUE:402,ARRAY_ADDITIONAL_ITEMS:403,FORMAT_CUSTOM:500,KEYWORD_CUSTOM:501,CIRCULAR_REFERENCE:600,UNKNOWN_PROPERTY:1e3},k={};for(var l in j)k[j[l]]=l;var m={INVALID_TYPE:"invalid type: {type} (expected {expected})",ENUM_MISMATCH:"No enum match for: {value}",ANY_OF_MISSING:'Data does not match any schemas from "anyOf"',ONE_OF_MISSING:'Data does not match any schemas from "oneOf"',ONE_OF_MULTIPLE:'Data is valid against more than one schema from "oneOf": indices {index1} and {index2}',NOT_PASSED:'Data matches schema from "not"',NUMBER_MULTIPLE_OF:"Value {value} is not a multiple of {multipleOf}",NUMBER_MINIMUM:"Value {value} is less than minimum {minimum}",NUMBER_MINIMUM_EXCLUSIVE:"Value {value} is equal to exclusive minimum {minimum}",NUMBER_MAXIMUM:"Value {value} is greater than maximum {maximum}",NUMBER_MAXIMUM_EXCLUSIVE:"Value {value} is equal to exclusive maximum {maximum}",STRING_LENGTH_SHORT:"String is too short ({length} chars), minimum {minimum}",STRING_LENGTH_LONG:"String is too long ({length} chars), maximum {maximum}",STRING_PATTERN:"String does not match pattern: {pattern}",OBJECT_PROPERTIES_MINIMUM:"Too few properties defined ({propertyCount}), minimum {minimum}",OBJECT_PROPERTIES_MAXIMUM:"Too many properties defined ({propertyCount}), maximum {maximum}",OBJECT_REQUIRED:"Missing required property: {key}",OBJECT_ADDITIONAL_PROPERTIES:"Additional properties not allowed",OBJECT_DEPENDENCY_KEY:"Dependency failed - key must exist: {missing} (due to key: {key})",ARRAY_LENGTH_SHORT:"Array is too short ({length}), minimum {minimum}",ARRAY_LENGTH_LONG:"Array is too long ({length}), maximum {maximum}",ARRAY_UNIQUE:"Array items are not unique (indices {match1} and {match2})",ARRAY_ADDITIONAL_ITEMS:"Additional items not allowed",FORMAT_CUSTOM:"Format validation failed ({message})",KEYWORD_CUSTOM:"Keyword failed: {key} ({message})",CIRCULAR_REFERENCE:"Circular $refs: {urls}",UNKNOWN_PROPERTY:"Unknown property (not in schema)"};f.prototype=Object.create(Error.prototype),f.prototype.constructor=f,f.prototype.name="ValidationError",f.prototype.prefixWith=function(a,b){if(null!==a&&(a=a.replace(/~/g,"~0").replace(/\//g,"~1"),this.dataPath="/"+a+this.dataPath),null!==b&&(b=b.replace(/~/g,"~0").replace(/\//g,"~1"),this.schemaPath="/"+b+this.schemaPath),null!==this.subErrors)for(var c=0;c<this.subErrors.length;c++)this.subErrors[c].prefixWith(a,b);return this};var n={},o=h();return o.addLanguage("en-gb",m),o.tv4=o,o});
670//# sourceMappingURL=tv4.min.js.map
671/* jshint ignore:end */
672
673window.plugin.arcs.list.addJSONdata = function() {
674 var arc_list = JSON.parse(localStorage.getItem('arc_list' ));
675 array2 = JSON.parse(String(document.getElementById("JSONstring").value));
676 //check that import is all good here
677 /* jshint ignore:start */
678 schema={"type":"array","items":{"type":"object","properties":{"startPortal":{"type":"object","required":true,"properties":{"title":{"type":"string"},"lat":{"type":"number"},"lon":{"type":"number"},"guid":{"type":"string"}},"required":["title","lat","lon","guid"]},"endPortal":{"type":"object","required":true,"properties":{"title":{"type":"string"},"lat":{"type":"number"},"lon":{"type":"number"},"guid":{"type":"string"}},"required":["title","lat","lon","guid"]},"distance":{"type":"number"}},"required":["startPortal","endPortal","distance"]}};
679 /* jshint ignore:end */
680 if (tv4.validate(array2,schema))
681 {
682 var arc_list = arc_list.concat(array2);
683 localStorage.setItem( 'arc_list', JSON.stringify(arc_list) );
684 for (var i=0;i<array2.length;i++)
685 {
686 var link = array2[i];
687 var startCoord = new window.plugin.arcs.arc.Coord(link.startPortal.lon, link.startPortal.lat);
688 var stopCoord = new window.plugin.arcs.arc.Coord(link.endPortal.lon, link.endPortal.lat);
689 window.plugin.arcs.create(startCoord, stopCoord, link);
690 }
691 window.plugin.arcs.list();
692 }
693 else
694 {
695 alert ('Data is corrupt');
696 }
697};
698
699window.plugin.arcs.changeColor = function(color) {
700 if (color==='')
701 {
702 color = String(document.getElementById("colorString").value);
703 console.log(color);
704 }
705 console.log(color);
706 if (!/^#[0-9A-F]{6}$/i.test(color))
707 {
708 alert('Invalid colour.');
709 return;
710 }
711 arcColor=color;
712 document.getElementById("colorString").value = color;
713 document.getElementById("colorString").style.color = color;
714};
715
716//Need a start end variable for this
717var linkEnd = 'start';
718var arcColor = '#ff0000';
719
720window.plugin.arcs.draw = function() {
721 //console.log('test');
722 if (window.selectedPortal === null)
723 {
724 $('#ArcError1').fadeIn(400).delay(400).fadeOut(400);
725 return;
726 }
727 var el = document.getElementById("arcButton");
728 var button = document.getElementById("leftarcbutton");
729
730 //Lets do some more. Store portal lat,long, name address and guid.
731 var portal = {};
732 //var portal_full = window.portals[window.selectedPortal];
733
734 var guid = window.selectedPortal;
735 var p = window.portals[guid];
736 var d = p.options.data;
737 var label = d.title;
738 var lat = p.getLatLng().lat;
739 var lng = p.getLatLng().lng;
740 var details = portalDetail.get(guid);
741
742 portal.title = label;
743 //portal.address = details.descriptiveText.map.ADDRESS;
744 portal.lat = lat;
745 portal.lon = lng;
746 portal.guid = guid;
747
748 //if things were not loaded yet stop
749 console.log(portal.title);
750 if (!label)
751 {
752 console.log('Portal data not loaded');
753 $('#ArcError1').fadeIn(400).delay(400).fadeOut(400);
754 return;
755 }
756
757 if (linkEnd == 'start') {
758 window.plugin.arcs.startPortal = portal;
759 el.title='End arc at this portal';
760 el.innerHTML='End arc';
761 window.plugin.arcs.startCoord = new window.plugin.arcs.arc.Coord(portal.lon, portal.lat);
762 linkEnd = 'stop';
763 button.style.background = 'red';
764 }
765 else{
766 endPortal = portal;
767 window.plugin.arcs.link = {};
768 window.plugin.arcs.link.startPortal = window.plugin.arcs.startPortal;
769 window.plugin.arcs.link.endPortal = endPortal;
770 window.plugin.arcs.link.distance = window.plugin.arcs.distance(window.plugin.arcs.link);
771
772 //set the color
773 window.plugin.arcs.link.color = arcColor;
774
775
776 el.title='Start an arc from this portal';
777 el.innerHTML='Start arc';
778 linkEnd = 'start';
779 button.style.background = 'white';
780
781 //If it was a 0 distance. DO NOT MAKE
782 if (window.plugin.arcs.link.distance === 0)
783 {
784 //Nope!
785 $('#ArcError2').fadeIn(400).delay(1000).fadeOut(400);
786 }
787 else
788 {
789 var stopCoord = new window.plugin.arcs.arc.Coord(endPortal.lon, endPortal.lat);
790 window.plugin.arcs.create(window.plugin.arcs.startCoord, stopCoord, window.plugin.arcs.link);
791 //add to local storage
792 var arc_list = JSON.parse(localStorage.getItem('arc_list' ));
793 //console.log(arc_list);
794 arc_list.push(window.plugin.arcs.link);
795 localStorage.setItem( 'arc_list', JSON.stringify(arc_list) );
796 //window.alert("Link Distance: "+window.plugin.arcs.link.distance+"km");
797 }
798 }
799};
800
801
802
803//auto draw
804window.plugin.arcs.dialogDrawer = function() {
805 dialog({
806 html:window.plugin.arcs.dialogLoadList,
807 dialogClass:'ui-dialog-autodrawer',
808 title:'Bookmarks - Arcs Auto Draw',
809 id: 'arcs-dialog-window',
810 buttons:{
811 'DRAW': function() {
812 window.plugin.arcs.adraw(0);
813 }
814 }
815 });
816 window.plugin.arcs.arcautoDrawOnSelect();
817};
818
819window.plugin.arcs.adraw = function(view) {
820 var label = [];
821 var latlngs = [];
822 var guid = [];
823 $('#bkmrksAutoDrawer a.bkmrk.selected').each(function(i) {
824 label[i] = $(this).text();
825 latlngs[i] = $(this).data('latlng');
826 guid[i] = $(this).data('guid');
827 });
828
829
830 if(latlngs.length >= 2 && latlngs.length <= 3)
831 {
832 if(latlngs.length == 3) {
833 window.plugin.arcs.draw_line(0,1,label,latlngs,guid);
834 window.plugin.arcs.draw_line(0,2,label,latlngs,guid);
835 window.plugin.arcs.draw_line(1,2,label,latlngs,guid);
836 }
837 else if(latlngs.length == 2) {
838 window.plugin.arcs.draw_line(0,1,label,latlngs,guid);
839 }
840 if($('#bkmrkClearSelection').prop('checked'))
841 {
842 $('#bkmrksAutoDrawer a.bkmrk.selected').removeClass('selected');
843 }
844 }
845};
846
847window.plugin.arcs.draw_line = function(i,j,label,latlngs,guid) {
848 //draw one line
849 window.plugin.arcs.link = {};
850 window.plugin.arcs.link.startPortal = {};
851 window.plugin.arcs.link.endPortal = {};
852 window.plugin.arcs.link.startPortal.title = label[i];
853 window.plugin.arcs.link.startPortal.lat = latlngs[i][0];
854 window.plugin.arcs.link.startPortal.lon = latlngs[i][1];
855 window.plugin.arcs.link.startPortal.guid = guid[i];
856 window.plugin.arcs.link.endPortal.title = label[j];
857 window.plugin.arcs.link.endPortal.lat = latlngs[j][0];
858 window.plugin.arcs.link.endPortal.lon = latlngs[j][1];
859 window.plugin.arcs.link.endPortal.guid = guid[j];
860 window.plugin.arcs.link.color = arcColor;
861 window.plugin.arcs.link.distance = window.plugin.arcs.distance(window.plugin.arcs.link);
862
863 //add to local storage
864 var arc_list = JSON.parse(localStorage.getItem('arc_list' ));
865 //console.log(arc_list);
866 //console.log(window.plugin.arcs.link);
867
868 var arcExists=false;
869 for (i=0;i<arc_list.length;i++)
870 {
871 if (window.plugin.arcs.link.startPortal.guid==arc_list[i].startPortal.guid && window.plugin.arcs.link.endPortal.guid==arc_list[i].endPortal.guid)
872 { arcExists = true;}
873 if (window.plugin.arcs.link.startPortal.guid==arc_list[i].endPortal.guid && window.plugin.arcs.link.endPortal.guid==arc_list[i].startPortal.guid)
874 { arcExists = true;}
875 }
876 //check if link already exists
877 if(!arcExists)
878 {
879 arc_list.push(window.plugin.arcs.link);
880 localStorage.setItem( 'arc_list', JSON.stringify(arc_list) );
881 //add to map
882 var startCoord = new window.plugin.arcs.arc.Coord(window.plugin.arcs.link.startPortal.lon, window.plugin.arcs.link.startPortal.lat);
883 var stopCoord = new window.plugin.arcs.arc.Coord(window.plugin.arcs.link.endPortal.lon, window.plugin.arcs.link.endPortal.lat);
884 window.plugin.arcs.create(startCoord, stopCoord, window.plugin.arcs.link);
885 }
886 window.plugin.arcs.arcautoDrawOnSelect();
887};
888
889window.plugin.arcs.arcautoDrawOnSelect = function() {
890 var numberSelected = 0;
891 var uuu = $('#bkmrksAutoDrawer a.bkmrk.selected').each(function(i) {
892 numberSelected++;
893 });
894 var text = "You must select 2 or 3 portals!";
895 var color = "red";
896
897 if(numberSelected == 2) {
898 text = 'Draw single Arc';
899 color = "";
900 } else if(numberSelected == 3) {
901 text = 'Draw three Arcs';
902 color = "";
903 }
904
905 $('#bkmrksAutoDrawer p')
906 .html(text)
907 .css("color", color);
908};
909
910window.plugin.arcs.filterDraw = function() {
911 // Declare variables
912 var input, filter, ul, li, a, i, portalbookmarks, folders;
913 input = document.getElementById('arcFilterDrawInput');
914 filter = input.value.toUpperCase();
915 portalbookmarks = $("a.bkmrk");
916 $("div.bookmarkFolder>div").show();
917 for (i = 0; i < portalbookmarks.length; i++) {
918 if (portalbookmarks[i].innerHTML.toUpperCase().indexOf(filter) > -1) {
919 portalbookmarks[i].style.display = "";
920 // portalbookmarks[i].hidden = "false";
921 } else {
922 portalbookmarks[i].style.display = "none";
923 // portalbookmarks[i].hidden = "true";
924 }
925 }
926 $("a.bkmrk.selected").show();
927 folders = $("div.bookmarkFolder");
928 for (i = 0; i < folders.length; i++) {
929 if (folders[i].innerHTML.toUpperCase().indexOf(filter) > -1) {
930 folders[i].style.display = "";
931 // portalbookmarks[i].hidden = "false";
932 } else {
933 folders[i].style.display = "none";
934 // portalbookmarks[i].hidden = "true";
935 }
936 }
937 $("div.bookmarkFolder a.bkmrk.selected").show();
938};
939
940window.plugin.arcs.dialogLoadList = function() {
941 var r = 'The "<a href="https://static.iitc.me/build/release/plugins/bookmarks-by-zaso.user.js" target="_BLANK"><strong>Bookmarks</strong></a>" plugin is required.</span>';
942
943 if(!window.plugin.bookmarks) {
944 $('.ui-dialog-autodrawer .ui-dialog-buttonset .ui-button:not(:first)').hide();
945 }
946 else
947 {
948 var portalsList = JSON.parse(localStorage[window.plugin.bookmarks.KEY_STORAGE]);
949 var element = '';
950 var elementTemp = '';
951 var elemGenericFolder = '';
952
953 // For each folder
954 var list = portalsList.portals;
955 for(var idFolders in list) {
956 var folders = list[idFolders];
957
958 // Create a label and a anchor for the sortable
959 var folderLabel = '<a class="folderLabel" onclick="$(this).siblings(\'div\').toggle();return false;">'+folders.label+'</a>';
960
961 // Create a folder
962 elementTemp = '<div class="bookmarkFolder" id="'+idFolders+'">'+folderLabel+'<div>';
963
964 // For each bookmark
965 var fold = folders.bkmrk;
966 for(var idBkmrk in fold) {
967 var bkmrk = fold[idBkmrk];
968 var label = bkmrk.label;
969 var latlng = bkmrk.latlng;
970 var guid = bkmrk.guid;
971
972 // Create the bookmark
973 elementTemp += '<a class="bkmrk" id="'+idBkmrk+'" onclick="$(this).toggleClass(\'selected\');return false" data-label="'+label+'" data-latlng="['+latlng+']" data-guid="'+guid+'">'+label+'</a>';
974 }
975 elementTemp += '</div></div>';
976
977 if(idFolders !== window.plugin.bookmarks.KEY_OTHER_BKMRK) {
978 element += elementTemp;
979 } else {
980 elemGenericFolder += elementTemp;
981 }
982 }
983 element += elemGenericFolder;
984 // Append all folders and bookmarks
985 r = '<div id="bkmrksAutoDrawer">'+
986 '<label style="margin-bottom: 9px; display: block;">'+
987 '<input style="vertical-align: middle;" type="checkbox" id="bkmrkClearSelection" checked>'+
988 ' Clear selection after drawing</label>'+
989 '<p style="margin-bottom:9px;color:red;display: block;">You must select 2 or 3 portals!</p>'+
990 '<label for="arcFilterDrawInput" style="margin-top: 5px; position:relative; display:inline-block; font-weight:bold;">Filter portals by name:</label><br />'+
991 '<input type="text" id="arcFilterDrawInput" onkeyup="window.plugin.arcs.filterDraw()" placeholder="Portalname" style="margin-top:3px; margin-bottom:5px; border: 1px solid #20a8b1;">'+
992 '<div onclick="window.plugin.arcs.arcautoDrawOnSelect();return false;">'+element+'</div></div>';
993 }
994 return r;
995};
996
997////////////////////////////////// Cross links ///////////////////////////////////////
998window.plugin.arcs.greatCircleArcIntersect = function(ta0,ta1,tb0,tb1) {
999 // based on the formula at http://williams.best.vwh.net/avform.htm#Int
1000
1001 // method:
1002 // check to ensure no line segment is zero length - if so, cannot cross
1003 // check to see if either of the lines start/end at the same point. if so, then they cannot cross
1004 // check to see if the line segments overlap in longitude. if not, no crossing
1005 // if overlap, clip each line to the overlapping longitudes, then see if latitudes cross
1006
1007 // anti-meridian handling. this code will not sensibly handle a case where one point is
1008 // close to -180 degrees and the other +180 degrees. unwrap coordinates in this case, so one point
1009 // is beyond +-180 degrees. this is already true in IITC
1010 // FIXME? if the two lines have been 'unwrapped' differently - one positive, one negative - it will fail
1011
1012 //Dimand: Lets fix the date line issue.
1013 //always work in the eastern hemisphere. so += 360
1014
1015 //fuck this object scope
1016
1017 a0={};
1018 a1={};
1019 b0={};
1020 b1={};
1021 a0.lng=ta0.lng;
1022 a0.lat=ta0.lat;
1023 a1.lng=ta1.lng;
1024 a1.lat=ta1.lat;
1025 b0.lng=tb0.lng;
1026 b0.lat=tb0.lat;
1027 b1.lng=tb1.lng;
1028 b1.lat=tb1.lat;
1029 //debugger;
1030 // zero length line tests
1031 if ((a0.lat==a1.lat)&&(a0.lng==a1.lng)) return false;
1032 if ((b0.lat==b1.lat)&&(b0.lng==b1.lng)) return false;
1033
1034 // lines have a common point
1035 if ((a0.lat==b0.lat)&&(a0.lng==b0.lng)) return false;
1036 if ((a0.lat==b1.lat)&&(a0.lng==b1.lng)) return false;
1037 if ((a1.lat==b0.lat)&&(a1.lng==b0.lng)) return false;
1038 if ((a1.lat==b1.lat)&&(a1.lng==b1.lng)) return false;
1039
1040 // a0.lng<=-90 && a1.lng>=90 dosent suffice... a link from -70 to 179 still crosses
1041 //if a0.lng-a1.lng >180 or <-180 there is a cross!
1042 var aCross = false;
1043 var bCross = false;
1044 //this is the real link
1045 if ((a0.lng-a1.lng)<-180 ||(a0.lng-a1.lng)>180)
1046 { //we have a dateline cross
1047 //console.log('DateLine Cross!');
1048 //move everything in the eastern hemisphere to the extended eastern one
1049 aCross = true;
1050 if (a0.lng <0)
1051 {
1052 a0.lng += 360;
1053 }
1054 if (a1.lng <0)
1055 {
1056 a1.lng += 360;
1057 }
1058 }
1059 //this is the arc
1060 if ((b0.lng-b1.lng)<-180 ||(b0.lng-b1.lng)>180)
1061 {
1062 //console.log('DateLine Cross!');
1063 bCross=true;
1064 if (b0.lng <0)
1065 {
1066 b0.lng += 360;
1067 }
1068 if (b1.lng <0)
1069 {
1070 b1.lng += 360;
1071 }
1072 }
1073 //now corrected both a and b for date line crosses.
1074 //now if link is entirely in the west we need to move it to the east.
1075 if (bCross && aCross)
1076 {
1077 //both got moved. all should be good.
1078 //do nothing
1079 }
1080 else if (aCross)
1081 {
1082 //now we need to move any links in the west of the main one
1083 if (Math.max(b0.lng,b1.lng)<Math.min(a0.lng,a1.lng))
1084 {
1085 //console.log('arc shift');
1086 b0.lng += 360;
1087 b1.lng += 360;
1088 }
1089 }
1090 else if (bCross)
1091 {
1092 //now we need to move any links in the west of the main one
1093 if (Math.max(a0.lng,a1.lng)<Math.min(b0.lng,b1.lng))
1094 {
1095 //console.log('link shift');
1096 a0.lng += 360;
1097 a1.lng += 360;
1098 //console.log(a0);
1099 //console.log(a1);
1100 //console.log(b0);
1101 //console.log(b1);
1102 }
1103 }
1104
1105 // check for 'horizontal' overlap in longitude
1106 if (Math.min(a0.lng,a1.lng) > Math.max(b0.lng,b1.lng)) return false;
1107 if (Math.max(a0.lng,a1.lng) < Math.min(b0.lng,b1.lng)) return false;
1108
1109 // ok, our two lines have some horizontal overlap in longitude
1110 // 1. calculate the overlapping min/max longitude
1111 // 2. calculate each line latitude at each point
1112 // 3. if latitudes change place between overlapping range, the lines cross
1113
1114 // class to hold the pre-calculated maths for a geodesic line
1115 // TODO: move this outside this function, so it can be pre-calculated once for each line we test
1116 var GeodesicLine = function(start,end) {
1117 var d2r = Math.PI/180.0;
1118 var r2d = 180.0/Math.PI;
1119
1120 // maths based on http://williams.best.vwh.net/avform.htm#Int
1121
1122 if (start.lng == end.lng) {
1123 throw 'Error: cannot calculate latitude for meridians';
1124 }
1125
1126 // only the variables needed to calculate a latitude for a given longitude are stored in 'this'
1127 this.lat1 = start.lat * d2r;
1128 this.lat2 = end.lat * d2r;
1129 this.lng1 = start.lng * d2r;
1130 this.lng2 = end.lng * d2r;
1131
1132 var dLng = this.lng1-this.lng2;
1133
1134 var sinLat1 = Math.sin(this.lat1);
1135 var sinLat2 = Math.sin(this.lat2);
1136 var cosLat1 = Math.cos(this.lat1);
1137 var cosLat2 = Math.cos(this.lat2);
1138
1139 this.sinLat1CosLat2 = sinLat1*cosLat2;
1140 this.sinLat2CosLat1 = sinLat2*cosLat1;
1141
1142 this.cosLat1CosLat2SinDLng = cosLat1*cosLat2*Math.sin(dLng);
1143 };
1144
1145 GeodesicLine.prototype.isMeridian = function() {
1146 return this.lng1 == this.lng2;
1147 };
1148
1149 GeodesicLine.prototype.latAtLng = function(lng) {
1150 lng = lng * Math.PI / 180; //to radians
1151
1152 var lat;
1153 // if we're testing the start/end point, return that directly rather than calculating
1154 // 1. this may be fractionally faster, no complex maths
1155 // 2. there's odd rounding issues that occur on some browsers (noticed on IITC MObile) for very short links - this may help
1156 if (lng == this.lng1) {
1157 lat = this.lat1;
1158 } else if (lng == this.lng2) {
1159 lat = this.lat2;
1160 } else {
1161 lat = Math.atan ( (this.sinLat1CosLat2*Math.sin(lng-this.lng2) - this.sinLat2CosLat1*Math.sin(lng-this.lng1))/this.cosLat1CosLat2SinDLng);
1162 }
1163 return lat * 180 / Math.PI; // return value in degrees
1164 };
1165
1166
1167
1168 // calculate the longitude of the overlapping region
1169 var leftLng = Math.max( Math.min(a0.lng,a1.lng), Math.min(b0.lng,b1.lng) );
1170 var rightLng = Math.min( Math.max(a0.lng,a1.lng), Math.max(b0.lng,b1.lng) );
1171 //console.log(leftLng);
1172 //console.log(rightLng);
1173
1174 // calculate the latitudes for each line at left + right longitudes
1175 // NOTE: need a special case for meridians - as GeodesicLine.latAtLng method is invalid in that case
1176 var aLeftLat, aRightLat;
1177 if (a0.lng == a1.lng) {
1178 // 'left' and 'right' now become 'top' and 'bottom' (in some order) - which is fine for the below intersection code
1179 aLeftLat = a0.lat;
1180 aRightLat = a1.lat;
1181 } else {
1182 var aGeo = new GeodesicLine(a0,a1);
1183 aLeftLat = aGeo.latAtLng(leftLng);
1184 aRightLat = aGeo.latAtLng(rightLng);
1185 }
1186
1187 var bLeftLat, bRightLat;
1188 if (b0.lng == b1.lng) {
1189 // 'left' and 'right' now become 'top' and 'bottom' (in some order) - which is fine for the below intersection code
1190 bLeftLat = b0.lat;
1191 bRightLat = b1.lat;
1192 } else {
1193 var bGeo = new GeodesicLine(b0,b1);
1194 bLeftLat = bGeo.latAtLng(leftLng);
1195 bRightLat = bGeo.latAtLng(rightLng);
1196 }
1197 //console.log(aLeftLat);
1198 //console.log(aRightLat);
1199 //console.log(bLeftLat);
1200 //console.log(bRightLat);
1201 // if both a are less or greater than both b, then lines do not cross
1202
1203 if (aLeftLat < bLeftLat && aRightLat < bRightLat) return false;
1204 if (aLeftLat > bLeftLat && aRightLat > bRightLat) return false;
1205
1206 // latitudes cross between left and right - so geodesic lines cross
1207 //console.log('Xlink!');
1208 return true;
1209};
1210
1211
1212
1213window.plugin.arcs.testPolyLine = function (arc, link) {
1214
1215 var a = link.getLatLngs();
1216 var start = {};
1217 var end = {};
1218 start.lat = arc.startPortal.lat;
1219 start.lng = arc.startPortal.lon;
1220 end.lat = arc.endPortal.lat;
1221 end.lng = arc.endPortal.lon;
1222
1223 if (window.plugin.arcs.greatCircleArcIntersect(a[0],a[1],start,end)) return true;
1224
1225 return false;
1226};
1227
1228
1229
1230window.plugin.arcs.checkAllLinks = function() {
1231 window.plugin.arcs.blockerCounterList = {};
1232 if (window.plugin.arcs.disabled) return;
1233
1234 console.debug("Cross-Links: checking all links");
1235 plugin.arcs.linkLayer.clearLayers();
1236 plugin.arcs.linkLayerGuids = {};
1237
1238 $.each(window.links, function(guid, link) {
1239 plugin.arcs.testLink(link);
1240 });
1241
1242 var iLinkCount = 0;
1243 var iPortalsCount = 0;
1244 var iEnlPortalsCount = 0;
1245 var portalCount = {};
1246 var portalList = {};
1247
1248 $
1249 .each(
1250 window.plugin.arcs.blockerCounterList,
1251 function(guid, link) {
1252 if (typeof link.options.guid != 'undefined') {
1253 details = links[link.options.guid];
1254
1255 // Portal 1
1256 if (typeof portalCount[details.options.data.dGuid] == 'undefined') {
1257 portalCount[details.options.data.dGuid] = 1;
1258 } else {
1259 portalCount[details.options.data.dGuid]++;
1260 }
1261
1262 // Portal 2
1263 if (typeof portalCount[details.options.data.oGuid] == 'undefined') {
1264 portalCount[details.options.data.oGuid] = 1;
1265 } else {
1266 portalCount[details.options.data.oGuid]++;
1267 }
1268
1269 iLinkCount++;
1270 }
1271 });
1272 $
1273 .each(
1274 window.plugin.arcs.blockerCounterList,
1275 function(guid, link) {
1276 if (typeof link.options.guid != 'undefined') {
1277 details = links[link.options.guid];
1278 portal1 = portals[details.options.data.dGuid];
1279 portal2 = portals[details.options.data.oGuid];
1280
1281 if (portalCount[details.options.data.dGuid] >= portalCount[details.options.data.oGuid]) {
1282 // Portal 1
1283 if (typeof portal1 != 'undefined') {
1284 portalList[details.options.data.dGuid] = portal1.options.data;
1285 } else {
1286 console.debug("Anchor not loaded: "+ details.options.data.dGuid+ ' (increase zoomlevel)');
1287 }
1288 } else {
1289 // Portal 2
1290 if (typeof portal2 != 'undefined') {
1291 portalList[details.options.data.oGuid] = portal2.options.data;
1292 } else {
1293 console.debug("Anchor not loaded: "+ details.options.data.oGuid+ ' (increase zoomlevel)');
1294 }
1295 }
1296 }
1297 });
1298
1299 $
1300 .each(
1301 portalList,
1302 function(guid, portal) {
1303 try {
1304 if (typeof portal != 'undefined') {
1305 anchorHtml = "";
1306
1307 if (portal.team == "E") {
1308 iEnlPortalsCount++;
1309 }
1310
1311 if (portal.team == "R") {
1312 iPortalsCount++;
1313 }
1314
1315 }
1316
1317 } catch (e) {
1318 console.debugger('error in Cross-Links-Counter->showLinkList: '+e);
1319 }
1320 });
1321 var msg = "Arcs Blockers - R: " + iPortalsCount + " E: " + iEnlPortalsCount;
1322 $('.plugin-arcs-crosslinks-stats').html(msg);
1323
1324
1325 ////// check for xlinks between arcs here. redraw all arcs on this procudure.//////////////////////
1326 // basical just go through the standard redraw but for each arc check that it doesn't cross another one else we draw them dotted.
1327 //refresh the layer group
1328 window.plugin.arcs.drawlayer.clearLayers();
1329 window.plugin.arcs.link_list = [];
1330
1331 var arc_list = JSON.parse(localStorage.getItem('arc_list' ));
1332 //cycle through and print them on load.
1333 for (var m=0;m<arc_list.length;m++)
1334 {
1335 var doesItCross=false;
1336 var link = arc_list[m];
1337
1338 var startCoord = new window.plugin.arcs.arc.Coord(link.startPortal.lon, link.startPortal.lat);
1339 var stopCoord = new window.plugin.arcs.arc.Coord(link.endPortal.lon, link.endPortal.lat);
1340
1341 var ta0={};
1342 var ta1={};
1343 var tb0={};
1344 var tb1={};
1345
1346 ta0.lng=link.startPortal.lon;
1347 ta0.lat=link.startPortal.lat;
1348 ta1.lng=link.endPortal.lon;
1349 ta1.lat=link.endPortal.lat;
1350
1351 for (var n=0;n<arc_list.length;n++)
1352 {
1353 var testlink = arc_list[n];
1354 tb0.lng=testlink.startPortal.lon;
1355 tb0.lat=testlink.startPortal.lat;
1356 tb1.lng=testlink.endPortal.lon;
1357 tb1.lat=testlink.endPortal.lat;
1358
1359 if (window.plugin.arcs.greatCircleArcIntersect(ta0,ta1,tb0,tb1))
1360 {
1361 doesItCross=true;
1362 }
1363 }
1364 //edit this function to have a xlink option
1365 window.plugin.arcs.create(startCoord, stopCoord, link, doesItCross);
1366 }
1367
1368
1369};
1370
1371window.plugin.arcs.testLink = function (link) {
1372 if (plugin.arcs.linkLayerGuids[link.options.guid]) return;
1373
1374 var arc_list = JSON.parse(localStorage.getItem('arc_list' ));
1375 for (i=0;i<arc_list.length;i++)
1376 {
1377 //console.log(link.getLatLngs());
1378 if (plugin.arcs.testPolyLine(arc_list[i], link,true))
1379 {
1380 window.plugin.arcs.blockerCounterList[link.options.guid] = link;
1381 //console.log(link.getLatLngs());
1382 plugin.arcs.showLink(link);
1383 // blocker recorder
1384 window.plugin.arcs.addBlocker(link.options.guid, link);
1385 }
1386 }
1387};
1388
1389
1390window.plugin.arcs.showLink = function(link) {
1391
1392 var poly = L.geodesicPolyline(link.getLatLngs(), {
1393 color: '#d22',
1394 opacity: 0.7,
1395 weight: 5,
1396 clickable: false,
1397 dashArray: [8,8],
1398
1399 guid: link.options.guid
1400 });
1401
1402 poly.addTo(plugin.arcs.linkLayer);
1403 plugin.arcs.linkLayerGuids[link.options.guid]=poly;
1404};
1405
1406
1407window.plugin.arcs.createLayer = function() {
1408 window.plugin.arcs.linkLayer = new L.FeatureGroup();
1409 window.plugin.arcs.linkLayerGuids={};
1410 window.addLayerGroup('Arc Cross Links', window.plugin.arcs.linkLayer, true);
1411
1412 map.on('layeradd', function(obj) {
1413 if(obj.layer === window.plugin.arcs.linkLayer) {
1414 delete window.plugin.arcs.disabled;
1415 window.plugin.arcs.checkAllLinks();
1416 $('.plugin-arcs-crosslinks-stats').show();
1417 }
1418 });
1419 map.on('layerremove', function(obj) {
1420 if(obj.layer === window.plugin.arcs.linkLayer) {
1421 window.plugin.arcs.disabled = true;
1422 window.plugin.arcs.linkLayer.clearLayers();
1423 plugin.arcs.linkLayerGuids = {};
1424 $('.plugin-arcs-crosslinks-stats').hide();
1425 }
1426 });
1427
1428 // ensure 'disabled' flag is initialised
1429 if (!map.hasLayer(window.plugin.arcs.linkLayer)) {
1430 window.plugin.arcs.disabled = true;
1431 }
1432};
1433
1434
1435/////////////////////// draw full great circle hack
1436//don't save these lines. just add one cord pair and write to the whole sphere
1437window.plugin.arcs.extend = function (lat1,lng1,lat2,lng2) {
1438 var R = 6367; // km
1439 var d2r = Math.PI/180.0;
1440 var r2d = 180.0/Math.PI;
1441
1442 lat1 = lat1 * d2r;
1443 lat2 = lat2 * d2r;
1444 lng1 = lng1 * d2r;
1445 lng2 = lng2 * d2r;
1446
1447 var sinLat1 = Math.sin(lat1);
1448 var sinLat2 = Math.sin(lat2);
1449 var cosLat1 = Math.cos(lat1);
1450 var cosLat2 = Math.cos(lat2);
1451 var sinDiff= Math.sin(lng1-lng2);
1452
1453 var coords = [];
1454
1455 for ( i = -100000; i <= 100000; i ++)
1456 {
1457 lng =(i/100000)*Math.PI;
1458 lat=Math.atan((sinLat1*cosLat2*Math.sin(lng-lng2)-sinLat2*cosLat1*Math.sin(lng-lng1))/(cosLat1*cosLat2*sinDiff));
1459 latd=lat*r2d;
1460 lngd=lng*r2d;
1461 //console.log(latd+','+lngd);
1462 coords.push([lngd,latd]);
1463 }
1464 //console.log(coords);
1465 //draws the link on the map
1466 var myStyle = {
1467 "color": arcColor,
1468 "weight": 3,
1469 "opacity": 0.7
1470 };
1471
1472 var geojson_feature ={"type":"LineString","coordinates":coords};
1473 //add to layer
1474 var line = new L.geoJson(geojson_feature,{style: myStyle}).addTo(window.plugin.arcs.drawlayer);
1475
1476 bindString='';
1477 bindString+='<div>';
1478 bindString+='<a id="arc_remove">Remove Arc</a></div>';
1479
1480 line.bindPopup(bindString);
1481 line.bringToBack();
1482 line.on('popupopen', function() { document.getElementById("arc_remove").onclick = function () {map.removeLayer(line);map.closePopup();} ;} );
1483 line.on('contextmenu', function() { map.removeLayer(line); } );
1484};
1485
1486window.plugin.arcs.clearBlockerList = function() { localStorage.removeItem('arc_blocker_list'); };
1487window.plugin.arcs.getBlockerList = function() { return JSON.parse(localStorage.getItem('arc_blocker_list') || '{}'); };
1488window.plugin.arcs.saveBlockerList = function(blockers) { localStorage.setItem('arc_blocker_list', JSON.stringify(blockers)); };
1489window.plugin.arcs.addBlocker = function(guid, link) {
1490 if (window.plugin.arcs.blockerRecording) {
1491 var blockers = window.plugin.arcs.getBlockerList();
1492 blockers[guid] = link.getLatLngs();
1493 window.plugin.arcs.saveBlockerList(blockers);
1494 }
1495};
1496window.plugin.arcs.deleteBlocker = function(guid) {
1497 var blockers = window.plugin.arcs.getBlockerList();
1498 delete blockers[guid];
1499 window.plugin.arcs.saveBlockerList(blockers);
1500};
1501window.plugin.arcs.showBlockerList = function() {
1502 var drawtools = [];
1503 var blockers = window.plugin.arcs.getBlockerList();
1504 var i;
1505 $.each(blockers,function(guid, latLngs) {
1506 console.log(i);
1507 drawtools.push({
1508 "type": "polyline",
1509 "latLngs": latLngs,
1510 "color": "#ee1111"
1511 });
1512 });
1513 dialog({
1514 html: '<div id="blockerdiag">Recorded blockers in draw-tools format.<br><textarea id="arcBlockerTextArea">' + JSON.stringify(drawtools) + '</textarea></div>',
1515 dialogClass: 'ui-dialog-portal',
1516 title: 'Recorded blockers',
1517 id: 'recorded-arc-blockers',
1518 buttons: {
1519 'Clear blockers': function() {
1520 window.plugin.arcs.clearBlockerList();
1521 $("#arcBlockerTextArea").text('[]');
1522 },
1523 'Keep recording': function() {
1524 window.plugin.arcs.crosslinkRecord();
1525 $(this).dialog('close');
1526 }
1527 }
1528 });
1529};
1530
1531window.plugin.arcs.crosslinkRecord = function() {
1532 if (window.plugin.arcs.blockerRecording) {
1533 window.plugin.arcs.blockerRecording = false;
1534 $('#recButton').text('Arc REC xlinks');
1535 window.plugin.arcs.showBlockerList();
1536 }
1537 else {
1538 window.plugin.arcs.blockerRecording = true;
1539 $('#recButton').text('Stop Recording');
1540 // Force a link check
1541 window.plugin.arcs.checkAllLinks();
1542 }
1543};
1544
1545////Anchor shift function
1546//this will move all arcs from one portal to another portal.
1547
1548var anchorEnd = 'start';
1549
1550
1551window.plugin.arcs.anchorShift = function() {
1552 //console.log('test');
1553 if (window.selectedPortal === null)
1554 {
1555 $('#ArcError1').fadeIn(400).delay(400).fadeOut(400);
1556 return;
1557 }
1558 var el = document.getElementById("anchorButton");
1559
1560 //Lets do some more. Store portal lat,long, name address and guid.
1561 var portal = {};
1562 //var portal_full = window.portals[window.selectedPortal];
1563
1564 var guid = window.selectedPortal;
1565 var p = window.portals[guid];
1566 var d = p.options.data;
1567 var label = d.title;
1568 var lat = p.getLatLng().lat;
1569 var lng = p.getLatLng().lng;
1570 var details = portalDetail.get(guid);
1571
1572 portal.title = label;
1573 //portal.address = details.descriptiveText.map.ADDRESS;
1574 portal.lat = lat;
1575 portal.lon = lng;
1576 portal.guid = guid;
1577
1578 //if things were not loaded yet stop
1579 console.log(portal.title);
1580 if (!label)
1581 {
1582 console.log('Portal data not loaded');
1583 $('#ArcError1').fadeIn(400).delay(400).fadeOut(400);
1584 return;
1585 }
1586
1587 if (anchorEnd == 'start') {
1588 window.plugin.arcs.startAnchorPortalGUID = portal.guid;
1589 el.innerHTML='Anchor Shift End';
1590 anchorEnd = 'stop';
1591 }
1592 else{
1593 //endPortal = portal;
1594 el.innerHTML='Anchor Shift Start';
1595 anchorEnd = 'start';
1596 //now we go through the arc list and find any arcs that went to the start anchor portal.
1597 var arc_list = JSON.parse(localStorage.getItem('arc_list' ));
1598 for (i=0;i<arc_list.length;i++)
1599 {
1600 checkArc=arc_list[i];
1601 if (checkArc.startPortal.guid===window.plugin.arcs.startAnchorPortalGUID)
1602 {
1603 //the start portal matches. Replace this with portal
1604 window.plugin.arcs.link = {};
1605 window.plugin.arcs.link.startPortal = portal;
1606 window.plugin.arcs.link.endPortal = checkArc.endPortal;
1607 window.plugin.arcs.link.distance = window.plugin.arcs.distance(window.plugin.arcs.link);
1608 //no color change
1609 window.plugin.arcs.link.color = checkArc.color;
1610 //If it was a 0 distance. DO NOT MAKE
1611 if (window.plugin.arcs.link.distance === 0)
1612 {
1613 //Nope! do nothing here
1614 //continue;
1615 }
1616 else
1617 {
1618 var stopCoord = new window.plugin.arcs.arc.Coord(window.plugin.arcs.link.endPortal.lon, window.plugin.arcs.link.endPortal.lat);
1619 var startCoord = new window.plugin.arcs.arc.Coord(window.plugin.arcs.link.startPortal.lon, window.plugin.arcs.link.startPortal.lat);
1620 window.plugin.arcs.create(startCoord, stopCoord, window.plugin.arcs.link);
1621 //add to local storage list
1622 arc_list[i] = window.plugin.arcs.link;
1623 }
1624
1625 }
1626 if (checkArc.endPortal.guid===window.plugin.arcs.startAnchorPortalGUID)
1627 {
1628 //the start portal matches. Replace this with portal
1629 window.plugin.arcs.link = {};
1630 window.plugin.arcs.link.endPortal = portal;
1631 window.plugin.arcs.link.startPortal = checkArc.startPortal;
1632 window.plugin.arcs.link.distance = window.plugin.arcs.distance(window.plugin.arcs.link);
1633 //no color change
1634 window.plugin.arcs.link.color = checkArc.color;
1635 //If it was a 0 distance. DO NOT MAKE
1636 if (window.plugin.arcs.link.distance === 0)
1637 {
1638 //Nope! do nothing here
1639 //continue;
1640 }
1641 else
1642 {
1643 var stopCoord = new window.plugin.arcs.arc.Coord(window.plugin.arcs.link.endPortal.lon, window.plugin.arcs.link.endPortal.lat);
1644 var startCoord = new window.plugin.arcs.arc.Coord(window.plugin.arcs.link.startPortal.lon, window.plugin.arcs.link.startPortal.lat);
1645 window.plugin.arcs.create(startCoord, stopCoord, window.plugin.arcs.link);
1646 //add to local storage list
1647 arc_list[i] = window.plugin.arcs.link;
1648 }
1649
1650 }
1651 }
1652
1653 //now we have rewitten all portals I will redraw everything.
1654
1655 //save changes
1656 localStorage.setItem( 'arc_list', JSON.stringify(arc_list) );
1657
1658 //refresh the layer group
1659 window.plugin.arcs.drawlayer.clearLayers();
1660 window.plugin.arcs.link_list = [];
1661 //redraw all lines
1662 for (var m=0;m<arc_list.length;m++)
1663 {
1664 var link = arc_list[m];
1665 var startCoord = new window.plugin.arcs.arc.Coord(link.startPortal.lon, link.startPortal.lat);
1666 var stopCoord = new window.plugin.arcs.arc.Coord(link.endPortal.lon, link.endPortal.lat);
1667 window.plugin.arcs.create(startCoord, stopCoord, link);
1668 }
1669
1670 }
1671
1672};
1673
1674
1675
1676var setup = window.plugin.arcs.loadExternals;
1677
1678
1679// PLUGIN END //////////////////////////////////////////////////////////
1680
1681if(window.iitcLoaded && typeof setup === 'function') {
1682 setup();
1683} else {
1684 if(window.bootPlugins)
1685 window.bootPlugins.push(setup);
1686 else
1687 window.bootPlugins = [setup];
1688}
1689} // wrapper end
1690// inject code into site context
1691var script = document.createElement('script');
1692script.appendChild(document.createTextNode('('+ wrapper +')();'));
1693(document.body || document.head || document.documentElement).appendChild(script);