// ==UserScript==
// @author DanielOnDiordna
// @name Quick Draw Links
// @category Layer
// @version 0.0.9.20210724.002500
// @updateURL https://raw.githubusercontent.com/IITC-CE/Community-plugins/master/dist/DanielOnDiordna/quick-draw-links.meta.js
// @downloadURL https://raw.githubusercontent.com/IITC-CE/Community-plugins/master/dist/DanielOnDiordna/quick-draw-links.user.js
// @description [danielondiordna-0.0.9.20210724.002500] Quickly draw and move links from portal to portal on the map. Show crosslinks, for links on the map, as well as for drawn links. Store/Restore your projects. Added great circle support. Added fields layer. Export list of used portals with link count. Integrated Spectrum Colorpicker 1.8.1
// @id quick-draw-links@DanielOnDiordna
// @namespace https://softspot.nl/ingress/
// @match https://intel.ingress.com/*
// @grant none
// ==/UserScript==
function wrapper(plugin_info) {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
// use own namespace for plugin
window.plugin.quickdrawlinks = function() {};
var self = window.plugin.quickdrawlinks;
self.id = 'quickdrawlinks';
self.title = 'Quick Draw Links';
self.version = '0.0.9.20210724.002500';
self.author = 'DanielOnDiordna';
self.changelog = `
Changelog:
version 0.0.1.20181101.224000
- added a new button to add bookmarks to portals connected to crosslinks
version 0.0.2.20190530.121700
- closedialog fix for smartphone
- fixed in/out direction for drawn links in portal overview
version 0.0.3.20191120.220400
- open side pane fix for smartphone
version 0.0.4.20200613.180700
- linkexists now checks both directions
version 0.0.5.20201230.204600
- replaced L.geodesicPolyline by L.geoJson (added sourcecode https://github.com/springmeyer/arc.js)
version 0.0.6.20210117.001400
- fixed color storage for setStyle compatibility issues with L.geoJson
version 0.0.7.20210118.220700
- rewritten some code for placing the buttons; buttons now also visible on desktop above the status bar
- updated plugin wrapper and userscript header formatting to match IITC-CE coding
version 0.0.7.20210119.185800
- fixed button width for smartphone
version 0.0.8.20210119.220700
- integrated Spectrum Colorpicker 1.8.1 plugin code, no need anymore for the separate plugin
- removed drawtools integration
version 0.0.9.20210127.225400
- removed icon button titles for mobile users
- enabled toggle function for icon buttons
- new active icon button indicators
version 0.0.9.20210421.190200
- minor fix for IITC CE where runHooks iitcLoaded is executed before addHook is defined in this plugin
version 0.0.9.20210724.002500
- prevent double plugin setup on hook iitcLoaded
`;
self.namespace = 'window.plugin.' + self.id + '.';
self.pluginname = 'plugin-' + self.id;
self.panename = 'plugin-' + self.id;
self.localstoragesettings = self.pluginname + '-settings';
self.localstoragelayer = self.pluginname + '-layer';
self.localstoragetitlecache = self.pluginname + '-titlecache';
self.localstoragedata = self.pluginname + '-data';
self.markerLayer = undefined;
self.iconstyle = 'link';
self.startguid = undefined;
self.startpos = undefined;
self.multistartpos = undefined;
self.guidpos = {};
self.titlecache = {};
self.isSmartphone = null;
self.settings = {};
self.settings.hidebuttons = false;
self.settings.drawcolor = '#E27000';
self.settings.greatcirclecolor = '#FF0000';
self.settings.fieldcolor = '#E27000';
self.settings.crosslinkbookmarkcolor = '#FF0000';
self.settings.showcrosslinks = 0; // 0 = Links, 1 = Drawn, 2 = Both
self.settings.showlinkdirection = false;
self.settings.fieldexistinglinks = false;
self.requestid = undefined;
self.selectedlink = undefined;
self.movelinksposition = undefined;
self.copylinksposition = undefined;
self.linkstyle = [
'10,5,5,5,5,5,5,5,100%',
];
self.crosslinklayerdisabled = false;
self.highlightlinkoptions = {
color: "#C33",
opacity: 1,
weight: 5,
fill: false,
dashArray: "1,6",
radius: 18,
};
// 120 x 60 - 4 buttons, 2 rows: link, move, star, copy
self.menuicons = "data:image/png;base64,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";
// 350 x 50 - 7 buttons: trash, move, swap, zoom, list, confirm, cancel
self.linkmenubuttonsicon = "data:image/png;base64,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";
self.restoresettings = function() {
if (typeof localStorage[self.localstoragesettings] === 'string') {
var settings = JSON.parse(localStorage[self.localstoragesettings]);
if (typeof settings === 'object' && settings instanceof Object) {
if (typeof settings.hidebuttons === 'boolean') self.settings.hidebuttons = settings.hidebuttons;
if (typeof settings.drawcolor === 'string') self.settings.drawcolor = settings.drawcolor;
if (typeof settings.greatcirclecolor === 'string') self.settings.greatcirclecolor = settings.greatcirclecolor;
if (typeof settings.fieldcolor === 'string') self.settings.fieldcolor = settings.fieldcolor;
if (typeof settings.crosslinkbookmarkcolor === 'string') self.settings.crosslinkbookmarkcolor = settings.crosslinkbookmarkcolor;
if (typeof settings.showcrosslinks === 'number') self.settings.showcrosslinks = settings.showcrosslinks;
if (typeof settings.showlinkdirection === 'boolean') self.settings.showlinkdirection = settings.showlinkdirection;
if (typeof settings.fieldexistinglinks === 'boolean') self.settings.fieldexistinglinks = settings.fieldexistinglinks;
}
}
};
self.storesettings = function() {
localStorage[self.localstoragesettings] = JSON.stringify(self.settings);
};
self.linkicon = function(zoom,iconstyle) {
if (iconstyle instanceof Object) iconstyle = iconstyle.icon;
if (!iconstyle) iconstyle = self.iconstyle;
var icon;
switch(iconstyle) {
case 'link':
icon = 'data:image/png;base64,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';
break;
case 'move':
icon = 'data:image/png;base64,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';
break;
case 'copy':
icon = 'data:image/png;base64,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';
break;
case 'star':
icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAB3RJTUUH4QIGDgw4wE60owAAAAlwSFlzAAALEgAACxIB0t1+/AAAAARnQU1BAACxjwv8YQUAAAv6SURBVHja7Z15kFxVFcZPMzNZxpiYgGECcS8NAq5oSVkoFCAYpaRcUItyiSCliBrKKrEkihCMf7hApbTcoymKIljKH4pLFFSCcWNRMbJEcTcSRpbsyUyW9vvNvTfd6XT3ez39Xt/3pvqrOnV73rx+797z3XvuuecubdZHH3300UcffURBJXYGeoHRkWWDSo6TPF/yQsmrJR+Zv3nFj2LnbUoSIIU/S8kLJCdITvTpQskcf8taKX9x7HyCwdgZ6BZS9rFWUzbyPMnTJPOsVsH2SHZLxiW7JEtj5zugVARI2UeaMyOhVqPsZ0qeLBnwt6FklP2IZK8d2srnSq5S7f9z7LIEFNYESdmzzCkaJR/v0+dI5kum+9v2mVP2mDllt8IBCS3lbin/JbHLVo9CtAApe5rVOskTfLpIskAy7G9DiSh7p+QxSdXSVSDum+E/fyJ2WRvRcwKkbJT2bKspu76TfKK/DaWFmr1dst8OV3ba1suzMF1rVPt/0OvyJiE3AqRobPJR5mpwqN0nenmqOXtc30kio+bMymSV3YigfFrMx/IqazfItQ8QCRT66obLoZMkbewk0+S32mE2MGOXqfZ/Js+yTha5d8Ii4f1KrpEMSR6y9La7EdOtUp1m1QpmaTzF/aHjvUPKf1ne5Zwsjsj7BSr8F8yZoF+aq41P8MrpDJUqJm1IaRqzCckz/ecr8i5jN+ipG6rWgBdypf9zk39/2jzQAiBvTK1gZ5v7hsy5qXTo16kCvLOXZewUubeAekgZVyl5heRv5swD7mfa1hDuI8+hL6A10Mkz6l3gZZ6/77dW0I63HlEGYmoJ1OQvSd5uzvt51NpXBpRNC5it2s99A3XXt0j+LfmT5F4vfxTZf49Rtk4RdSQsIs5X8lVz/cJmq9VyFEzrwJTMPJjPirymSnWX1L5eRNxlXtmSv0jhnfcrBUD0UIRIIHB2neSVDf/Czv9X8oBkgxT/oA3vWWwD+9US7NL5G1eWooYnIXooQjX3n0pOFRGfVPoqya/M1eoNkvv0f6KXNrpoKS2C8AQxoaMlU4KA6C2gE4iEDyk5S3KNWsBPYucnC/TUC8oAe3w6N3ZGskLZCAhm59jYGckKZSOA/gDXc7bM0UC3DysCykbAf8yZITrhabEzkwXKRkCIoM60Wqyn1CgbAYyYie3PsdoKh1KjbAQw2sUEYf/7BPQa8v1RPv0A9n9+7PxkgVIR4BFWP8zo6ikFQRkJCGOBZ8TOSBYoIwG7fDqssUCpQinNUEYCwliAZSylN0NlJADl4w3REQ/Fzky3KCMBjAMYD7DeZ16Xz4qOMhKAFzTu8943QREQxgIof2HszHSL0hGgwRjR0DH/Z78PiIRNPi39WKCsBDzu0+GunlIAlJUAVlHTES/UYKzUHXFZCdhqbs/AjBKXYQJlzfxWL4wDjoydmW5QVgJ2e2E0PDt2ZrpBWQnY5wUT9B71A2dIStkhly6aKEVTaV4jucjcyr5t5pai3ydhD9idGivsmvwbeotSESDls1iXYwaW+EtrzPUDLHmnL6BVbJTcLlkvIh6NneeWZRlZxiByqDQESPmsgrjQHAHEg1ZJfmhunRCb/s6WnGqOCK79S/JjybqiESHls1FxueSuUhAg5bMU8W0Sznd4WPJNczX8QN09lAUiTpac7j8DiPiZ5Dd89qGM3pfBbc99reTdknP95TcVngApll0vHzR3ygl7CFZKiX9I+A6tgNZAq4AIykkrWGeuVfSMCCmerbpsRHmHL0MAleiSQhMgRT5dyXt9xlmuvkqKe6CD70PEKeb2HrC0nU4bItab6yc26nn7csn7yLIXm3MU3mBuBQfvCTv8Wdl3/vzNK9YUlgApD6V/wNxCXGo8Nf+hST4LF/Wl5kwA505ABJ7SnZLvS+7Pggjfsb5ecoHkDP8eNprgqYXtuaxnoiWfJAK2FI4Ab8tRPmaHmnKr5HopaDSDZwciTjN3xA1/ByLWmmsRHbuwUvyTlFxirp86zl+mtjN3Ua9jSDhGslrKf5dZwdxQ7+Mv9gWhpuDlYHZ2Z/weauZzJeeYIwQimGPAhe14LCECVii53Jx3RqS22XELgBV9mKMJ82NWIAK8UnAxL/SXvie5MWvlN3knRGCaaBFzvfIY1EH+PXr/422fMbKMSvM7c2dg4KG10+kh5sesIAR4H3+JOQJwLSd8/Ho3M+f3UzOZ3qwfSxBtZeqz7VhCBJzu7yE42O4IhcPMD4hOgArPwUxLzIUXOOXqesmtvVJ+Q17CWAIiGE8s8P8Kg7pfkMd6F1YEfErJR83t6Gynz8PMj1nsfcLOx3+f5CRzzTfRx+9RvtAL/jshjjCWAHhhDOgmxhK2dRbmhw4c8/NIwmMPMz8gGgFe+Ryeh8eDb09nuyFWftrks35Qh5miJrtB3c6Z223fAHucJ2V+QJyjChYtZa8vnS0uW1c+fg/zTAdNR42pdGOJ3TOeYuODfP6fuc67FZqaH1CRDXu51c5cCBvf9lrzg5Eq/kX8n0HHqB64vcOCUOOp+fj4d0u+WHTlN+Q/jCXOse3DF9mBI2ZbpeoODaxW9lhzIpqanwmFioCLUYK5GSaUiV3DA2hFwAEv2EjOADpXD92RIuM890xzPj7fxc1bLeUnfreIGF1w+WIp/GZpRMqv1p/gwnE69WOIluYHHKGLnFrycXOb3mBq0H8ebiJcx2thGhCbhwt2k4/0JSmfpnuxf8fN5mx+KZXv1Fqhgx6Qerfo83Y72AdUGr23cBxE0539E1OSIoFzGohPM+FB7eeBO1vIDi/cg+ng6IBvt8qn9/E5NCkMsL6G5DnAyhv+QMIwL+HMcrWyQ7JNhIw13E6F5XykpudUH5wTFgmcZnWtuUEIk91J4drQ5HAf36hMrToso7VJlPPMxUW+bm6AlUsEsofAK8KR2NZwvdF08xnLcXuj7Q84ZFJeN3EYBjWUo4AHLR0JvBQv4AKRcG34h5RPr4/JwfRA0qeth6PbnHGm189Ywn1tzQ9oarulyBuVvMVqhygluavcwwoFWs9ym7Pjy1bz8VnH+fkiDLCygDc/XQ2+6tF0WYpufqu58OyIv5TUEngOJoaXXGG7p99gTvko/eqponyPVuanEYnmB7RbF8S8JW7mMZbusNRAwl4bHzrN9kynVTDA+kdsjWWMzMwPaEmAWMOtIkzL6VXMSqWz3ZUqntK4jQ0ttq2zTomtrSzRxPtph7beT0DblXEigRjH2VY7ZnJ/wkurcsVwL5m9ooZ8S5k+K7biMgRlwbRuTdRDCvMDEpcm6gF0IjQ7PBmCUUkkAGoKnhGt5rsi4eTYmssILzJX8zMxPyDV2lB/BiejXpjvhAQGanhHa0XC8XF0lik4YpNDBoljtTPJqcwPSL04VyQwTYc5oqMllJyWBGaVcMd+KhJKvaVIOsDtJGowaK1PnExtfkBHq6P1QI4Dfp25ZshgrRMScGlvEQlHx1JgFpAOGM3fZq1bQWrzAzpenq4M3KLkzebiRmHuNAmQwICMn5e6oddKywHLfUpNb3TRMT9/NRftTcSk9geIhJuUEFol1sOamDQuaghll35rqcr/cyXfMLeKolns5zbvQSZi0hs09ILVSi41xziSRELFv29jJL1ljSvNudtH1ZW9I/Nj1uUOGZGw0twvE9HJzrR0LWFzjxWVC1R2TmwnwIgpDnqkIj5oLoyTCl1vUVJGsIefNbdRgsy0CluEkWPXSwyLApX9c+YCc8ErxPys0/WkONFBZLJHTC/8sJKvmGuOrcLYYb65NPO/KRE65Fk+7ehM68w26YkElpEz4888AMpuJAFimEmbEiaortysrmZGEGeEn0hMbX5AprsklRl+kIEM4SM3/uQUpBCom2otAIRf6LunE/MD8timyoYENj+EZX2BBFoA88gPx9BQnpDS7zf3kyy/7vS7mROgzBCqZdn37+3QuYSJdUTmWsFUxGXmSOgIua2MGx1ZRqiCrUD8AiqhCIJ43xFB58XSUBGR2055KZpwNPFzVg2Hk62mnPnpFrkeVeB/H4a9Uo/5S5u6eNyURC9+ypCVz+H328t6NkVu6IlCRMIdSlhpcW/sAvfRRx999NFHUfB/GqOEeimrVP8AAAAASUVORK5CYII=';
break;
default:
iconstyle = 'link';
icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAB3RJTUUH4QIGDBEPhBup3gAAAAlwSFlzAAALEgAACxIB0t1+/AAAAARnQU1BAACxjwv8YQUAAAfMSURBVHja7Z1piBxFFMffbnY1G+MdjUeIqHiQxBNFWUTFIyqKwSMi4oEhiqBgCKgguCbRT2IMgigaz3wwBMmHgMbFRYyBrBgRMRqNN6K5Vg2a+9jD/3+ramd2dmemerq6a7L7fvCo2Z7enqr3ql5VV1e9FlEURVEUJQoNsTOQB32djU1IzoacCzkfcj3kiYbW3g9j521EGgAKPx3JeZCpkGk2nQQ50p7SDuXfEDufpCl2BtICZZ8sBWVTzoGcAjlGChVsL2QPZD9kN+TR2Pl2HFQGgLKPFeNGXK2msk+DHAcZY0+jkqnsvyEHZHArPxoyH7X/x9hlcdStC4Kyx4tRNJU8xaZnQo6HHGpP6xaj7H1ilF2OXghbypdQ/kWxy1ZMXbQAKPsQKXSSU216FuREyDh7GpVIZe+CbOO/iV8F4nlj7eenY5e1lNwNAGVTaWdIQdnFneTh7jQp1OwdkB4Zqmzf1str0XUtRe3/IO/yViMzFwRF0ydPEFODXe2eZmWyGH9c3ElS6L+7A+aLymdnzI73Yhjg16zKWyuZtQAUtgdGeAAfnyn5qlInKRK2UvBadD9t9aj80IUdFhjhESQvQJohm8Xfd6fFdbxrofxLcvi9mmjM+gdQ+JfEuKA1YjrVw6xysoRGbrGf27IuYxpyHYaiNXAUMs/+udH+fug8sKVxmMoOfQkqwH15ljEpud8HwAiXIXlHzA0U+wGOdGppiazlVDaHsPTz7t6ArYtD1e8gM2GAP/IuYxKi3IjBCHRDr0DuETP6+UcqG4HK5oDBKXts0fF/IVTyt5D1VtZB8b/FKFtSot4JwxB3IXlNTL+wRQp9A4ewVDZrdUtRPrdD/oR8LwWFr4P8BIVn3a9kQvSpCBiBE2dLIJeXfEU3sgmyAfKNGJfCdAOUvT92vkMR3QAOGOJZJNdCOsXU6n6lQ9m7Y+dNURRFURRFURRFURRFURRFURRFURRFURRFURRFURRf6mZp4mijr7ORS+ubx6S+kpIYKJ8bFV+GTNYWkBN2e+6NkNmQGfbw7XWxUXskA8Vzqy43otwrJlKL4y3ISjVARkDxFyLhNt1bxYRX4P7nLjG7eiZCOhpae/eoAQJiO9ZbILMgV4vZVsWNJsXbcxkyh3uW+2MVqQECAMUfheRhyN1ituQSxrPg/jfXzzKlERg5YDVqP/e2qQEC8RjkSTE7/+lmXLiF0kGO0/dHpQeUGkHt5+5Ojm4YUOQvqbz3mSF4BtwPyXyn/CjgSjHRXuhSKg3rh7gfogZIzzViPMm+KucNcT9EDZACG5KHERiHi/pSyhD3Q9QA6bhCTCi17VXOG9b9EDVAOlK5n/4v0IxapRBzwU3OHbDHSmEz67bf86ajCxbdEVsLMQjhfggtw5ibnJljFCsqk62CQ6pyBui1wjmONcjIDBhhZ2yFRMC5n/+qnFfW/ZBGHGTUkqfEBMXgbXKT/TxuGOFxWvMIMaHHroIstzN9o43U7of09wEwAuM0LBATnYS1ny1hVxnZaYXncI5jOuS92NrIk1Duhwx0wjACo1ktEhPikaFi+qpc2M1tbIXchky9EVsxOZJ69OMYNArCSXORLBYTCrhJ/IzgbsFnwQiLYmsmJ4K4HzJkGAojPIhkmZg5bH7vYwT2B4x6NQdGmB9bO1kS0v2QYe8DYIQ7kbRDTnC/W+WHeB1OvbKZtSGTc2MrKkOCuR9S6UaMzy0ZavIkqW4Ady120uycF8IIs2NrKiOCuR9S1gA2LBinWRm9igFQfWKy8XqsGYxytRhGmBlbWyEJ7X5IxakIGIE3GdfZC9EIPR755DX5NIg1ZBkyPT224gLCsvDBeqqbr2KqzgXhAoxmyGbH4SYjnPsYgTWFIyO2mhUwwqWxNReIC8TU/CDuh3hNxtkYnLzrpeWTGIE3aozx2Q4jTImjs6AwxObvYlY1VHLJXu6HeM+GwggMG0l3xNEOY0D7GoFxPjnF8TGMcGoszYUAOmCkX84aNEn5x7ne7ockmo7GBT9HcrOYZsibtSRG4JC2A0aYGEuBIYAOXkeySsq3Am/3QxI/D0AGOpDcIWbeiNMWvkZgsG6+XurdvJWWAQtsyppeOkSn+/kFstLnQjU9kIERliO5X8zsKNfE+AxR3VR2c/76CgvK/wmSN8W8BaTYAM79rLIjyKrU/EQMP/A2kjliLE6pZoQG+3s/xFJcYOaJWQM0oajsidyPSMpHkjDCi2LeTMROtkX8WsKWnBWVCTYs/nNiXLHTIyviz2KmcbxI/UwYGaE/fF7My3KYmXLTFu7OsSuOysKDsi9E8oUURoV0P5/ieLV5ogGCPJTHD3Jp3qtimmO5aWz3vHlzRJ1lgeuQx9vU2/2QYKsiYISHkCwVM41NZZcagYbhk7QR4YKKyv2+mCeCHIzwFYne7ocEXZaCzPCFDMwQx8juiZmDRnFLtUca7g19XydxPySLdUHckLBajF8kzghsAZyq3hpDQ1kCpfONHlzc8FnS/w1uAGSGU7U3Qb6Swc8S+tcRiWkFI5HHxRghEZmsjLOLtThvRJ/oprFpgE34zufhzkEH10ZB9ib9v8yWJiIznI7m/DnfAzPJHh5x7ictma4NhRE4dcu9UtvsoY2xC1xv5PEqQ74Fyb2/XRcDl5CLQmCEtUi40mJ97AIriqIoSr3wP25jEZOXeWltAAAAAElFTkSuQmCC';
// icon = '//storage.googleapis.com/ingress.com/img/map_icons/marker_images/lp-origin-ornament.png';
}
self.iconstyle = iconstyle;
var size = Math.max(30,zoom * 4);
return L.icon({
iconUrl: icon,
iconSize: [size, size], // size of the icon
iconAnchor: [size/2, size/2], // point of the icon which will correspond to marker's location
zIndexOffset: -1000
});
};
self.zoomadjust = function(zoom) {
if (self.markerLayer === undefined) return;
self.markerLayer.setIcon(self.linkicon(zoom));
};
self.clearall = function() {
self.moveselectedlinkstartposition = undefined;
self.moveselectedlinkendposition = undefined;
self.movelinksposition = undefined;
self.multistartpos = undefined;
self.copylinksposition = undefined;
self.closedialog();
self.deactivatebuttons();
};
self.addMarker = function(guid,iconstyle) {
if (self.removeMarker() == iconstyle.icon) {
self.clearall();
return;
}
if (self.drawnItems._map === null) return;
self.activatebutton(iconstyle.icon);
var portal = window.portals[guid];
var startpos = portal.getLatLng();
self.markerLayer = L.marker([startpos.lat, startpos.lng], {icon: self.linkicon(map.getZoom(),iconstyle), iconstyle: iconstyle.icon}).addTo(map);
self.markerLayer.on('click', function(e) {
self.clearall();
self.removeMarker();
});
self.startguid = guid;
self.startpos = startpos;
map.on('zoomend', function() {
self.zoomadjust(map.getZoom());
});
};
self.multistartlinks = function() {
if (window.selectedPortal === null) return;
self.addMarker(window.selectedPortal,{icon:'star'});
self.multistartpos = self.startpos;
};
self.removeMarker = function() {
if (self.markerLayer === undefined) return false;
// remove marker
let iconstyle = self.markerLayer.options.iconstyle;
map.removeLayer(self.markerLayer);
self.markerLayer = undefined;
return iconstyle;
};
self.removelink = function(link) {
if (self.markerLayer !== undefined) return; // disable remove when drawing a new line
self.stophighlightlink();
var drawlayer = self.getDrawlayer();
drawlayer.removeLayer(link);
self.updategreatcircleslayer();
self.updatefieldslayer();
self.storelinks();
// all other event types - assume anything could have been modified and re-check all links
self.checkAllLinksForCrosslinks();
return true;
};
self.linkexists = function(latLngs) {
var drawlayer = self.getDrawlayer();
var linkexists = false;
drawlayer.eachLayer( function(layer) {
//if (layer instanceof L.GeodesicPolyline && layer.getLatLngs().length === 2) {
if (layer instanceof L.GeoJSON && layer.getLatLngs().length === 2) {
var existinglatLngs = layer.getLatLngs();
if ((existinglatLngs[0].lat === latLngs[0].lat && existinglatLngs[0].lng === latLngs[0].lng && existinglatLngs[1].lat === latLngs[1].lat && existinglatLngs[1].lng === latLngs[1].lng) ||
(existinglatLngs[0].lat === latLngs[1].lat && existinglatLngs[0].lng === latLngs[1].lng && existinglatLngs[1].lat === latLngs[0].lat && existinglatLngs[1].lng === latLngs[0].lng)){
linkexists = true;
}
}
});
//console.log('link exists: ' + linkexists);
return linkexists;
};
self.distanceBetween = function(startLatLng,endLatLng) {
// source: Arc 1.7.0
// How far between portals.
let R = 6367;
// km
let lat1 = startLatLng.lat;
let lon1 = startLatLng.lng;
let lat2 = endLatLng.lat;
let lon2 = endLatLng.lng;
let dLat = (lat2 - lat1) * Math.PI / 180;
let dLon = (lon2 - lon1) * Math.PI / 180;
lat1 = lat1 * Math.PI / 180;
lat2 = lat2 * Math.PI / 180;
let a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
let c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
let d = R * c;
d = Math.round(d * 1000) / 1000;
return d;
};
/*
self.Coord = function(c, e) {
// source: Arc 1.7.0
let D2R = Math.PI / 180;
let R2D = 180 / Math.PI;
this.lon = c;
this.lat = e;
this.x = D2R * c;
this.y = D2R * e;
};
self.Coord.prototype.view = function() {
return String(this.lon).slice(0, 4) + "," + String(this.lat).slice(0, 4);
};
self.Coord.prototype.antipode = function() {
return new Coord(0 > this.lon ? 180 + this.lon : -1 * (180 - this.lon),-1 * this.lat);
};
*/
self.drawline = function(latLngs,color) {
if (latLngs[0].lat === latLngs[1].lat && latLngs[0].lng === latLngs[1].lng) return; // no 0 length lines
if (self.linkexists(latLngs)) return; // no double lines
function randomguid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
var drawlayer = self.getDrawlayer();
// Draw method:
/*
self.lineOptions = {
stroke: true,
color: self.settings.drawcolor,
weight: 4,
opacity: 0.8,
fill: false,
clickable: true
};
var lineoptions = self.lineOptions;
var link = L.geodesicPolyline(latLngs, L.extend({}, lineoptions, {color:color, dashArray: (self.settings.showlinkdirection?self.linkstyle:null)}));
*/
// Arc method:
var startCoord = new self.arc.Coord(latLngs[0].lng,latLngs[0].lat);
var stopCoord = new self.arc.Coord(latLngs[1].lng,latLngs[1].lat);
var lineoptions = self.lineOptions;
var myStyle = L.extend({}, lineoptions, {color:color, dashArray: (self.settings.showlinkdirection?self.linkstyle:null)});
var distance = self.distanceBetween(latLngs[0],latLngs[1]);
var gc = new self.arc.GreatCircle(startCoord,stopCoord);
//var gc = new window.plugin.arcs.arc.GreatCircle(startCoord,stopCoord);
//console.log('==================== gc new arcs:',gcnew,gc);
var geojson_feature = gc.Arc(Math.round(distance)).json();
var link = L.geoJson(geojson_feature,{
style: myStyle
});
// additions to Arc, to make it compatible for Quick Draw:
link.getLatLngs = function() {
return [L.latLng(latLngs[0]),L.latLng(latLngs[1])];
};
link.options = L.extend({}, myStyle);
link.on('click',function(e) { self.linkmenu(link); });
drawlayer.addLayer(link);
self.updategreatcircleslayer();
self.updatefieldslayer();
link.options.guid = randomguid(); // create a fake guid for cross link support
// we can just test the new layer in this case
self.testAllLinksAgainstLayer(link);
return link;
};
self.addline = function() {
if (!self.startpos || window.selectedPortal === null) return;
var startpos = self.startpos;
var endpos = window.portals[window.selectedPortal].getLatLng();
var latLngs = [new L.LatLng(startpos.lat,startpos.lng),new L.LatLng(endpos.lat,endpos.lng)];
self.drawline(latLngs,self.settings.drawcolor);
self.storelinks();
};
self.clonelatlngs = function(latlngs) {
var newlatlngs = [];
for (var cnt = 0; cnt < latlngs.length; cnt++) {
newlatlngs.push(new L.LatLng(latlngs[cnt].lat,latlngs[cnt].lng));
}
return newlatlngs;
};
self.moveline = function(index) { // 0 = start, 1 = end
if (window.selectedPortal === null) return;
var guid = window.selectedPortal;
var portal = window.portals[guid];
var drawlayer = self.getDrawlayer();
var latLngs = self.clonelatlngs(self.selectedlink.getLatLngs());
var newll = portal.getLatLng();
latLngs[index] = new L.LatLng(newll.lat,newll.lng);
if ((latLngs[0].lat === latLngs[1].lat && latLngs[0].lng === latLngs[1].lng) || self.linkexists(latLngs)) { // remove line if start and end match or if line already exists
drawlayer.removeLayer(self.selectedlink);
self.selectedlink = undefined;
} else {
//self.selectedlink.setLatLngs(latLngs);
var color = self.selectedlink.options.color;
drawlayer.removeLayer(self.selectedlink);
self.selectedlink = self.drawline(latLngs,color);
}
self.updategreatcircleslayer();
self.updatefieldslayer();
self.storelinks();
// all other event types - assume anything could have been modified and re-check all links
self.checkAllLinksForCrosslinks();
};
self.movelines = function() {
if (window.selectedPortal === null) return;
if (!self.movelinksposition) return;
var guid = window.selectedPortal;
var portal = window.portals[guid];
var newll = portal.getLatLng();
var drawlayer = self.getDrawlayer();
var movefromposition = self.movelinksposition;
var movecnt = 0;
drawlayer.eachLayer( function(layer) {
//if (layer instanceof L.GeodesicPolyline && layer.getLatLngs().length === 2) {
if (layer instanceof L.GeoJSON && layer.getLatLngs().length === 2) {
var moved = false;
var latLngs = self.clonelatlngs(layer.getLatLngs());
if (latLngs[0].lat === movefromposition.lat && latLngs[0].lng === movefromposition.lng) {
latLngs[0] = new L.LatLng(newll.lat,newll.lng);
moved = true;
} else if (latLngs[1].lat === movefromposition.lat && latLngs[1].lng === movefromposition.lng) {
latLngs[1] = new L.LatLng(newll.lat,newll.lng);
moved = true;
}
if (moved) {
movecnt++;
if ((latLngs[0].lat === latLngs[1].lat && latLngs[0].lng === latLngs[1].lng) || self.linkexists(latLngs)) { // remove line if start and end match or if line already exists
drawlayer.removeLayer(layer);
} else {
//layer.setLatLngs(latLngs);
var color = layer.options.color;
drawlayer.removeLayer(layer);
self.drawline(latLngs,color);
}
}
}
});
if (movecnt > 0) {
self.updategreatcircleslayer();
self.updatefieldslayer();
self.storelinks();
}
// all other event types - assume anything could have been modified and re-check all links
self.checkAllLinksForCrosslinks();
};
self.copylines = function() {
if (window.selectedPortal === null) return;
if (!self.copylinksposition) return;
var guid = window.selectedPortal;
var portal = window.portals[guid];
var newll = portal.getLatLng();
var drawlayer = self.getDrawlayer();
var copyfromposition = self.copylinksposition;
var copycnt = 0;
drawlayer.eachLayer( function(layer) {
//if (layer instanceof L.GeodesicPolyline && layer.getLatLngs().length === 2) {
if (layer instanceof L.GeoJSON && layer.getLatLngs().length === 2) {
var latLngs = self.clonelatlngs(layer.getLatLngs());
var startpos;
var endpos;
if (latLngs[0].lat === copyfromposition.lat && latLngs[0].lng === copyfromposition.lng) {
startpos = newll;
endpos = new L.LatLng(latLngs[1].lat,latLngs[1].lng);
} else if (latLngs[1].lat === copyfromposition.lat && latLngs[1].lng === copyfromposition.lng) {
startpos = new L.LatLng(latLngs[0].lat,latLngs[0].lng);
endpos = newll;
}
if (startpos && endpos) {
latLngs = [new L.LatLng(startpos.lat,startpos.lng),new L.LatLng(endpos.lat,endpos.lng)];
self.drawline(latLngs,layer.options.color);
copycnt++;
}
}
});
if (copycnt > 0) {
self.updategreatcircleslayer();
self.updatefieldslayer();
self.storelinks();
}
// all other event types - assume anything could have been modified and re-check all links
self.checkAllLinksForCrosslinks();
};
self.storetitles = function() {
// only save titles for stored positions
var savetitles = {};
var drawlayer = self.getDrawlayer();
drawlayer.eachLayer( function(layer) {
//if (layer instanceof L.GeodesicPolyline && layer.getLatLngs().length === 2) {
if (layer instanceof L.GeoJSON && layer.getLatLngs().length === 2) {
var latLngs = layer.getLatLngs();
for (var cnt = 0; cnt < latLngs.length; cnt++) {
var guid = self.getguid(latLngs[cnt]);
var title = self.gettitle(latLngs[cnt]);
if (title && guid) {
savetitles[latLngs[cnt].lat + ',' + latLngs[cnt].lng] = {title:title,guid:guid};
}
}
}
});
localStorage[self.localstoragetitlecache] = JSON.stringify(savetitles);
};
self.restoretitles = function() {
// restore stored titles
try {
var dataStr = localStorage[self.localstoragetitlecache];
if (dataStr === undefined) return;
var data = JSON.parse(dataStr);
$.each(data, function(pos,item) {
if (item instanceof Object) {
self.guidpos[pos] = item.guid;
self.titlecache[item.guid] = item.title;
}
});
} catch(e) {
console.warn(self.id + ': failed to load data from localStorage: '+e);
}
};
self.gettitle = function(position) {
var guid = self.getguid(position);
if (!guid) return undefined;
return self.titlecache[guid];
};
self.getguid = function(position) {
if (!(position instanceof Object) || !position.lat || !position.lng) return undefined;
return self.guidpos[position.lat + ',' + position.lng];
};
self.deactivatebuttons = function() {
console.log('deactivatebuttons');
$('.screenlinkicon, .titlelinkicon').css('background-position-y','top');
$('.screenmoveicon, .titlemoveicon').css('background-position-y','top');
$('.screenstaricon, .titlestaricon').css('background-position-y','top');
$('.screencopyicon, .titlecopyicon').css('background-position-y','top');
};
self.activatebutton = function(icon) {
console.log('activatebutton',icon);
$('.screen' + icon + 'icon, .title' + icon + 'icon').css('background-position-y','bottom');
};
self.onPortalSelected = function() {
// remove the sidebar button
self.stophighlightlink();
$('.quickdrawbutton').remove();
if (window.selectedPortal === null) {
$('#quickdrawmenuselectedportal').hide();
return;
}
if (self.drawnItems._map === null) return;
$('#quickdrawmenuselectedportal').show();
var guid = window.selectedPortal;
var portal = window.portals[guid];
var latlng = portal.getLatLng();
if (portal.options.data.title) {
self.guidpos[latlng.lat + ',' + latlng.lng] = guid;
self.titlecache[guid] = portal.options.data.title;
self.storetitles();
}
if (self.markerLayer !== undefined) { // there is a start marker
if (self.startguid !== guid) { // another portal then the start portal is selected
if (self.selectedlink && self.moveselectedlinkstartposition) {
self.moveline(0);
self.moveselectedlinkstartposition = undefined;
// remove marker
self.removeMarker();
} else if (self.selectedlink && self.moveselectedlinkendposition) {
self.moveline(1);
self.moveselectedlinkendposition = undefined;
// remove marker
self.removeMarker();
} else if (self.movelinksposition) {
// move all links connected to movelinksposition to new portal
self.movelines();
self.movelinksposition = undefined;
// remove marker
self.removeMarker();
} else if (self.copylinksposition) {
// copy all links connected to copylinksposition to new portal
self.copylines();
self.copylinksposition = undefined;
// remove marker
self.removeMarker();
} else {
self.addline();
// remove marker
let iconstyle = self.removeMarker();
// set marker for new portal
self.addMarker(guid,{icon:iconstyle}); // repeat link or star
if (self.multistartpos) { // star
self.startpos = self.multistartpos;
}
}
}
}
setTimeout(function() { // the sidebar is constructed after firing the hook
// add button to portal details window:
$('.quickdrawbutton').remove();
if (window.selectedPortal === null) return;
var guid = window.selectedPortal;
var portalposition = window.portals[guid].getLatLng();
// find links connected to selectedportal
var linkcount = self.linkcount(portalposition);
if (linkcount > 0) {
// copybutton
let titledescription = '';
if (!self.isSmartphone) titledescription = ' title="Click to copy all links from this portal to another portal"';
let onclickaction = self.namespace + 'clearall(); ' + self.namespace + 'copylinks(); return false;'
if (!self.settings.hidebuttons) {
$('#updatestatus').prepend('');
}
$('#portaldetails > .title').prepend('');
}
if (true) {
// starbutton
let titledescription = '';
if (!self.isSmartphone) titledescription = ' title="Click to start making multiple links to this portal"';
let onclickaction = self.namespace + 'clearall(); ' + self.namespace + 'multistartlinks(); return false;'
let styleactivebutton = (self.markerLayer != undefined && self.markerLayer.options.iconstyle == 'star'?' style="background-position-y: bottom;"':'' );
if (!self.settings.hidebuttons) {
$('#updatestatus').prepend('');
}
$('#portaldetails > .title').prepend('');
}
if (linkcount > 0) {
// movebutton
let titledescription = '';
if (!self.isSmartphone) titledescription = ' title="Click to move all links from this portal to another portal"';
let onclickaction = self.namespace + 'clearall(); ' + self.namespace + 'movelinks(); return false;'
if (!self.settings.hidebuttons) {
$('#updatestatus').prepend('');
}
$('#portaldetails > .title').prepend('');
}
if (true) {
// linkbutton
let titledescription = '';
if (!self.isSmartphone) titledescription = ' title="Click to start a link from this portal, click another portal to create a link"';
let onclickaction = self.namespace + 'clearall(); ' + self.namespace + 'addMarker(\'' + guid + '\',{icon:\'link\'}); return false;'
let styleactivebutton = (self.markerLayer != undefined && self.markerLayer.options.iconstyle == 'link'?' style="background-position-y: bottom;"':'' );
if (!self.settings.hidebuttons) {
$('#updatestatus').prepend('');
}
$('#portaldetails > .title').prepend('');
}
}, 0);
};
self.setalloutgoing = function(position) {
if (!position) return;
var drawlayer = self.getDrawlayer();
var swapcount = 0;
var outcount = 0;
drawlayer.eachLayer( function(layer) {
//if (layer instanceof L.GeodesicPolyline && layer.getLatLngs().length === 2) {
if (layer instanceof L.GeoJSON && layer.getLatLngs().length === 2) {
var latLngs = layer.getLatLngs();
if (position.lat === latLngs[1].lat && position.lng === latLngs[1].lng) {
// set incoming link to outgoing link
self.selectedlink = layer;
self.swapstartend();
swapcount++;
} else if (position.lat === latLngs[0].lat && position.lng === latLngs[0].lng) {
outcount++;
}
}
});
alert('Total Drawn Links connected to portal: ' + (swapcount + outcount) + "\n" + 'links changed to outgoing: ' + swapcount);
};
self.setallincoming = function(position) {
if (!position) return;
var drawlayer = self.getDrawlayer();
var swapcount = 0;
var incount = 0;
drawlayer.eachLayer( function(layer) {
//if (layer instanceof L.GeodesicPolyline && layer.getLatLngs().length === 2) {
if (layer instanceof L.GeoJSON && layer.getLatLngs().length === 2) {
var latLngs = layer.getLatLngs();
if (position.lat === latLngs[0].lat && position.lng === latLngs[0].lng) {
// set outgoing link to incoming link
self.selectedlink = layer;
self.swapstartend();
swapcount++;
} else if (position.lat === latLngs[1].lat && position.lng === latLngs[1].lng) {
incount++;
}
}
});
alert('Total Drawn Links connected to portal: ' + (swapcount + incount) + "\n" + 'links changed to incoming: ' + swapcount);
};
self.linkcount = function(position) {
var drawlayer = self.getDrawlayer();
var linkcount = 0;
drawlayer.eachLayer( function(layer) {
//if (layer instanceof L.GeodesicPolyline && layer.getLatLngs().length === 2) {
if (layer instanceof L.GeoJSON && layer.getLatLngs().length === 2) {
var latLngs = layer.getLatLngs();
if (!position || position.lat === latLngs[0].lat && position.lng === latLngs[0].lng || position.lat === latLngs[1].lat && position.lng === latLngs[1].lng) {
linkcount++;
}
}
});
return linkcount;
};
self.storelinks = function() {
var data = [];
self.drawnItems.eachLayer( function(layer) {
if (layer instanceof L.GeoJSON && layer.getLatLngs().length === 2) {
var item = {};
item.type = 'polyline';
item.latLngs = layer.getLatLngs();
item.color = layer.options.color;
data.push(item);
}
});
localStorage[self.localstoragelayer] = JSON.stringify(data);
self.storetitles();
};
self.load = function() {
try {
var dataStr = localStorage[self.localstoragelayer];
if (dataStr === undefined) return;
var data = JSON.parse(dataStr);
self.import(data);
} catch(e) {
console.warn(self.id + ': failed to load data from localStorage: '+e);
}
};
self.import = function(data) {
if (!data.layerdata && !data.titledata) data.layerdata = data; // support some backwards compatiblity
if (data.layerdata) {
$.each(data.layerdata, function(index,item) {
switch(item.type) {
case 'polyline':
self.drawline(item.latLngs,item.color);
break;
default:
console.warn(self.id + ': unknown import layer type "'+item.type);
break;
}
});
}
if (data.titledata) {
localStorage[self.localstoragetitlecache] = JSON.stringify(data.titledata);
self.restoretitles();
}
};
// copy start
// copied from Cross Links plugin //////////
self.greatCircleArcIntersect = function(a0,a1,b0,b1) {
// based on the formula at http://williams.best.vwh.net/avform.htm#Int
// method:
// check to ensure no line segment is zero length - if so, cannot cross
// check to see if either of the lines start/end at the same point. if so, then they cannot cross
// check to see if the line segments overlap in longitude. if not, no crossing
// if overlap, clip each line to the overlapping longitudes, then see if latitudes cross
// anti-meridian handling. this code will not sensibly handle a case where one point is
// close to -180 degrees and the other +180 degrees. unwrap coordinates in this case, so one point
// is beyond +-180 degrees. this is already true in IITC
// FIXME? if the two lines have been 'unwrapped' differently - one positive, one negative - it will fail
// zero length line tests
if (a0.equals(a1)) return false;
if (b0.equals(b1)) return false;
// lines have a common point
if (a0.equals(b0) || a0.equals(b1)) return false;
if (a1.equals(b0) || a1.equals(b1)) return false;
// check for 'horizontal' overlap in lngitude
if (Math.min(a0.lng,a1.lng) > Math.max(b0.lng,b1.lng)) return false;
if (Math.max(a0.lng,a1.lng) < Math.min(b0.lng,b1.lng)) return false;
// ok, our two lines have some horizontal overlap in longitude
// 1. calculate the overlapping min/max longitude
// 2. calculate each line latitude at each point
// 3. if latitudes change place between overlapping range, the lines cross
// class to hold the pre-calculated maths for a geodesic line
// TODO: move this outside this function, so it can be pre-calculated once for each line we test
var GeodesicLine = function(start,end) {
var d2r = Math.PI/180.0;
var r2d = 180.0/Math.PI;
// maths based on http://williams.best.vwh.net/avform.htm#Int
if (start.lng == end.lng) {
throw 'Error: cannot calculate latitude for meridians';
}
// only the variables needed to calculate a latitude for a given longitude are stored in 'this'
this.lat1 = start.lat * d2r;
this.lat2 = end.lat * d2r;
this.lng1 = start.lng * d2r;
this.lng2 = end.lng * d2r;
var dLng = this.lng1-this.lng2;
var sinLat1 = Math.sin(this.lat1);
var sinLat2 = Math.sin(this.lat2);
var cosLat1 = Math.cos(this.lat1);
var cosLat2 = Math.cos(this.lat2);
this.sinLat1CosLat2 = sinLat1*cosLat2;
this.sinLat2CosLat1 = sinLat2*cosLat1;
this.cosLat1CosLat2SinDLng = cosLat1*cosLat2*Math.sin(dLng);
};
GeodesicLine.prototype.isMeridian = function() {
return this.lng1 == this.lng2;
};
GeodesicLine.prototype.latAtLng = function(lng) {
lng = lng * Math.PI / 180; //to radians
var lat;
// if we're testing the start/end point, return that directly rather than calculating
// 1. this may be fractionally faster, no complex maths
// 2. there's odd rounding issues that occur on some browsers (noticed on IITC MObile) for very short links - this may help
if (lng == this.lng1) {
lat = this.lat1;
} else if (lng == this.lng2) {
lat = this.lat2;
} else {
lat = Math.atan ( (this.sinLat1CosLat2*Math.sin(lng-this.lng2) - this.sinLat2CosLat1*Math.sin(lng-this.lng1)) / this.cosLat1CosLat2SinDLng);
}
return lat * 180 / Math.PI; // return value in degrees
};
// calculate the longitude of the overlapping region
var leftLng = Math.max( Math.min(a0.lng,a1.lng), Math.min(b0.lng,b1.lng) );
var rightLng = Math.min( Math.max(a0.lng,a1.lng), Math.max(b0.lng,b1.lng) );
// calculate the latitudes for each line at left + right longitudes
// NOTE: need a special case for meridians - as GeodesicLine.latAtLng method is invalid in that case
var aLeftLat, aRightLat;
if (a0.lng == a1.lng) {
// 'left' and 'right' now become 'top' and 'bottom' (in some order) - which is fine for the below intersection code
aLeftLat = a0.lat;
aRightLat = a1.lat;
} else {
var aGeo = new GeodesicLine(a0,a1);
aLeftLat = aGeo.latAtLng(leftLng);
aRightLat = aGeo.latAtLng(rightLng);
}
var bLeftLat, bRightLat;
if (b0.lng == b1.lng) {
// 'left' and 'right' now become 'top' and 'bottom' (in some order) - which is fine for the below intersection code
bLeftLat = b0.lat;
bRightLat = b1.lat;
} else {
var bGeo = new GeodesicLine(b0,b1);
bLeftLat = bGeo.latAtLng(leftLng);
bRightLat = bGeo.latAtLng(rightLng);
}
// if both a are less or greater than both b, then lines do not cross
if (aLeftLat < bLeftLat && aRightLat < bRightLat) return false;
if (aLeftLat > bLeftLat && aRightLat > bRightLat) return false;
// latitudes cross between left and right - so geodesic lines cross
return true;
};
self.testPolyLine = function (polyline, link,closed) {
var a = link.getLatLngs();
var b = polyline.getLatLngs();
for (var i=0;i' + displaylength + '';
rows.push({length:length,text:direction + ' ' + title + ' - ' + displaylength});
}
rows.sort( function(a, b) {
if (a.length === b.length) {
return 0;
} else {
return (a.length > b.length) ? 1 : -1;
}
});
let rowstext = [];
for (let cnt = 0; cnt < rows.length; cnt++) {
rowstext.push(rows[cnt].text);
}
return rowstext.join(' \n') + ' \n';
};
self.overviewConnected = function() {
var drawlayer = self.getDrawlayer();
if (!drawlayer) return;
if (!window.selectedPortal) return;
var portal = window.portals[window.selectedPortal];
var portalLinks = { in: [], out: [] };
$.each(window.links, function(linkguid,link) {
if (link.options.data.oGuid === window.selectedPortal) portalLinks.out.push(link);
if (link.options.data.dGuid === window.selectedPortal) portalLinks.in.push(link);
});
var position = portal.getLatLng();
var drawnLinks = { in: [], out: [] };
drawlayer.eachLayer( function(layer) {
//if (layer instanceof L.GeodesicPolyline && layer.getLatLngs().length === 2) {
if (layer instanceof L.GeoJSON && layer.getLatLngs().length === 2) {
var latLngs = layer.getLatLngs();
if (position.lat === latLngs[0].lat && position.lng === latLngs[0].lng) { // portal position matches first draw links position (base)
drawnLinks.out.push(layer);
} else if (position.lat === latLngs[1].lat && position.lng === latLngs[1].lng) { // portal position matches second draw links position (target)
drawnLinks.in.push(layer);
}
}
});
var html = '
' +
'';
window.dialog({
html: html,
id: 'ui-dialog-quickdrawlinks-export-data',
width: 600,
dialogClass: 'ui-dialog-quickdrawlinks-export',
title: self.title + ' Copy'
});
};
self.pastedata = function(appenddata) {
if (!appenddata && self.linkcount() !== 0 && !confirm('Are you sure you want to replace all data?')) return;
var promptAction = prompt('Press CTRL+V to paste (' + (appenddata?'append':'replace') + ' ' + self.title + ' data or URL).', '');
if (promptAction === null || promptAction === '') return;
try {
// first see if it looks like a URL-format stock intel link, and if so, try and parse out any stock drawn items
// from the pls parameter
if (promptAction.match(new RegExp("^(https?://)?(www\\.)ingress\\.com/intel.*[?&]pls="))) {
//looks like a ingress URL that has drawn items...
var items = promptAction.split(/[?&]/);
var foundAt = -1;
var i;
for (i=0; i b.toLowerCase()?1:0)); });
if (layers.length === 0) return 'nothing stored';
var list = [];
if (!selectedlayer) selectedlayer = $('#quickdrawlinks_selectlayer option:selected').val();
if (!selectedlayer) selectedlayer = layers[0];
for (var index in layers) {
var layername = layers[index];
list.push('');
}
return '';
};
self.updatelayerlist = function(selectedlayer) {
var newlist = self.projectselectlist(selectedlayer);
if (newlist !== $('#quickdrawlinks_selectlayer').html()) $('#quickdrawlinks_selectlayer').replaceWith(newlist);
};
self.deletestored = function() {
var selectedlayer = $('#quickdrawlinks_selectlayer option:selected').val();
if (!selectedlayer) {
alert('Nothing stored to delete');
return;
}
if (!confirm('Are you sure you want to delete stored data \'' + selectedlayer + '\'?')) return;
var storeddata = self.getstoreddata();
delete(storeddata[selectedlayer]);
localStorage[self.localstoragedata] = JSON.stringify(storeddata);
self.updatelayerlist();
};
self.restore = function(replacelinks) {
var selectedlayer = $('#quickdrawlinks_selectlayer option:selected').val();
if (!selectedlayer) {
alert('Nothing to restore');
return;
}
var linkcount = self.linkcount();
if (linkcount !== 0) {
if (replacelinks) {
if (!confirm('Are you sure you want to replace all drawn links with stored data \'' + selectedlayer + '\'?')) return;
} else {
if (!confirm('Are you sure you want to add stored links from \'' + selectedlayer + '\' to current drawn links?')) return;
}
}
var storeddata = self.getstoreddata();
if (replacelinks && linkcount) self.removeAll(true);
self.import(storeddata[selectedlayer]);
self.storelinks();
};
self.renamestored = function() {
var selectedlayer = $('#quickdrawlinks_selectlayer option:selected').val();
if (!selectedlayer) {
alert('Nothing to rename');
return;
}
var newname = prompt('Enter a new unique name for this layer:',selectedlayer);
if (newname === null || newname === selectedlayer) return;
if (newname === '') {
alert('Layer name cannot be empty!');
return;
}
if (newname.match(/['"]/) !== null) {
alert('Quote characters are not allowed in the layer name');
return;
}
var storeddata = self.getstoreddata();
if (storeddata[newname]) {
alert('Layer name must be unique! \'' + newname + '\' already in use');
return;
}
storeddata[newname] = storeddata[selectedlayer];
delete(storeddata[selectedlayer]);
localStorage[self.localstoragedata] = JSON.stringify(storeddata);
self.updatelayerlist(newname);
};
self.listportals = function() {
if (self.linkcount() === 0) {
alert('No drawn links');
return;
}
var drawlayer = self.getDrawlayer();
var listportalsindex = {};
var listportals = [];
var linklengths = {};
drawlayer.eachLayer( function(layer) {
//if (layer instanceof L.GeodesicPolyline && layer.getLatLngs().length === 2) {
if (layer instanceof L.GeoJSON && layer.getLatLngs().length === 2) {
var latLngs = layer.getLatLngs();
for (var cnt = 0; cnt < latLngs.length; cnt++) {
var guid = self.getguid(latLngs[cnt]);
var title = self.gettitle(latLngs[cnt]);
if (title && guid) {
var id = latLngs[cnt].lat + ',' + latLngs[cnt].lng;
if (listportalsindex[id] === undefined) {
listportalsindex[id] = listportals.length;
listportals.push({id:id,title:title,guid:guid,countin:0,countout:0,outindex:[]});
linklengths[listportalsindex[id]] = {};
}
if (cnt === 0) {
listportals[listportalsindex[id]].countout++;
var id1 = latLngs[1].lat + ',' + latLngs[1].lng;
listportals[listportalsindex[id]].outindex.push(id1);
linklengths[listportalsindex[id]][id1] = self.linklength(layer);
} else {
listportals[listportalsindex[id]].countin++;
}
}
}
}
});
var linkout = []; // listportals sort must be AFTER linkout is created, because listportals are used by indexes
for (var cnt = 0; cnt < listportals.length; cnt++) {
var portalinfo = listportals[cnt];
for (var cnt2 = 0; cnt2 < listportals[cnt].outindex.length; cnt2++) {
linkout.push(portalinfo.title + "\t" + listportals[listportalsindex[portalinfo.outindex[cnt2]]].title + "\t" + linklengths[cnt][portalinfo.outindex[cnt2]]);
}
}
linkout.sort();
listportals.sort( function(a, b) { // reverse sort by countin (highest first)
if (a.countin === b.countin) {
return 0;
} else {
return (a.countin > b.countin) ? -1 : 1;
}
});
var baseurl = window.location.protocol + "//" + window.location.host;
var linkcount = [];
var locations = [];
for (var cnt = 0; cnt < listportals.length; cnt++) {
var portalinfo = listportals[cnt];
linkcount.push(portalinfo.title + "\t" + portalinfo.countin + "\t" + portalinfo.countout);
locations.push(portalinfo.title + "\t" + baseurl + '/intel?ll=' + portalinfo.id + '&pll=' + portalinfo.id + "\t" + portalinfo.guid);
}
locations.sort();
var html = '