From e761a01aed4d492ec20e386a1741920bd6e9e76a Mon Sep 17 00:00:00 2001 From: Cameron Moon Date: Tue, 12 Feb 2013 08:58:06 +1100 Subject: [PATCH 01/46] fixed various minor sidebar layout issues --- code/boot.js | 2 +- dist/style.css | 10 +++------- main.js | 1 - style.css | 10 +++------- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/code/boot.js b/code/boot.js index 57e6ebe9..f27ec694 100644 --- a/code/boot.js +++ b/code/boot.js @@ -36,7 +36,7 @@ window.setupStyles = function() { '.leaflet-right { margin-right: '+(SIDEBAR_WIDTH+1)+'px } ', '#updatestatus { width:'+(SIDEBAR_WIDTH-2*4+1)+'px; } ', '#sidebar { width:'+(SIDEBAR_WIDTH + HIDDEN_SCROLLBAR_ASSUMED_WIDTH + 1 /*border*/)+'px; } ', - '#sidebartoggle { right:'+SIDEBAR_WIDTH+'px; } ', + '#sidebartoggle { right:'+(SIDEBAR_WIDTH+1)+'px; } ', '#scrollwrapper { width:'+(SIDEBAR_WIDTH + 2*HIDDEN_SCROLLBAR_ASSUMED_WIDTH)+'px; right:-'+(2*HIDDEN_SCROLLBAR_ASSUMED_WIDTH-2)+'px } ', '#sidebar input, h2 { width:'+(SIDEBAR_WIDTH - 2*4)+'px !important } ', '#sidebar > *, #gamestat span, .imgpreview img { width:'+SIDEBAR_WIDTH+'px; }'].join("\n") diff --git a/dist/style.css b/dist/style.css index 6fb01ecd..43abdb69 100644 --- a/dist/style.css +++ b/dist/style.css @@ -36,10 +36,10 @@ body { #sidebartoggle { display: block; padding: 20px 5px; - margin-top: -31px; + margin-top: -31px; /* -(toggle height / 2) */ line-height: 10px; position: absolute; - top: 50%; + top: 340px; /* (sidebar height / 2) */ z-index: 3001; background-color: rgba(8, 48, 78, 0.9); color: #FFCE00; @@ -561,10 +561,6 @@ aside:nth-child(odd) span { padding: 5px; } -#spacer { - height: 10px; -} - /* a common portal display takes this much space (prevents moving * content when first selecting a portal) */ @@ -575,7 +571,7 @@ aside:nth-child(odd) span { /* update status */ #updatestatus { - background-color: rgba(8, 48, 78, 1); + background-color: rgba(8, 48, 78, 0.9); border-bottom: 0; border-top: 1px solid #20A8B1; border-left: 1px solid #20A8B1; diff --git a/main.js b/main.js index 96f0a63c..64a0967d 100644 --- a/main.js +++ b/main.js @@ -79,7 +79,6 @@ document.getElementsByTagName('body')[0].innerHTML = '' + '
' + ' ' + '
permalink
' - + '
' + ' ' + '' + '
'; diff --git a/style.css b/style.css index bec15a62..652db7a3 100644 --- a/style.css +++ b/style.css @@ -50,10 +50,10 @@ body { #sidebartoggle { display: block; padding: 20px 5px; - margin-top: -31px; + margin-top: -31px; /* -(toggle height / 2) */ line-height: 10px; position: absolute; - top: 50%; + top: 340px; /* (sidebar height / 2) */ z-index: 3001; background-color: rgba(8, 48, 78, 0.9); color: #FFCE00; @@ -575,10 +575,6 @@ aside:nth-child(odd) span { padding: 5px; } -#spacer { - height: 10px; -} - /* a common portal display takes this much space (prevents moving * content when first selecting a portal) */ @@ -589,7 +585,7 @@ aside:nth-child(odd) span { /* update status */ #updatestatus { - background-color: rgba(8, 48, 78, 1); + background-color: rgba(8, 48, 78, 0.9); border-bottom: 0; border-top: 1px solid #20A8B1; border-left: 1px solid #20A8B1; From f9f1cc1266cdafe7118fa39eb59e642803814db1 Mon Sep 17 00:00:00 2001 From: Cameron Moon Date: Tue, 12 Feb 2013 09:23:28 +1100 Subject: [PATCH 02/46] Added details on how to find updates to error message --- style.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/style.css b/style.css index 652db7a3..09654f4a 100644 --- a/style.css +++ b/style.css @@ -2,7 +2,7 @@ body:after { background: none repeat scroll 0 0 #FFFFFF; color: red; - content: "Please update your total conversion script or it will not work properly anymore."; + content: "Please update your total conversion script or it will not work properly anymore. \a Google \"ingress total conversion\"."; display: block; font-weight: bold; left: 381px; @@ -10,6 +10,8 @@ body:after { position: absolute; top: 0; z-index: 9001; + white-space: pre; + text-align: center; } /* general rules ******************************************************/ From 195dc611b249ad3467fbd21c5e7183e39afdafc1 Mon Sep 17 00:00:00 2001 From: vita10gy Date: Tue, 12 Feb 2013 00:21:49 -0600 Subject: [PATCH 03/46] Weak Portal Plugin At a glance high level indicator of portals in disrepair. Opacity is used to denote how much it's hurting. (Bright means needs the most attention.) Factors in current energy, missing shields, or missing resonators. Red means it needs attention. Orange means the same thing, except that it's down at least one resonator. I realise this is in opposition to game convention where dim == almost dead, but I tried it that way, and it just made no sense to me to do it that way. The whole point is a high level way to quickly identify portals that most need repairing. If opacity isn't done this way your eyes are most drawn to the portals that least need your attention. --- code/map_data.js | 2 +- main.js | 2 +- plugins/show-portal-weakness.user.js | 132 +++++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 plugins/show-portal-weakness.user.js diff --git a/code/map_data.js b/code/map_data.js index 893ecc3a..7f8737c7 100644 --- a/code/map_data.js +++ b/code/map_data.js @@ -351,7 +351,7 @@ window.isResonatorsShow = function() { } window.portalResetColor = function(portal) { - portal.setStyle({color: portal.options.fillColor}); + portal.setStyle({color: COLORS[getTeam(portal.options.details)]}); } // renders a link on the map from the given entity diff --git a/main.js b/main.js index 64a0967d..6460139c 100644 --- a/main.js +++ b/main.js @@ -125,7 +125,7 @@ var MAX_DRAWN_LINKS = 400; var MAX_DRAWN_FIELDS = 200; -var COLOR_SELECTED_PORTAL = '#f00'; +var COLOR_SELECTED_PORTAL = '#fff'; var COLORS = ['#FFCE00', '#0088FF', '#03FE03']; // none, res, enl var COLORS_LVL = ['#000', '#FECE5A', '#FFA630', '#FF7315', '#E40000', '#FD2992', '#EB26CD', '#C124E0', '#9627F4']; var COLORS_MOD = {VERY_RARE: '#F78AF6', RARE: '#AD8AFF', COMMON: '#84FBBD'}; diff --git a/plugins/show-portal-weakness.user.js b/plugins/show-portal-weakness.user.js new file mode 100644 index 00000000..34647d78 --- /dev/null +++ b/plugins/show-portal-weakness.user.js @@ -0,0 +1,132 @@ +// ==UserScript== +// @id iitc-plugin-show-portal-weakness@vita10gy +// @name iitc: show portal weakness +// @version 0.1 +// @namespace https://github.com/breunigs/ingress-intel-total-conversion +// @updateURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/show-portal-weekness.user.js +// @downloadURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/show-portal-weekness.user.js +// @description Uses the fill color of the portals to denote if the portal is weak (Needs recharging, missing a resonator, needs shields) +// @include http://www.ingress.com/intel* +// @match http://www.ingress.com/intel* +// ==/UserScript== + +function wrapper() { +// ensure plugin framework is there, even if iitc is not yet loaded +if(typeof window.plugin !== 'function') window.plugin = function() {}; + + +// PLUGIN START //////////////////////////////////////////////////////// + +// use own namespace for plugin +window.plugin.portalWeakness = function() {}; + +window.plugin.portalWeakness.getPortalWeaknessFactor = function(d) +{ + var portal_weakness = 0; + if(getTeam(d) != 0) + { + if(window.getTotalPortalEnergy(d)> 0 && window.getCurrentPortalEnergy(d) < window.getTotalPortalEnergy(d)) + { + portal_weakness = 1 - (window.getPortalEnergy(d)/window.getTotalPortalEnergy(d)); + } + //Ding the portal for every missing sheild. + $.each(d.portalV2.linkedModArray, function(ind, mod) + { + if(mod == null) + { + portal_weakness += .05; + } + }); + //Ding the portal for every missing resonator. + var resCount = 0; + $.each(d.resonatorArray.resonators, function(ind, reso) + { + if(reso == null) { + portal_weakness += .125; + } + else { + resCount++; + } + }); + if(portal_weakness<0) { + portal_weakness = 0; + } + if(portal_weakness>1) + { + portal_weakness = 1; + } + } + return(Math.round(portal_weakness*100)/100); +} + +window.plugin.portalWeakness.portalAdded = function(data) { + + var d = data.portal.options.details; + var portal_weakness = 0; + if(getTeam(d) != 0) + { + if(window.getTotalPortalEnergy(d)> 0 && window.getCurrentPortalEnergy(d) < window.getTotalPortalEnergy(d)) + { + portal_weakness = 1 - (window.getCurrentPortalEnergy(d)/window.getTotalPortalEnergy(d)); + } + //Ding the portal for every missing sheild. + $.each(d.portalV2.linkedModArray, function(ind, mod) + { + if(mod == null) + { + portal_weakness += .05; + } + }); + //Ding the portal for every missing resonator. + var resCount = 0; + $.each(d.resonatorArray.resonators, function(ind, reso) + { + if(reso == null) { + portal_weakness += .125; + } + else { + resCount++; + } + }); + if(portal_weakness<0) { + portal_weakness = 0; + } + if(portal_weakness>1) + { + portal_weakness = 1; + } + + if(portal_weakness>0) + { + var color = 'red'; + if(resCount<8) + { + color = 'orange'; + } + var fill_opacity = Math.round((portal_weakness*.7 + .3)*100)/100; + data.portal.setStyle({fillColor: color, fillOpacity: fill_opacity}); + } + } + + +} + +var setup = function() { + window.addHook('portalAdded', window.plugin.portalWeakness.portalAdded); +} + +// PLUGIN END ////////////////////////////////////////////////////////// + +if(window.iitcLoaded && typeof setup === 'function') { + setup(); +} else { + if(window.bootPlugins) + window.bootPlugins.push(setup); + else + window.bootPlugins = [setup]; +} +} // wrapper end +// inject code into site context +var script = document.createElement('script'); +script.appendChild(document.createTextNode('('+ wrapper +')();')); +(document.body || document.head || document.documentElement).appendChild(script); From 52306b033de33adb4dca0370789e9f932e6ace38 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Tue, 12 Feb 2013 09:20:08 +0100 Subject: [PATCH 04/46] fix indenting --- code/chat.js | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/code/chat.js b/code/chat.js index 77969845..11b116e9 100644 --- a/code/chat.js +++ b/code/chat.js @@ -636,27 +636,24 @@ window.chat.setupTime = function() { window.chat.setupPosting = function() { $('#chatinput input').keydown(function(event) { -try{ - - var kc = (event.keyCode ? event.keyCode : event.which); - if(kc === 13) { // enter - chat.postMsg(); - event.preventDefault(); - } else if (kc === 9) { // tab - event.preventDefault(); - window.chat.handleTabCompletion(); + try { + var kc = (event.keyCode ? event.keyCode : event.which); + if(kc === 13) { // enter + chat.postMsg(); + event.preventDefault(); + } else if (kc === 9) { // tab + event.preventDefault(); + window.chat.handleTabCompletion(); + } + } catch(error) { + console.log(error); + debug.printStackTrace(); } - - -} catch(error) { - console.log(error); - debug.printStackTrace(); -} }); $('#chatinput').submit(function(event) { - chat.postMsg(); event.preventDefault(); + chat.postMsg(); }); } From 331d9a378198881dcd8c07163be2353d41febe4c Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Tue, 12 Feb 2013 10:01:21 +0100 Subject: [PATCH 05/46] add debugging/console capability to devices where it is not available or easily accessibile --- code/boot.js | 2 ++ code/chat.js | 16 ++++++++++-- code/debugging.js | 65 +++++++++++++++++++++++++++++++++++++++++++++++ style.css | 1 + 4 files changed, 82 insertions(+), 2 deletions(-) diff --git a/code/boot.js b/code/boot.js index f27ec694..3f90fb63 100644 --- a/code/boot.js +++ b/code/boot.js @@ -193,6 +193,8 @@ window.setupSidebarToggle = function() { // BOOTING /////////////////////////////////////////////////////////// function boot() { + window.debug.console.overwriteNativeIfRequired(); + console.log('loading done, booting'); window.setupStyles(); window.setupMap(); diff --git a/code/chat.js b/code/chat.js index 11b116e9..7b091552 100644 --- a/code/chat.js +++ b/code/chat.js @@ -496,8 +496,12 @@ window.chat.request = function() { window.chat.needMoreMessages = function() { var activeChat = $('#chat > :visible'); if(scrollBottom(activeChat) !== 0 || activeChat.scrollTop() !== 0) return; + var activeTab = $('#chatcontrols .active').text(); + if(activeTab === 'debug') return; + console.log('no scrollbar in active chat, requesting more msgs'); - if($('#chatcontrols a:last.active').length) + + if(activeTab === 'faction') chat.requestOldFaction(); else chat.requestOldPublic(); @@ -507,6 +511,7 @@ window.chat.needMoreMessages = function() { window.chat.chooser = function(event) { var t = $(event.target); var tt = t.text(); + var span = $('#chatinput span'); $('#chatcontrols .active').removeClass('active'); @@ -537,6 +542,8 @@ window.chat.chooser = function(event) { break; } + if(!elm) throw('chat button handled by chat.chooser, yet it is null'); + elm.show(); if(elm.data('needsScrollTop')) { elm.data('ignoreNextScroll', true); @@ -580,7 +587,10 @@ window.chat.setup = function() { $('#chatcontrols, #chat, #chatinput').show(); $('#chatcontrols a:first').click(window.chat.toggle); - $('#chatcontrols a:not(:first)').click(window.chat.chooser); + $('#chatcontrols a').each(function(ind, elm) { + if($.inArray($(elm).text(), ['automated', 'public', 'faction']) !== -1) + $(elm).click(window.chat.chooser); + }); $('#chatinput').click(function() { @@ -665,6 +675,8 @@ window.chat.postMsg = function() { var msg = $.trim($('#chatinput input').val()); if(!msg || msg === '') return; + if(c === 'debug') return new Function (msg)(); + var public = c === 'public'; var latlng = map.getCenter(); diff --git a/code/debugging.js b/code/debugging.js index 0a3ce734..b3f12ecc 100644 --- a/code/debugging.js +++ b/code/debugging.js @@ -42,3 +42,68 @@ window.debug.forceSync = function() { updateGameScore(); requestData(); } + +window.debug.console = function() { + $('#debugconsole').text(); +} + +window.debug.console.create = function() { + if($('#debugconsole').length) return; + $('#chatcontrols').append('debug'); + $('#chatcontrols a:last').click(function() { + $('#chatinput span').css('cssText', 'color: #bbb !important').text('debug:'); + $('#chat > div').hide(); + $('#debugconsole').show(); + $('#chatcontrols .active').removeClass('active'); + $(this).addClass('active'); + }); + $('#chat').append(''); +} + +window.debug.console.renderLine = function(text, errorType) { + debug.console.create(); + switch(errorType) { + case 'error': var color = '#FF424D'; break; + case 'warning': var color = '#FFDE42'; break; + case 'alert': var color = '#42FF90'; break; + default: var color = '#eee'; + } + if(typeof text !== 'string' && typeof text !== 'number') text = JSON.stringify(text); + var d = new Date(); + var ta = d.toLocaleTimeString(); // print line instead maybe? + var tb = d.toLocaleString(); + var t = ''; + var s = 'style="color:'+color+'"'; + var l = '

'+t+''+errorType+''+text+'

'; + $('#debugconsole').prepend(l); +} + +window.debug.console.log = function(text) { + debug.console.renderLine(text, 'notice'); +} + +window.debug.console.warn = function(text) { + debug.console.renderLine(text, 'warning'); +} + +window.debug.console.error = function(text) { + debug.console.renderLine(text, 'error'); +} + +window.debug.console.alert = function(text) { + debug.console.renderLine(text, 'alert'); +} + +window.debug.console.overwriteNative = function() { + window.debug.console.create(); + window.console = function() {} + window.console.log = window.debug.console.log; + window.console.warn = window.debug.console.warn; + window.console.error = window.debug.console.error; + window.alert = window.debug.console.alert; +} + +window.debug.console.overwriteNativeIfRequired = function() { + if(!window.console || L.Browser.mobile) + window.debug.console.overwriteNative(); +} diff --git a/style.css b/style.css index 652db7a3..03492dc4 100644 --- a/style.css +++ b/style.css @@ -224,6 +224,7 @@ time { display: inline-block; width: 44px; color: #bbb; + overflow: hidden; } mark { From 6edf2210f849969b1924423640c4c83020deb962 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Tue, 12 Feb 2013 11:54:58 +0100 Subject: [PATCH 06/46] add example for decay message JSON (see #137) --- json_examples/chat_public_decay_msg.js | 49 ++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 json_examples/chat_public_decay_msg.js diff --git a/json_examples/chat_public_decay_msg.js b/json_examples/chat_public_decay_msg.js new file mode 100644 index 00000000..d7366372 --- /dev/null +++ b/json_examples/chat_public_decay_msg.js @@ -0,0 +1,49 @@ +[ + "431a30b634394956a16e62954222a37d.d", + 1360634878999, + { + "plext": { + "text": "Control Field @In the fishing village ( Lomse (Oktyabr'skaya ulitsa, 1, Kaliningrad, Kaliningrad Oblast, Russia) has decayed -108 MUs", + "markup": [ + [ + "TEXT", + { + "plain": "Control Field @" + } + ], + [ + "PORTAL", + { + "name": "In the fishing village ( Lomse", + "plain": "In the fishing village ( Lomse (Oktyabr'skaya ulitsa, 1, Kaliningrad, Kaliningrad Oblast, Russia)", + "team": "ALIENS", + "latE6": 54705182, + "address": "Oktyabr'skaya ulitsa, 1, Kaliningrad, Kaliningrad Oblast, Russia", + "lngE6": 20514959, + "guid": "6af16d09fb574c989b7fa09e718585a7.12" + } + ], + [ + "TEXT", + { + "plain": " has decayed -" + } + ], + [ + "TEXT", + { + "plain": "108" + } + ], + [ + "TEXT", + { + "plain": " MUs" + } + ] + ], + "plextType": "SYSTEM_BROADCAST", + "team": "NEUTRAL" + } + } +] From 0c6f0a97e21502ed5a078d6898f520b89b9b8e3a Mon Sep 17 00:00:00 2001 From: vita10gy Date: Tue, 12 Feb 2013 09:27:47 -0600 Subject: [PATCH 07/46] Description Added Description added to plugins readme --- plugins/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/README.md b/plugins/README.md index 310077f6..891daddd 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -10,6 +10,7 @@ Available Plugins ----------------- - [**Guess Player Level**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/guess-player-levels.user.js) looks for the highest placed resonator per player in the current view to guess the player level. +- [**Highlight Weakened Portals**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/show-portal-weakness.user.js) fill portals with red or orange to indicate portal's state of disrepair. The brighter the color the more attention needed (recharge, shields, resonators). Red means general attention needed. Orange means at least one resonator is gone. Hacking From 10da1dee8348160094b241fcc3f60584559971d6 Mon Sep 17 00:00:00 2001 From: saithis Date: Tue, 12 Feb 2013 19:34:16 +0100 Subject: [PATCH 08/46] Added jQuery UI tooltips --- code/boot.js | 56 +++++++++++++++++++++++++++-- code/chat.js | 6 ++-- code/debugging.js | 2 +- code/portal_detail_display.js | 4 +-- code/portal_detail_display_tools.js | 16 ++++----- code/request_handling.js | 2 +- main.js | 3 +- 7 files changed, 71 insertions(+), 18 deletions(-) diff --git a/code/boot.js b/code/boot.js index 3f90fb63..2e91471d 100644 --- a/code/boot.js +++ b/code/boot.js @@ -161,7 +161,7 @@ window.setupPlayerStat = function() { + '\n\nNote: your player stats can only be updated by a full reload (F5)'; $('#playerstat').html('' - + '

'+level+' ' + + '

'+level+' ' + ''+PLAYER.nickname+'' + '
' + 'XM: '+xmRatio+'%' @@ -189,6 +189,56 @@ window.setupSidebarToggle = function() { }); } +window.setupTooltips = function() { + $(document).tooltip({ + // enable mouse tracking + track: true, + // disable show/hide animation + show: false, + hide: false, + items: "[data-tooltip]", + content: function(){ + var type = $(this).attr('data-tooltip'); + if(type == 'title'){ + return $(this).attr('title'); + } + else if(type == 'title_render'){ + var title = $(this).attr('title'); + var data = []; + var max_columns = 0; + + // parse data + var rows = title.split('\n'); + $.each(rows, function(i, row){ + data[i] = row.replace(/\t+/g, '\t').split('\t'); + if(data[i].length > max_columns) max_columns = data[i].length; + }); + + // build table + if(max_columns > 1) { + var tooltip = ''; + $.each(data, function(i, row){ + tooltip += ''; + $.each(data[i], function(k, cell){ + var attributes = ''; + if(k == 0 && data[i].length < max_columns){ + attributes = ' colspan="'+(max_columns - data[i].length + 1)+'"'; + } + tooltip += ''+cell+''; + }); + tooltip += ''; + }); + tooltip += '
'; + return tooltip; + } + else { + return title.replace(/\n/g, '
'); + } + } + } + }); +} + // BOOTING /////////////////////////////////////////////////////////// @@ -204,6 +254,7 @@ function boot() { window.setupSidebarToggle(); window.updateGameScore(); window.setupPlayerStat(); + window.setupTooltips(); window.chat.setup(); // read here ONCE, so the URL is only evaluated one time after the // necessary data has been loaded. @@ -232,10 +283,11 @@ function asyncLoadScript(a){return function(b,c){var d=document.createElement("s // contains the default Ingress map style. var LLGMAPS = 'http://breunigs.github.com/ingress-intel-total-conversion/dist/leaflet_google.js'; var JQUERY = 'https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js'; +var JQUERYUI = 'http://code.jquery.com/ui/1.10.0/jquery-ui.js'; var LEAFLET = 'http://cdn.leafletjs.com/leaflet-0.5/leaflet.js'; var AUTOLINK = 'http://breunigs.github.com/ingress-intel-total-conversion/dist/autolink.js'; // after all scripts have loaded, boot the actual app -load(JQUERY, LEAFLET, AUTOLINK).then(LLGMAPS).onError(function (err) { +load(JQUERY, LEAFLET, AUTOLINK).then(LLGMAPS, JQUERYUI).onError(function (err) { alert('Could not all resources, the script likely won’t work.\n\nIf this happend the first time for you, it’s probably a temporary issue. Just wait a bit and try again.\n\nIf you installed the script for the first time and this happens:\n– try disabling NoScript if you have it installed\n– press CTRL+SHIFT+K in Firefox or CTRL+SHIFT+I in Chrome/Opera and reload the page. Additional info may be available in the console.\n– Open an issue at https://github.com/breunigs/ingress-intel-total-conversion/issues'); }).thenRun(boot); diff --git a/code/chat.js b/code/chat.js index 7b091552..61bd1ffd 100644 --- a/code/chat.js +++ b/code/chat.js @@ -336,7 +336,7 @@ window.chat.handlePublicAutomated = function(data) { case 'PORTAL': var latlng = [part[1].latE6/1E6, part[1].lngE6/1E6]; var js = 'window.zoomToAndShowPortal(\''+part[1].guid+'\', ['+latlng[0]+', '+latlng[1]+'])'; - tmpmsg += ''+part[1].name+''; + tmpmsg += ''+part[1].name+''; break; } }); @@ -453,9 +453,9 @@ window.chat.renderMsg = function(msg, nick, time, team) { var ta = unixTimeToHHmm(time); var tb = unixTimeToString(time, true); // help cursor via “#chat time” - var t = ''; + var t = ''; var s = 'style="color:'+COLORS[team]+'"'; - var title = nick.length >= 8 ? 'title="'+nick+'" class="help"' : ''; + var title = nick.length >= 8 ? 'title="'+nick+'" class="help" data-tooltip="title"' : ''; return '

'+t+' <'+nick+'> '+msg+'

'; } diff --git a/code/debugging.js b/code/debugging.js index b3f12ecc..7156ddda 100644 --- a/code/debugging.js +++ b/code/debugging.js @@ -72,7 +72,7 @@ window.debug.console.renderLine = function(text, errorType) { var d = new Date(); var ta = d.toLocaleTimeString(); // print line instead maybe? var tb = d.toLocaleString(); - var t = ''; + var t = ''; var s = 'style="color:'+color+'"'; var l = '

'+t+''+errorType+''+text+'

'; $('#debugconsole').prepend(l); diff --git a/code/portal_detail_display.js b/code/portal_detail_display.js index 98b33592..cec6b052 100644 --- a/code/portal_detail_display.js +++ b/code/portal_detail_display.js @@ -18,7 +18,7 @@ window.renderPortalDetails = function(guid) { if(d.portalV2.linkedEdges) $.each(d.portalV2.linkedEdges, function(ind, link) { links[link.isOrigin ? 'outgoing' : 'incoming']++; }); - function linkExpl(t) { return ''+t+''; } + function linkExpl(t) { return ''+t+''; } var linksText = [linkExpl('links'), linkExpl(' ↳ ' + links.incoming+'  •  '+links.outgoing+' ↴')]; var player = d.captured && d.captured.capturingPlayerId @@ -62,7 +62,7 @@ window.renderPortalDetails = function(guid) { .html('' + '

'+d.portalV2.descriptiveText.TITLE+'

' // help cursor via “.imgpreview img” - + '
' + + '
' + ''+Math.floor(getPortalLevel(d))+'' + '
'+getModDetails(d)+'
' + '
'+randDetails+'
' diff --git a/code/portal_detail_display_tools.js b/code/portal_detail_display_tools.js index 6bcbe96e..71d7c333 100644 --- a/code/portal_detail_display_tools.js +++ b/code/portal_detail_display_tools.js @@ -56,10 +56,10 @@ window.getModDetails = function(d) { } }); - var t = ''+mods[0]+'' - + ''+mods[1]+'' - + ''+mods[2]+'' - + ''+mods[3]+'' + var t = ''+mods[0]+'' + + ''+mods[1]+'' + + ''+mods[2]+'' + + ''+mods[3]+'' return t; } @@ -69,7 +69,7 @@ window.getEnergyText = function(d) { var totalNrg = getTotalPortalEnergy(d); var inf = currentNrg + ' / ' + totalNrg; var fill = prettyEnergy(currentNrg) + ' / ' + prettyEnergy(totalNrg) - return ['energy', '' + fill + '']; + return ['energy', '' + fill + '']; } window.getAvgResoDistText = function(d) { @@ -112,7 +112,7 @@ window.getResonatorDetails = function(d) { // rotates clockwise. So, last one is 7 (southeast). window.renderResonatorDetails = function(slot, level, nrg, dist, nick, isLeft) { if(level === 0) { - var meter = ''; + var meter = ''; } else { var max = RESO_NRG[level]; var fillGrade = nrg/max*100; @@ -131,7 +131,7 @@ window.renderResonatorDetails = function(slot, level, nrg, dist, nick, isLeft) { var fill = ''; - var meter = '' + fill + lbar + ''; + var meter = '' + fill + lbar + ''; } var cls = isLeft ? 'left' : 'right'; var text = ''+(nick||'')+''; @@ -162,7 +162,7 @@ window.getDestroyAP = function(d) { t += linkCount + '×\tLinks\t\t= ' + digits(linkAp) + '\n'; t += fieldCount + '×\tFields\t\t= ' + digits(fieldAp) + '\n'; t += 'Sum: ' + digits(sum) + ' AP'; - return '' + digits(text) + ''; + return '' + digits(text) + ''; } return [tt('AP Gain'), tt(sum)]; diff --git a/code/request_handling.js b/code/request_handling.js index 042fc397..e28f4c7e 100644 --- a/code/request_handling.js +++ b/code/request_handling.js @@ -47,7 +47,7 @@ window.renderUpdateStatus = function() { t += 'Up to date.'; if(renderLimitReached()) - t += ' RENDER LIMIT ' + t += ' RENDER LIMIT ' if(window.failedRequestCount > 0) t += ' ' + window.failedRequestCount + ' failed.' diff --git a/main.js b/main.js index 64a0967d..2d63987d 100644 --- a/main.js +++ b/main.js @@ -57,7 +57,8 @@ document.getElementsByTagName('head')[0].innerHTML = '' + 'Ingress Intel Map' + '' + '' - + ''; + + '' + + ''; document.getElementsByTagName('body')[0].innerHTML = '' + '
Loading, please wait
' From e0bb10f9897c60c4afab089abb2d8262b2c3288f Mon Sep 17 00:00:00 2001 From: saithis Date: Tue, 12 Feb 2013 19:46:04 +0100 Subject: [PATCH 09/46] Added missing space between 'span' and 'title' --- code/portal_detail_display_tools.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/portal_detail_display_tools.js b/code/portal_detail_display_tools.js index 71d7c333..96b92094 100644 --- a/code/portal_detail_display_tools.js +++ b/code/portal_detail_display_tools.js @@ -56,10 +56,10 @@ window.getModDetails = function(d) { } }); - var t = ''+mods[0]+'' - + ''+mods[1]+'' - + ''+mods[2]+'' - + ''+mods[3]+'' + var t = ''+mods[0]+'' + + ''+mods[1]+'' + + ''+mods[2]+'' + + ''+mods[3]+'' return t; } From 0d0bd4b26a0784f7b28fca923d272dc63379c160 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Tue, 12 Feb 2013 23:12:28 +0100 Subject: [PATCH 10/46] fix indenting --- code/chat.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/chat.js b/code/chat.js index 7b091552..ac3da081 100644 --- a/code/chat.js +++ b/code/chat.js @@ -304,7 +304,7 @@ window.chat.handlePublic = function(data, textStatus, jqXHR, isOldMsgs) { window.chat.handlePublicAutomated = function(data) { - $.each(data.result, function(ind, json) { // newest first! + $.each(data.result, function(ind, json) { // newest first! var time = json[1]; // ignore player messages @@ -347,7 +347,7 @@ window.chat.handlePublicAutomated = function(data) { tmpmsg = chat.renderMsg(tmpmsg, nick, time, team); window.chat._displayedPlayerActionTime[pguid] = [time, tmpmsg]; }; - }); + }); if(chat.getActive() === 'automated') window.chat.renderAutomatedMsgsTo(); From 139e06d86ca96f235a7a95a3a31e5e21a5b2f2ac Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Tue, 12 Feb 2013 23:12:41 +0100 Subject: [PATCH 11/46] fix typo --- code/map_data.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/map_data.js b/code/map_data.js index 893ecc3a..f915de47 100644 --- a/code/map_data.js +++ b/code/map_data.js @@ -75,7 +75,7 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { if(getTypeByGuid(guid) === TYPE_FIELD && window.fields[guid] !== undefined) { $.each(window.fields[guid].options.vertices, function(ind, vertex) { if(window.portals[vertex.guid] === undefined) return true; - fieldArray = window.portals[vertex.guid].options.portalV2.linkedFields; + fieldArray = window.portals[vertex.guid].options.details.portalV2.linkedFields; fieldArray.splice($.inArray(guid, fieldArray), 1); }); } From 039f9c14b5fdc2d3ac8007b91be752afc94264e0 Mon Sep 17 00:00:00 2001 From: saithis Date: Tue, 12 Feb 2013 23:16:12 +0100 Subject: [PATCH 12/46] * The jQuery UI js/css file is now taken from ajax.googleapis.com instead of code.jquery.com * Table or not is now autodetected, removed data-tooltip attributes * Empty table cells are now possible * Removed duplicated \t's on some titles * Some tooltip code cleanup --- code/boot.js | 80 +++++++++++++---------------- code/chat.js | 6 +-- code/debugging.js | 2 +- code/game_status.js | 2 +- code/portal_detail_display.js | 4 +- code/portal_detail_display_tools.js | 26 +++++----- code/request_handling.js | 2 +- main.js | 2 +- 8 files changed, 59 insertions(+), 65 deletions(-) diff --git a/code/boot.js b/code/boot.js index 2e91471d..a0c7a591 100644 --- a/code/boot.js +++ b/code/boot.js @@ -153,15 +153,15 @@ window.setupPlayerStat = function() { var cls = PLAYER.team === 'ALIENS' ? 'enl' : 'res'; - var t = 'Level:\t\t' + level + '\n' - + 'XM:\t\t\t' + PLAYER.energy + ' / ' + xmMax + '\n' - + 'AP:\t\t\t' + digits(ap) + '\n' + var t = 'Level:\t' + level + '\n' + + 'XM:\t' + PLAYER.energy + ' / ' + xmMax + '\n' + + 'AP:\t' + digits(ap) + '\n' + (level < 8 ? 'level up in:\t' + lvlUpAp + ' AP' : 'Congrats! (neeeeerd)') - + '\n\Invites:\t\t'+PLAYER.available_invites; + + '\n\Invites:\t'+PLAYER.available_invites; + '\n\nNote: your player stats can only be updated by a full reload (F5)'; $('#playerstat').html('' - + '

'+level+' ' + + '

'+level+' ' + ''+PLAYER.nickname+'' + '
' + 'XM: '+xmRatio+'%' @@ -196,45 +196,39 @@ window.setupTooltips = function() { // disable show/hide animation show: false, hide: false, - items: "[data-tooltip]", - content: function(){ - var type = $(this).attr('data-tooltip'); - if(type == 'title'){ - return $(this).attr('title'); - } - else if(type == 'title_render'){ - var title = $(this).attr('title'); - var data = []; - var max_columns = 0; + content: function() { + var title = $(this).attr('title'); - // parse data - var rows = title.split('\n'); - $.each(rows, function(i, row){ - data[i] = row.replace(/\t+/g, '\t').split('\t'); - if(data[i].length > max_columns) max_columns = data[i].length; + // check if it should be converted to a table + if(!title.match(/\t/)) { + return title.replace(/\n/g, '
'); + } + + var data = []; + var columnCount = 0; + + // parse data + var rows = title.split('\n'); + $.each(rows, function(i, row) { + data[i] = row.split('\t'); + if(data[i].length > columnCount) columnCount = data[i].length; + }); + + // build the table + var tooltip = ''; + $.each(data, function(i, row) { + tooltip += ''; + $.each(data[i], function(k, cell) { + var attributes = ''; + if(k === 0 && data[i].length < columnCount) { + attributes = ' colspan="'+(columnCount - data[i].length + 1)+'"'; + } + tooltip += ''+cell+''; }); - - // build table - if(max_columns > 1) { - var tooltip = '
'; - $.each(data, function(i, row){ - tooltip += ''; - $.each(data[i], function(k, cell){ - var attributes = ''; - if(k == 0 && data[i].length < max_columns){ - attributes = ' colspan="'+(max_columns - data[i].length + 1)+'"'; - } - tooltip += ''+cell+''; - }); - tooltip += ''; - }); - tooltip += '
'; - return tooltip; - } - else { - return title.replace(/\n/g, '
'); - } - } + tooltip += ''; + }); + tooltip += ''; + return tooltip; } }); } @@ -283,7 +277,7 @@ function asyncLoadScript(a){return function(b,c){var d=document.createElement("s // contains the default Ingress map style. var LLGMAPS = 'http://breunigs.github.com/ingress-intel-total-conversion/dist/leaflet_google.js'; var JQUERY = 'https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js'; -var JQUERYUI = 'http://code.jquery.com/ui/1.10.0/jquery-ui.js'; +var JQUERYUI = 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.0/jquery-ui.min.js'; var LEAFLET = 'http://cdn.leafletjs.com/leaflet-0.5/leaflet.js'; var AUTOLINK = 'http://breunigs.github.com/ingress-intel-total-conversion/dist/autolink.js'; diff --git a/code/chat.js b/code/chat.js index 61bd1ffd..7b091552 100644 --- a/code/chat.js +++ b/code/chat.js @@ -336,7 +336,7 @@ window.chat.handlePublicAutomated = function(data) { case 'PORTAL': var latlng = [part[1].latE6/1E6, part[1].lngE6/1E6]; var js = 'window.zoomToAndShowPortal(\''+part[1].guid+'\', ['+latlng[0]+', '+latlng[1]+'])'; - tmpmsg += ''+part[1].name+''; + tmpmsg += ''+part[1].name+''; break; } }); @@ -453,9 +453,9 @@ window.chat.renderMsg = function(msg, nick, time, team) { var ta = unixTimeToHHmm(time); var tb = unixTimeToString(time, true); // help cursor via “#chat time” - var t = ''; + var t = ''; var s = 'style="color:'+COLORS[team]+'"'; - var title = nick.length >= 8 ? 'title="'+nick+'" class="help" data-tooltip="title"' : ''; + var title = nick.length >= 8 ? 'title="'+nick+'" class="help"' : ''; return '

'+t+' <'+nick+'> '+msg+'

'; } diff --git a/code/debugging.js b/code/debugging.js index 7156ddda..b3f12ecc 100644 --- a/code/debugging.js +++ b/code/debugging.js @@ -72,7 +72,7 @@ window.debug.console.renderLine = function(text, errorType) { var d = new Date(); var ta = d.toLocaleTimeString(); // print line instead maybe? var tb = d.toLocaleString(); - var t = ''; + var t = ''; var s = 'style="color:'+color+'"'; var l = '

'+t+''+errorType+''+text+'

'; $('#debugconsole').prepend(l); diff --git a/code/game_status.js b/code/game_status.js index 6027bfe3..fe29b868 100644 --- a/code/game_status.js +++ b/code/game_status.js @@ -15,7 +15,7 @@ window.updateGameScore = function(data) { var es = ' '+Math.round(ep)+'%'; $('#gamestat').html(rs+es).one('click', function() { window.updateGameScore() }); // help cursor via “#gamestat span” - $('#gamestat').attr('title', 'Resistance:\t\t'+r+' MindUnits\nEnlightenment:\t'+e+' MindUnits'); + $('#gamestat').attr('title', 'Resistance:\t'+r+' MindUnits\nEnlightenment:\t'+e+' MindUnits'); window.setTimeout('window.updateGameScore', REFRESH_GAME_SCORE*1000); } diff --git a/code/portal_detail_display.js b/code/portal_detail_display.js index cec6b052..98b33592 100644 --- a/code/portal_detail_display.js +++ b/code/portal_detail_display.js @@ -18,7 +18,7 @@ window.renderPortalDetails = function(guid) { if(d.portalV2.linkedEdges) $.each(d.portalV2.linkedEdges, function(ind, link) { links[link.isOrigin ? 'outgoing' : 'incoming']++; }); - function linkExpl(t) { return ''+t+''; } + function linkExpl(t) { return ''+t+''; } var linksText = [linkExpl('links'), linkExpl(' ↳ ' + links.incoming+'  •  '+links.outgoing+' ↴')]; var player = d.captured && d.captured.capturingPlayerId @@ -62,7 +62,7 @@ window.renderPortalDetails = function(guid) { .html('' + '

'+d.portalV2.descriptiveText.TITLE+'

' // help cursor via “.imgpreview img” - + '
' + + '
' + ''+Math.floor(getPortalLevel(d))+'' + '
'+getModDetails(d)+'
' + '
'+randDetails+'
' diff --git a/code/portal_detail_display_tools.js b/code/portal_detail_display_tools.js index 96b92094..33571d6c 100644 --- a/code/portal_detail_display_tools.js +++ b/code/portal_detail_display_tools.js @@ -56,10 +56,10 @@ window.getModDetails = function(d) { } }); - var t = ''+mods[0]+'' - + ''+mods[1]+'' - + ''+mods[2]+'' - + ''+mods[3]+'' + var t = ''+mods[0]+'' + + ''+mods[1]+'' + + ''+mods[2]+'' + + ''+mods[3]+'' return t; } @@ -69,7 +69,7 @@ window.getEnergyText = function(d) { var totalNrg = getTotalPortalEnergy(d); var inf = currentNrg + ' / ' + totalNrg; var fill = prettyEnergy(currentNrg) + ' / ' + prettyEnergy(totalNrg) - return ['energy', '' + fill + '']; + return ['energy', '' + fill + '']; } window.getAvgResoDistText = function(d) { @@ -112,15 +112,15 @@ window.getResonatorDetails = function(d) { // rotates clockwise. So, last one is 7 (southeast). window.renderResonatorDetails = function(slot, level, nrg, dist, nick, isLeft) { if(level === 0) { - var meter = ''; + var meter = ''; } else { var max = RESO_NRG[level]; var fillGrade = nrg/max*100; - var inf = 'energy:\t\t' + nrg + ' / ' + max + ' (' + Math.round(fillGrade) + '%)\n' - + 'level:\t\t' + level + '\n' + var inf = 'energy:\t' + nrg + ' / ' + max + ' (' + Math.round(fillGrade) + '%)\n' + + 'level:\t' + level + '\n' + 'distance:\t' + dist + 'm\n' - + 'owner:\t\t' + nick + '\n' + + 'owner:\t' + nick + '\n' + 'octant:\t' + OCTANTS[slot]; var style = 'width:'+fillGrade+'%; background:'+COLORS_LVL[level]+';'; @@ -131,7 +131,7 @@ window.renderResonatorDetails = function(slot, level, nrg, dist, nick, isLeft) { var fill = ''; - var meter = '' + fill + lbar + ''; + var meter = '' + fill + lbar + ''; } var cls = isLeft ? 'left' : 'right'; var text = ''+(nick||'')+''; @@ -159,10 +159,10 @@ window.getDestroyAP = function(d) { function tt(text) { var t = 'Destroy:\n'; t += resoCount + '×\tResonators\t= ' + digits(resoAp) + '\n'; - t += linkCount + '×\tLinks\t\t= ' + digits(linkAp) + '\n'; - t += fieldCount + '×\tFields\t\t= ' + digits(fieldAp) + '\n'; + t += linkCount + '×\tLinks\t= ' + digits(linkAp) + '\n'; + t += fieldCount + '×\tFields\t= ' + digits(fieldAp) + '\n'; t += 'Sum: ' + digits(sum) + ' AP'; - return '' + digits(text) + ''; + return '' + digits(text) + ''; } return [tt('AP Gain'), tt(sum)]; diff --git a/code/request_handling.js b/code/request_handling.js index e28f4c7e..042fc397 100644 --- a/code/request_handling.js +++ b/code/request_handling.js @@ -47,7 +47,7 @@ window.renderUpdateStatus = function() { t += 'Up to date.'; if(renderLimitReached()) - t += ' RENDER LIMIT ' + t += ' RENDER LIMIT ' if(window.failedRequestCount > 0) t += ' ' + window.failedRequestCount + ' failed.' diff --git a/main.js b/main.js index 2d63987d..9d1ea3b1 100644 --- a/main.js +++ b/main.js @@ -58,7 +58,7 @@ document.getElementsByTagName('head')[0].innerHTML = '' + '' + '' + '' - + ''; + + ''; document.getElementsByTagName('body')[0].innerHTML = '' + '
Loading, please wait
' From 847a3d5fc15217d90fa91e613c31805ad8b8f920 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Tue, 12 Feb 2013 23:22:45 +0100 Subject: [PATCH 13/46] =?UTF-8?q?warn=20when=20chat=20message=20didn?= =?UTF-8?q?=E2=80=99t=20make=20it=20but=20the=20server=20actually=20send?= =?UTF-8?q?=20a=20response?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/chat.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/code/chat.js b/code/chat.js index ac3da081..808b198f 100644 --- a/code/chat.js +++ b/code/chat.js @@ -685,11 +685,15 @@ window.chat.postMsg = function() { lngE6: Math.round(latlng.lng*1E6), factionOnly: !public}; + var errMsg = 'Your message could not be delivered. You can copy&' + + 'paste it here and try again if you want:\n\n' + msg; + window.postAjax('sendPlext', data, - function() { if(public) chat.requestNewPublic(); else chat.requestNewFaction(); }, + function(response) { + if(response.error) alert(errMsg); + if(public) chat.requestNewPublic(); else chat.requestNewFaction(); }, function() { - alert('Your message could not be delivered. You can copy&' + - 'paste it here and try again if you want:\n\n'+msg); + alert(errMsg); } ); From 4c07fb12ae63e82271b7d17c50e4a3580ee77b57 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 02:49:13 +0100 Subject: [PATCH 14/46] properly check if portal details are available --- code/portal_detail_display.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/portal_detail_display.js b/code/portal_detail_display.js index 98b33592..703af772 100644 --- a/code/portal_detail_display.js +++ b/code/portal_detail_display.js @@ -4,13 +4,14 @@ // methods that highlight the portal in the map view. window.renderPortalDetails = function(guid) { - var d = window.portals[guid].options.details; - if(!d) { + if(!window.portals[guid]) { unselectOldPortal(); urlPortal = guid; return; } + var d = window.portals[guid].options.details; + var update = selectPortal(guid); // collect some random data that’s not worth to put in an own method From 360f6f8336dc6d2c1e01414db35a77fa1c0f6cba Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 02:52:27 +0100 Subject: [PATCH 15/46] rework chat handling completely MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old system was getting too complicated to add new features to. The new one should be easier to understand and will be explained below. This patch should fix #140 and fix #16. There are several places where new data requests may come from: - chat.needMoreMessages checks if we are scrolled too far up or there is no scrollbar. It then requests new messages. - scrolling up - switching the chat tab via chat.chooser - auto refresh - once on boot The latter two always request both types of chat. Faction and public are handled the same way. Public is later split into categories. I will explain the faction chat here because it’s easier. It starts in chat.requestFaction. This will initialize the query to the server for data. The exact query is determined by chat. genPostData. There can only be one faction chat request at a time. Clearing on map move is handled automatically in code/requests.js. Let’s assume the data query is successful. It is now passed to chat.handleFaction which runs some basic checks before the data is processed and stored in chat._factionData. This is done by chat. writeDataToHash. The hash keys are the message GUIDs to avoid duplicates. The hash values are an array of timestamp, processed message and other meta data. There is only one way to render faction chat, so data is directly handed to chat.renderFaction which immediately hands it to chat .renderData. renderData discards the GUIDs and sorts the values by their timestamp. It then iterates over the data to insert date break lines and finally renders the data in the DOM. It also does some magic to keep the correct scrolling position. Chat data will be cleared on map move or zoom. However, the display is not refreshed, so the old, invalid chat data is still displayed. Only once the data query is finished the data is rendered. The upside is that small map operations within your local area appear to never lose their chat data. Downside is that there’s invalid chat for some time when changing cities. --- code/chat.js | 460 +++++++++++++++------------------------ code/request_handling.js | 6 +- main.js | 12 +- style.css | 2 +- 4 files changed, 183 insertions(+), 297 deletions(-) diff --git a/code/chat.js b/code/chat.js index 808b198f..faf7f0b9 100644 --- a/code/chat.js +++ b/code/chat.js @@ -1,22 +1,14 @@ window.chat = function() {}; -window.chat._lastNicksForAutocomplete = [[], []]; -window.chat.addNickForAutocomplete = function(nick, isFaction) { - var r = chat._lastNicksForAutocomplete[isFaction ? 0 : 1]; - if(r.indexOf(nick) !== -1) return; - r.push(nick); - if(r.length >= 15) - r.shift(); -} - window.chat.handleTabCompletion = function() { var el = $('#chatinput input'); var curPos = el.get(0).selectionStart; var text = el.val(); var word = text.slice(0, curPos).replace(/.*\b([a-z0-9-_])/, '$1').toLowerCase(); - var list = window.chat._lastNicksForAutocomplete; - list = list[1].concat(list[0]); + var list = $('#chat > div:visible mark'); + list = list.map(function(ind, mark) { return $(mark).text(); } ); + list = uniqueArray(list); var nick = null; for(var i = 0; i < list.length; i++) { @@ -43,27 +35,24 @@ window.chat.handleTabCompletion = function() { // timestamp and clear management // -window.chat._oldFactionTimestamp = -1; -window.chat._newFactionTimestamp = -1; -window.chat._oldPublicTimestamp = -1; -window.chat._newPublicTimestamp = -1; - -window.chat.getOldestTimestamp = function(public) { - return chat['_old'+(public ? 'Public' : 'Faction')+'Timestamp']; +window.chat.getTimestamps = function(isFaction) { + var storage = isFaction ? chat._factionData : chat._publicData; + return $.map(storage, function(v, k) { return [v[0]]; }); } -window.chat.getNewestTimestamp = function(public) { - return chat['_new'+(public ? 'Public' : 'Faction')+'Timestamp']; +window.chat.getOldestTimestamp = function(isFaction) { + var t = Math.min.apply(null, chat.getTimestamps(isFaction)); + return t === Infinity ? -1 : t; } -window.chat.clearIfRequired = function(elm) { - if(!elm.data('needsClearing')) return; - elm.data('ignoreNextScroll', true).data('needsClearing', false).html(''); +window.chat.getNewestTimestamp = function(isFaction) { + var t = Math.max.apply(null, chat.getTimestamps(isFaction)); + return t === -1*Infinity ? -1 : t; } window.chat._oldBBox = null; -window.chat.genPostData = function(public, getOlderMsgs) { - if(typeof public !== 'boolean') throw('Need to know if public or faction chat.'); +window.chat.genPostData = function(isFaction, getOlderMsgs) { + if(typeof isFaction !== 'boolean') throw('Need to know if public or faction chat.'); chat._localRangeCircle.setLatLng(map.getCenter()); var b = map.getBounds().extend(chat._localRangeCircle.getBounds()); @@ -78,35 +67,30 @@ window.chat.genPostData = function(public, getOlderMsgs) { // need to reset these flags now because clearing will only occur // after the request is finished – i.e. there would be one almost // useless request. - chat._displayedFactionGuids = []; - chat._displayedPublicGuids = []; - chat._displayedPlayerActionTime = {}; - chat._oldFactionTimestamp = -1; - chat._newFactionTimestamp = -1; - chat._oldPublicTimestamp = -1; - chat._newPublicTimestamp = -1; + chat._factionData = {}; + chat._publicData = {}; } chat._oldBBox = bbs; var ne = b.getNorthEast(); var sw = b.getSouthWest(); var data = { - desiredNumItems: public ? CHAT_PUBLIC_ITEMS : CHAT_FACTION_ITEMS, + desiredNumItems: isFaction ? CHAT_FACTION_ITEMS : CHAT_PUBLIC_ITEMS , minLatE6: Math.round(sw.lat*1E6), minLngE6: Math.round(sw.lng*1E6), maxLatE6: Math.round(ne.lat*1E6), maxLngE6: Math.round(ne.lng*1E6), minTimestampMs: -1, maxTimestampMs: -1, - factionOnly: !public + factionOnly: isFaction } if(getOlderMsgs) { // ask for older chat when scrolling up - data = $.extend(data, {maxTimestampMs: chat.getOldestTimestamp(public)}); + data = $.extend(data, {maxTimestampMs: chat.getOldestTimestamp(isFaction)}); } else { // ask for newer chat - var min = chat.getNewestTimestamp(public); + var min = chat.getNewestTimestamp(isFaction); // the inital request will have both timestamp values set to -1, // thus we receive the newest desiredNumItems. After that, we will // only receive messages with a timestamp greater or equal to min @@ -130,322 +114,217 @@ window.chat.genPostData = function(public, getOlderMsgs) { // -// requesting faction +// faction // -window.chat._requestOldFactionRunning = false; -window.chat.requestOldFaction = function(isRetry) { - if(chat._requestOldFactionRunning) return; +window.chat._requestFactionRunning = false; +window.chat.requestFaction = function(getOlderMsgs, isRetry) { + if(chat._requestFactionRunning && !isRetry) return; if(isIdle()) return renderUpdateStatus(); - chat._requestOldFactionRunning = true; + chat._requestFactionRunning = true; - var d = chat.genPostData(false, true); + var d = chat.genPostData(true, getOlderMsgs); var r = window.postAjax( 'getPaginatedPlextsV2', d, - chat.handleOldFaction, + chat.handleFaction, isRetry - ? function() { window.chat._requestOldFactionRunning = false; } - : function() { window.chat.requestOldFaction(true) } - ); - - requests.add(r); -} - -window.chat._requestNewFactionRunning = false; -window.chat.requestNewFaction = function(isRetry) { - if(chat._requestNewFactionRunning) return; - if(window.isIdle()) return renderUpdateStatus(); - chat._requestNewFactionRunning = true; - - var d = chat.genPostData(false, false); - var r = window.postAjax( - 'getPaginatedPlextsV2', - d, - chat.handleNewFaction, - isRetry - ? function() { window.chat._requestNewFactionRunning = false; } - : function() { window.chat.requestNewFaction(true) } + ? function() { window.chat._requestFactionRunning = false; } + : function() { window.chat.requestFaction(getOlderMsgs, true) } ); requests.add(r); } -// -// handle faction -// +window.chat._factionData = {}; +window.chat.handleFaction = function(data, textStatus, jqXHR) { + chat._requestFactionRunning = false; -window.chat.handleOldFaction = function(data, textStatus, jqXHR) { - chat._requestOldFactionRunning = false; - chat.handleFaction(data, textStatus, jqXHR, true); -} - -window.chat.handleNewFaction = function(data, textStatus, jqXHR) { - chat._requestNewFactionRunning = false; - chat.handleFaction(data, textStatus, jqXHR, false); -} - - - -window.chat._displayedFactionGuids = []; -window.chat.handleFaction = function(data, textStatus, jqXHR, isOldMsgs) { if(!data || !data.result) { window.failedRequestCount++; return console.warn('faction chat error. Waiting for next auto-refresh.'); } - var c = $('#chatfaction'); - chat.clearIfRequired(c); - if(data.result.length === 0) return; - chat._newFactionTimestamp = data.result[0][1]; - chat._oldFactionTimestamp = data.result[data.result.length-1][1]; + var old = chat.getOldestTimestamp(true); + chat.writeDataToHash(data, chat._factionData, false); + var oldMsgsWereAdded = old !== chat.getOldestTimestamp(true); - var scrollBefore = scrollBottom(c); - chat.renderPlayerMsgsTo(true, data, isOldMsgs, chat._displayedFactionGuids); - chat.keepScrollPosition(c, scrollBefore, isOldMsgs); + window.chat.renderFaction(oldMsgsWereAdded); if(data.result.length >= CHAT_FACTION_ITEMS) chat.needMoreMessages(); } - +window.chat.renderFaction = function(oldMsgsWereAdded) { + chat.renderData(chat._factionData, 'chatfaction', oldMsgsWereAdded); +} // -// requesting public +// public // -window.chat._requestOldPublicRunning = false; -window.chat.requestOldPublic = function(isRetry) { - if(chat._requestOldPublicRunning) return; +window.chat._requestPublicRunning = false; +window.chat.requestPublic = function(getOlderMsgs, isRetry) { + if(chat._requestPublicRunning && !isRetry) return; if(isIdle()) return renderUpdateStatus(); - chat._requestOldPublicRunning = true; + chat._requestPublicRunning = true; - var d = chat.genPostData(true, true); + var d = chat.genPostData(false, getOlderMsgs); var r = window.postAjax( 'getPaginatedPlextsV2', d, - chat.handleOldPublic, + chat.handlePublic, isRetry - ? function() { window.chat._requestOldPublicRunning = false; } - : function() { window.chat.requestOldPublic(true) } + ? function() { window.chat._requestPublicRunning = false; } + : function() { window.chat.requestPublic(getOlderMsgs, true) } ); requests.add(r); } -window.chat._requestNewPublicRunning = false; -window.chat.requestNewPublic = function(isRetry) { - if(chat._requestNewPublicRunning) return; - if(window.isIdle()) return renderUpdateStatus(); - chat._requestNewPublicRunning = true; +window.chat._publicData = {}; +window.chat.handlePublic = function(data, textStatus, jqXHR) { + chat._requestPublicRunning = false; - var d = chat.genPostData(true, false); - var r = window.postAjax( - 'getPaginatedPlextsV2', - d, - chat.handleNewPublic, - isRetry - ? function() { window.chat._requestNewPublicRunning = false; } - : function() { window.chat.requestNewPublic(true) } - ); - - requests.add(r); -} - - -// -// handle public -// - - -window.chat.handleOldPublic = function(data, textStatus, jqXHR) { - chat._requestOldPublicRunning = false; - chat.handlePublic(data, textStatus, jqXHR, true); -} - -window.chat.handleNewPublic = function(data, textStatus, jqXHR) { - chat._requestNewPublicRunning = false; - chat.handlePublic(data, textStatus, jqXHR, false); -} - -window.chat._displayedPublicGuids = []; -window.chat._displayedPlayerActionTime = {}; -window.chat.handlePublic = function(data, textStatus, jqXHR, isOldMsgs) { if(!data || !data.result) { window.failedRequestCount++; return console.warn('public chat error. Waiting for next auto-refresh.'); } - var ca = $('#chatautomated'); - var cp = $('#chatpublic'); - chat.clearIfRequired(ca); - chat.clearIfRequired(cp); - if(data.result.length === 0) return; - chat._newPublicTimestamp = data.result[0][1]; - chat._oldPublicTimestamp = data.result[data.result.length-1][1]; + var old = chat.getOldestTimestamp(true); + chat.writeDataToHash(data, chat._publicData, true); + var oldMsgsWereAdded = old !== chat.getOldestTimestamp(true); - - var scrollBefore = scrollBottom(ca); - chat.handlePublicAutomated(data); - chat.keepScrollPosition(ca, scrollBefore, isOldMsgs); - - - var scrollBefore = scrollBottom(cp); - chat.renderPlayerMsgsTo(false, data, isOldMsgs, chat._displayedPublicGuids); - chat.keepScrollPosition(cp, scrollBefore, isOldMsgs); + switch(chat.getActive()) { + case 'public': window.chat.renderPublic(oldMsgsWereAdded); break; + case 'compact': window.chat.renderCompact(oldMsgsWereAdded); break; + case 'full': window.chat.renderFull(oldMsgsWereAdded); break; + } if(data.result.length >= CHAT_PUBLIC_ITEMS) chat.needMoreMessages(); } - -window.chat.handlePublicAutomated = function(data) { - $.each(data.result, function(ind, json) { // newest first! - var time = json[1]; - - // ignore player messages - var t = json[2].plext.plextType; - if(t !== 'SYSTEM_BROADCAST' && t !== 'SYSTEM_NARROWCAST') return true; - - var tmpmsg = '', nick = null, pguid, team; - - // each automated message is composed of many text chunks. loop - // over them to gather all necessary data. - $.each(json[2].plext.markup, function(ind, part) { - switch(part[0]) { - case 'PLAYER': - pguid = part[1].guid; - var lastAction = window.chat._displayedPlayerActionTime[pguid]; - // ignore older messages about player - if(lastAction && lastAction[0] > time) return false; - - nick = part[1].plain; - team = part[1].team === 'ALIENS' ? TEAM_ENL : TEAM_RES; - window.setPlayerName(pguid, nick); // free nick name resolves - if(ind > 0) tmpmsg += nick; // don’t repeat nick directly - break; - - case 'TEXT': - tmpmsg += part[1].plain; - break; - - case 'PORTAL': - var latlng = [part[1].latE6/1E6, part[1].lngE6/1E6]; - var js = 'window.zoomToAndShowPortal(\''+part[1].guid+'\', ['+latlng[0]+', '+latlng[1]+'])'; - tmpmsg += ''+part[1].name+''; - break; - } - }); - - // nick will only be set if we don’t have any info about that - // player yet. - if(nick) { - tmpmsg = chat.renderMsg(tmpmsg, nick, time, team); - window.chat._displayedPlayerActionTime[pguid] = [time, tmpmsg]; - }; +window.chat.renderPublic = function(oldMsgsWereAdded) { + // only keep player data + var data = $.map(chat._publicData, function(entry) { + if(!entry[1]) return [entry]; }); - - if(chat.getActive() === 'automated') - window.chat.renderAutomatedMsgsTo(); + chat.renderData(data, 'chatpublic', oldMsgsWereAdded); } -window.chat.renderAutomatedMsgsTo = function() { - var x = window.chat._displayedPlayerActionTime; - // we don’t care about the GUIDs anymore - var vals = $.map(x, function(v, k) { return [v]; }); - // sort them old to new - vals = vals.sort(function(a, b) { return a[0]-b[0]; }); - - var prevTime = null; - var msgs = $.map(vals, function(v) { - var nowTime = new Date(v[0]).toLocaleDateString(); - if(prevTime && prevTime !== nowTime) - var val = chat.renderDivider(nowTime) + v[1]; - else - var val = v[1]; - - prevTime = nowTime; - return val; - }).join('\n'); - - $('#chatautomated').html(msgs); +window.chat.renderCompact = function(oldMsgsWereAdded) { + var data = {}; + $.each(chat._publicData, function(guid, entry) { + // skip player msgs + if(!entry[1]) return true; + var pguid = entry[3]; + // ignore if player has newer data + if(data[pguid] && data[pguid][0] > entry[0]) return true; + data[pguid] = entry; + }); + // data keys are now player guids instead of message guids. However, + // it is all the same to renderData. + chat.renderData(data, 'chatcompact', oldMsgsWereAdded); } - +window.chat.renderFull = function(oldMsgsWereAdded) { + // only keep automatically generated data + var data = $.map(chat._publicData, function(entry) { + if(entry[1]) return [entry]; + }); + chat.renderData(data, 'chatfull', oldMsgsWereAdded); +} // // common // - -window.chat.renderPlayerMsgsTo = function(isFaction, data, isOldMsgs, dupCheckArr) { - var msgs = ''; - var prevTime = null; - - $.each(data.result.reverse(), function(ind, json) { // oldest first! - if(json[2].plext.plextType !== 'PLAYER_GENERATED') return true; - +window.chat.writeDataToHash = function(newData, storageHash, skipSecureMsgs) { + $.each(newData.result, function(ind, json) { // avoid duplicates - if(dupCheckArr.indexOf(json[0]) !== -1) return true; - dupCheckArr.push(json[0]); + if(json[0] in storageHash) return true; var time = json[1]; var team = json[2].plext.team === 'ALIENS' ? TEAM_ENL : TEAM_RES; - var msg, nick, pguid; + var auto = json[2].plext.plextType !== 'PLAYER_GENERATED'; + var msg = '', nick, pguid; $.each(json[2].plext.markup, function(ind, markup) { - if(markup[0] === 'SENDER') { + switch(markup[0]) { + case 'SENDER': // user generated messages nick = markup[1].plain.slice(0, -2); // cut “: ” at end pguid = markup[1].guid; - window.setPlayerName(pguid, nick); // free nick name resolves - if(!isOldMsgs) window.chat.addNickForAutocomplete(nick, isFaction); - } + break; - if(markup[0] === 'TEXT') { - msg = markup[1].plain.autoLink(); - msg = msg.replace(window.PLAYER['nickMatcher'], '$1'); - } + case 'PLAYER': // automatically generated messages + pguid = markup[1].guid; + nick = markup[1].plain; + team = markup[1].team === 'ALIENS' ? TEAM_ENL : TEAM_RES; + if(ind > 0) msg += nick; // don’t repeat nick directly + break; - if(!isFaction && markup[0] === 'SECURE') { - nick = null; - return false; // aka break + case 'TEXT': + var tmp = markup[1].plain.autoLink(); + msg += tmp.replace(window.PLAYER['nickMatcher'], '$1'); + break; + + case 'PORTAL': + var latlng = [markup[1].latE6/1E6, markup[1].lngE6/1E6]; + var js = 'window.zoomToAndShowPortal(\''+markup[1].guid+'\', ['+latlng[0]+', '+latlng[1]+'])'; + msg += ''+markup[1].name+''; + break; + + case 'SECURE': + if(skipSecureMsgs) { + nick = null; + return false; // breaks $.each + } } }); - if(!nick) return true; // aka next - var nowTime = new Date(time).toLocaleDateString(); - if(prevTime && prevTime !== nowTime) - msgs += chat.renderDivider(nowTime); + // format: timestamp, autogenerated, HTML message, player guid + storageHash[json[0]] = [json[1], auto, chat.renderMsg(msg, nick, time, team), pguid]; - msgs += chat.renderMsg(msg, nick, time, team); - prevTime = nowTime; + window.setPlayerName(pguid, nick); // free nick name resolves + }); +} + +// renders data from the data-hash to the element defined by the given +// ID. Set 3rd argument to true if it is likely that old data has been +// added. Latter is only required for scrolling. +window.chat.renderData = function(data, element, likelyWereOldMsgs) { + var elm = $('#'+element); + if(elm.is(':hidden')) return; + + // discard guids and sort old to new + var vals = $.map(data, function(v, k) { return [v]; }); + vals = vals.sort(function(a, b) { return a[0]-b[0]; }); + + // render to string with date separators inserted + var msgs = ''; + var prevTime = null; + $.each(vals, function(ind, msg) { + var nextTime = new Date(msg[0]).toLocaleDateString(); + if(prevTime && prevTime !== nextTime) + msgs += chat.renderDivider(nextTime); + msgs += msg[2]; + prevTime = nextTime; }); - var addTo = isFaction ? $('#chatfaction') : $('#chatpublic'); - - // if there is a change of day between two requests, handle the - // divider insertion here. - if(isOldMsgs) { - var ts = addTo.find('time:first').data('timestamp'); - var nextTime = new Date(ts).toLocaleDateString(); - if(prevTime && prevTime !== nextTime && ts) - msgs += chat.renderDivider(nextTime); - } - - if(isOldMsgs) - addTo.prepend(msgs); - else - addTo.append(msgs); + var scrollBefore = scrollBottom(elm); + elm.html(msgs); + chat.keepScrollPosition(elm, scrollBefore, likelyWereOldMsgs); } window.chat.renderDivider = function(text) { - return '─ '+text+' ────────────────────────────────────────────────────────────────────────────'; + return '─ '+text+' ───────────────────────────────────────────────────────────'; } @@ -486,25 +365,29 @@ window.chat.toggle = function() { window.chat.request = function() { console.log('refreshing chat'); - chat.requestNewFaction(); - chat.requestNewPublic(); + chat.requestFaction(false); + chat.requestPublic(false); } // checks if there are enough messages in the selected chat tab and // loads more if not. window.chat.needMoreMessages = function() { - var activeChat = $('#chat > :visible'); - if(scrollBottom(activeChat) !== 0 || activeChat.scrollTop() !== 0) return; - var activeTab = $('#chatcontrols .active').text(); + var activeTab = chat.getActive(); if(activeTab === 'debug') return; - console.log('no scrollbar in active chat, requesting more msgs'); + var activeChat = $('#chat > :visible'); + + var hasScrollbar = scrollBottom(activeChat) !== 0 || activeChat.scrollTop() !== 0; + var nearTop = activeChat.scrollTop() <= CHAT_REQUEST_SCROLL_TOP; + if(hasScrollbar && !nearTop) return; + + console.log('No scrollbar or near top in active chat. Requesting more data.'); if(activeTab === 'faction') - chat.requestOldFaction(); + chat.requestFaction(true); else - chat.requestOldPublic(); + chat.requestPublic(true); } @@ -525,26 +408,26 @@ window.chat.chooser = function(event) { case 'faction': span.css('color', ''); span.text('tell faction:'); - elm = $('#chatfaction'); break; case 'public': span.css('cssText', 'color: red !important'); span.text('broadcast:'); - elm = $('#chatpublic'); break; - case 'automated': + case 'compact': + case 'full': span.css('cssText', 'color: #bbb !important'); span.text('tell Jarvis:'); - chat.renderAutomatedMsgsTo(); - elm = $('#chatautomated'); break; + + default: + throw('chat.chooser was asked to handle unknown button: ' + tt); } - if(!elm) throw('chat button handled by chat.chooser, yet it is null'); - + var elm = $('#chat' + tt); elm.show(); + eval('chat.render' + tt.capitalize() + '(false);'); if(elm.data('needsScrollTop')) { elm.data('ignoreNextScroll', true); elm.scrollTop(elm.data('needsScrollTop')); @@ -588,7 +471,7 @@ window.chat.setup = function() { $('#chatcontrols a:first').click(window.chat.toggle); $('#chatcontrols a').each(function(ind, elm) { - if($.inArray($(elm).text(), ['automated', 'public', 'faction']) !== -1) + if($.inArray($(elm).text(), ['full', 'compact', 'public', 'faction']) !== -1) $(elm).click(window.chat.chooser); }); @@ -603,15 +486,15 @@ window.chat.setup = function() { $('#chatfaction').scroll(function() { var t = $(this); if(t.data('ignoreNextScroll')) return t.data('ignoreNextScroll', false); - if(t.scrollTop() < 200) chat.requestOldFaction(); - if(scrollBottom(t) === 0) chat.requestNewFaction(); + if(t.scrollTop() < CHAT_REQUEST_SCROLL_TOP) chat.requestFaction(true); + if(scrollBottom(t) === 0) chat.requestFaction(false); }); - $('#chatpublic, #chatautomated').scroll(function() { + $('#chatpublic, #chatfull, #chatcompact').scroll(function() { var t = $(this); if(t.data('ignoreNextScroll')) return t.data('ignoreNextScroll', false); - if(t.scrollTop() < 200) chat.requestOldPublic(); - if(scrollBottom(t) === 0) chat.requestNewPublic(); + if(t.scrollTop() < CHAT_REQUEST_SCROLL_TOP) chat.requestPublic(true); + if(scrollBottom(t) === 0) chat.requestPublic(false); }); chat.request(); @@ -670,7 +553,8 @@ window.chat.setupPosting = function() { window.chat.postMsg = function() { var c = chat.getActive(); - if(c === 'automated') return alert('Jarvis: A strange game. The only winning move is not to play. How about a nice game of chess?'); + if(c === 'full' || c === 'compact') + return alert('Jarvis: A strange game. The only winning move is not to play. How about a nice game of chess?'); var msg = $.trim($('#chatinput input').val()); if(!msg || msg === '') return; @@ -691,7 +575,7 @@ window.chat.postMsg = function() { window.postAjax('sendPlext', data, function(response) { if(response.error) alert(errMsg); - if(public) chat.requestNewPublic(); else chat.requestNewFaction(); }, + if(public) chat.requestPublic(false); else chat.requestFaction(false); }, function() { alert(errMsg); } diff --git a/code/request_handling.js b/code/request_handling.js index 042fc397..6fe0acd3 100644 --- a/code/request_handling.js +++ b/code/request_handling.js @@ -25,10 +25,8 @@ window.requests.abort = function() { window.activeRequests = []; window.failedRequestCount = 0; - window.chat._requestOldPublicRunning = false; - window.chat._requestNewPublicRunning = false; - window.chat._requestOldFactionRunning = false; - window.chat._requestNewFactionRunning = false; + window.chat._requestPublicRunning = false; + window.chat._requestFactionRunning = false; renderUpdateStatus(); } diff --git a/main.js b/main.js index 64a0967d..b190399e 100644 --- a/main.js +++ b/main.js @@ -62,12 +62,14 @@ document.getElementsByTagName('head')[0].innerHTML = '' document.getElementsByTagName('body')[0].innerHTML = '' + '
Loading, please wait
' + '' + '' + '' + '' @@ -115,8 +117,10 @@ var CHAT_MIN_RANGE = 6; var VIEWPORT_PAD_RATIO = 0.3; // how many items to request each query -var CHAT_PUBLIC_ITEMS = 200 -var CHAT_FACTION_ITEMS = 50 +var CHAT_PUBLIC_ITEMS = 200; +var CHAT_FACTION_ITEMS = 50; +// how many pixels to the top before requesting new data +var CHAT_REQUEST_SCROLL_TOP = 200; // Leaflet will get very slow for MANY items. It’s better to display // only some instead of crashing the browser. diff --git a/style.css b/style.css index f7a375cf..15a033d3 100644 --- a/style.css +++ b/style.css @@ -191,7 +191,7 @@ em { top: 25px; } -#chatpublic, #chatautomated { +#chatpublic, #chatfull, #chatcompact, /* FIXME DEPRECATED: */#chatautomated { display: none; } From 4ca80b877e40c19df92bfe8b4b9467ec8aabd3a2 Mon Sep 17 00:00:00 2001 From: Xelio Date: Mon, 11 Feb 2013 21:14:35 +0800 Subject: [PATCH 16/46] Add resonator re-render logic Resonator will re-render if it's level/energy/distance changed Bring portal to front after resonators re-rendered. --- code/map_data.js | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/code/map_data.js b/code/map_data.js index 893ecc3a..e0df8e41 100644 --- a/code/map_data.js +++ b/code/map_data.js @@ -227,7 +227,7 @@ window.renderPortal = function(ent) { u = u || oo.level !== portalLevel; // nothing for the portal changed, so don’t update. Let resonators // manage themselves if they want to be updated. - if(!u) return renderResonators(ent); + if(!u) return renderResonators(ent, old); // there were changes, remove old portal removeByGuid(ent[0]); } @@ -237,7 +237,6 @@ window.renderPortal = function(ent) { // pre-loads player names for high zoom levels loadPlayerNamesForPortal(ent[2]); - var lvWeight = Math.max(2, portalLevel / 1.5); var lvRadius = Math.max(portalLevel + 3, 5); @@ -261,7 +260,7 @@ window.renderPortal = function(ent) { // all resonators have already removed by zooming if(isResonatorsShow()) { for(var i = 0; i <= 7; i++) - removeByGuid(portalResonatorGuid(portalGuid,i)); + removeByGuid(portalResonatorGuid(portalGuid, i)); } delete window.portals[portalGuid]; if(window.selectedPortal === portalGuid) { @@ -287,7 +286,7 @@ window.renderPortal = function(ent) { window.map.setView(latlng, 17); }); - window.renderResonators(ent); + window.renderResonators(ent, null); window.runHooks('portalAdded', {portal: p}); @@ -295,18 +294,28 @@ window.renderPortal = function(ent) { p.addTo(layerGroup); } -window.renderResonators = function(ent) { +window.renderResonators = function(ent, portalLayer) { + if(!isResonatorsShow()) return; + var portalLevel = getPortalLevel(ent[2]); if(portalLevel < getMinPortalLevel() && ent[0] != selectedPortal) return; - if(!isResonatorsShow()) return; - - for(var i=0; i < ent[2].resonatorArray.resonators.length; i++) { + var layerGroup = portalsLayers[parseInt(portalLevel)]; + var reRendered = false; + for(var i = 0; i < ent[2].resonatorArray.resonators.length; i++) { var rdata = ent[2].resonatorArray.resonators[i]; - if(rdata == null) continue; + // skip if resonator didn't change + if(portalLayer) { + var oldRes = findEntityInLeaflet(layerGroup, window.resonators, portalResonatorGuid(ent[0], i)); + if(oldRes && isSameResonator(oldRes.options.details, rdata)) continue; + } - if(window.resonators[portalResonatorGuid(ent[0],i)]) continue; + // skip and remove old resonator if no new resonator + if(rdata === null) { + if(oldRes) removeByGuid(oldRes.options.guid); + continue; + } // offset in meters var dn = rdata.distanceToPortal*SLOT_TO_LAT[rdata.slot]; @@ -332,13 +341,16 @@ window.renderResonators = function(ent) { level: rdata.level, details: rdata, pDetails: ent[2], - guid: portalResonatorGuid(ent[0],i) }); + guid: portalResonatorGuid(ent[0], i) }); r.on('remove', function() { delete window.resonators[this.options.guid]; }); r.on('add', function() { window.resonators[this.options.guid] = this; }); r.addTo(portalsLayers[parseInt(portalLevel)]); + reRendered = true; } + // if there is any resonator re-rendered, bring portal to front + if(reRendered && portalLayer) portalLayer.bringToFront(); } // append portal guid with -resonator-[slot] to get guid for resonators @@ -350,6 +362,15 @@ window.isResonatorsShow = function() { return map.getZoom() >= RESONATOR_DISPLAY_ZOOM_LEVEL; } +window.isSameResonator = function(oldRes, newRes) { + if(!oldRes && !newRes) return true; + if(typeof oldRes !== typeof newRes) return false; + if(oldRes.level !== newRes.level) return false; + if(oldRes.energyTotal !== newRes.energyTotal) return false; + if(oldRes.distanceToPortal !== newRes.distanceToPortal) return false; + return true; +} + window.portalResetColor = function(portal) { portal.setStyle({color: portal.options.fillColor}); } From 79b917c8f1b6e9e7bb5edee4a54e0dedddb79f81 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 03:22:01 +0100 Subject: [PATCH 17/46] divider bar too short --- code/chat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/chat.js b/code/chat.js index faf7f0b9..4e7b7893 100644 --- a/code/chat.js +++ b/code/chat.js @@ -324,7 +324,7 @@ window.chat.renderData = function(data, element, likelyWereOldMsgs) { window.chat.renderDivider = function(text) { - return '─ '+text+' ───────────────────────────────────────────────────────────'; + return '─ '+text+' ──────────────────────────────────────────────────────────────────────────'; } From ae65dff2d9d9b79d948ab9a4273859f8141abef4 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 04:10:40 +0100 Subject: [PATCH 18/46] * ditch jQueryUI vanilla styles in favor of own ones. * disable tracking for tooltips and make them behave more like regular ones (this also stops my fan from spinning up when using the intel map) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Improvements welcome. Tooltips are currently placed at the bottom of the element instead of next to cursor. It seems it’s either tracking or placing it not anywhere where one would expect a tooltip. I immediately regret having chosen jQueryUI. It’s not very flexible and has awkward defaults. --- code/boot.js | 7 ++++--- main.js | 3 +-- style.css | 18 ++++++++++++++---- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/code/boot.js b/code/boot.js index a0c7a591..7b1956a9 100644 --- a/code/boot.js +++ b/code/boot.js @@ -191,11 +191,12 @@ window.setupSidebarToggle = function() { window.setupTooltips = function() { $(document).tooltip({ - // enable mouse tracking - track: true, // disable show/hide animation - show: false, + show: { effect: "hide", duration: 0 } , hide: false, + open: function(event, ui) { + ui.tooltip.delay(300).fadeIn(0); + }, content: function() { var title = $(this).attr('title'); diff --git a/main.js b/main.js index e0af1db1..b190399e 100644 --- a/main.js +++ b/main.js @@ -57,8 +57,7 @@ document.getElementsByTagName('head')[0].innerHTML = '' + 'Ingress Intel Map' + '' + '' - + '' - + ''; + + ''; document.getElementsByTagName('body')[0].innerHTML = '' + '
Loading, please wait
' diff --git a/style.css b/style.css index 15a033d3..f179dc6a 100644 --- a/style.css +++ b/style.css @@ -450,10 +450,6 @@ h3 { border: 1px solid #666; } -.mods span[title=""] { - cursor: auto; -} - .res .mods span, .res .meter { border: 1px solid #0076b6; } @@ -616,3 +612,17 @@ aside:nth-child(odd) span { #largepreview img { border: 2px solid #f8ff5e; } + +/* tooltips */ +.ui-tooltip { + background: #1E425D; + border: 1px solid #20A8B1; + box-shadow:0 0 7px #000; + color: #EEEEEE; + font-family: Verdana, sans-serif; + font-size:13px; + max-width: 300px; + padding: 8px; + position: absolute; + z-index: 9999; +} From 21943d7155f4353bcb1dd794c6a53273d3c9282a Mon Sep 17 00:00:00 2001 From: vita10gy Date: Tue, 12 Feb 2013 21:39:56 -0600 Subject: [PATCH 19/46] Change Selected color back to red --- main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.js b/main.js index 6460139c..64a0967d 100644 --- a/main.js +++ b/main.js @@ -125,7 +125,7 @@ var MAX_DRAWN_LINKS = 400; var MAX_DRAWN_FIELDS = 200; -var COLOR_SELECTED_PORTAL = '#fff'; +var COLOR_SELECTED_PORTAL = '#f00'; var COLORS = ['#FFCE00', '#0088FF', '#03FE03']; // none, res, enl var COLORS_LVL = ['#000', '#FECE5A', '#FFA630', '#FF7315', '#E40000', '#FD2992', '#EB26CD', '#C124E0', '#9627F4']; var COLORS_MOD = {VERY_RARE: '#F78AF6', RARE: '#AD8AFF', COMMON: '#84FBBD'}; From 43a6adad14675e1a5a186211fda5a3b9c2b8efd2 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 04:59:36 +0100 Subject: [PATCH 20/46] make many variables overwritable by plugins --- main.js | 61 +++++++++++++++++++++++++++------------------------------ 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/main.js b/main.js index b190399e..320d0c9a 100644 --- a/main.js +++ b/main.js @@ -97,49 +97,55 @@ function wrapper() { L_PREFER_CANVAS = false; // CONFIG OPTIONS //////////////////////////////////////////////////// -var REFRESH = 30; // refresh view every 30s (base time) -var ZOOM_LEVEL_ADJ = 5; // add 5 seconds per zoom level -var REFRESH_GAME_SCORE = 5*60; // refresh game score every 5 minutes -var MAX_IDLE_TIME = 4; // stop updating map after 4min idling -var PRECACHE_PLAYER_NAMES_ZOOM = 17; // zoom level to start pre-resolving player names -var HIDDEN_SCROLLBAR_ASSUMED_WIDTH = 20; -var SIDEBAR_WIDTH = 300; +window.REFRESH = 30; // refresh view every 30s (base time) +window.ZOOM_LEVEL_ADJ = 5; // add 5 seconds per zoom level +window.REFRESH_GAME_SCORE = 5*60; // refresh game score every 5 minutes +window.MAX_IDLE_TIME = 4; // stop updating map after 4min idling +window.PRECACHE_PLAYER_NAMES_ZOOM = 17; // zoom level to start pre-resolving player names +window.HIDDEN_SCROLLBAR_ASSUMED_WIDTH = 20; +window.SIDEBAR_WIDTH = 300; // chat messages are requested for the visible viewport. On high zoom // levels this gets pretty pointless, so request messages in at least a // X km radius. -var CHAT_MIN_RANGE = 6; +window.CHAT_MIN_RANGE = 6; // this controls how far data is being drawn outside the viewport. Set // it 0 to only draw entities that intersect the current view. A value // of one will render an area twice the size of the viewport (or some- // thing like that, Leaflet doc isn’t too specific). Setting it too low // makes the missing data on move/zoom out more obvious. Setting it too // high causes too many items to be drawn, making drag&drop sluggish. -var VIEWPORT_PAD_RATIO = 0.3; +window.VIEWPORT_PAD_RATIO = 0.3; // how many items to request each query -var CHAT_PUBLIC_ITEMS = 200; -var CHAT_FACTION_ITEMS = 50; +window.CHAT_PUBLIC_ITEMS = 200; +window.CHAT_FACTION_ITEMS = 50; // how many pixels to the top before requesting new data -var CHAT_REQUEST_SCROLL_TOP = 200; +window.CHAT_REQUEST_SCROLL_TOP = 200; +window.CHAT_SHRINKED = 60; // Leaflet will get very slow for MANY items. It’s better to display // only some instead of crashing the browser. -var MAX_DRAWN_PORTALS = 1000; -var MAX_DRAWN_LINKS = 400; -var MAX_DRAWN_FIELDS = 200; +window.MAX_DRAWN_PORTALS = 1000; +window.MAX_DRAWN_LINKS = 400; +window.MAX_DRAWN_FIELDS = 200; +// Minimum zoom level resonator will display +window.RESONATOR_DISPLAY_ZOOM_LEVEL = 17; - -var COLOR_SELECTED_PORTAL = '#f00'; -var COLORS = ['#FFCE00', '#0088FF', '#03FE03']; // none, res, enl -var COLORS_LVL = ['#000', '#FECE5A', '#FFA630', '#FF7315', '#E40000', '#FD2992', '#EB26CD', '#C124E0', '#9627F4']; -var COLORS_MOD = {VERY_RARE: '#F78AF6', RARE: '#AD8AFF', COMMON: '#84FBBD'}; +window.COLOR_SELECTED_PORTAL = '#f00'; +window.COLORS = ['#FFCE00', '#0088FF', '#03FE03']; // none, res, enl +window.COLORS_LVL = ['#000', '#FECE5A', '#FFA630', '#FF7315', '#E40000', '#FD2992', '#EB26CD', '#C124E0', '#9627F4']; +window.COLORS_MOD = {VERY_RARE: '#F78AF6', RARE: '#AD8AFF', COMMON: '#84FBBD'}; // circles around a selected portal that show from where you can hack // it and how far the portal reaches (i.e. how far links may be made // from this portal) -var ACCESS_INDICATOR_COLOR = 'orange'; -var RANGE_INDICATOR_COLOR = 'red'; +window.ACCESS_INDICATOR_COLOR = 'orange'; +window.RANGE_INDICATOR_COLOR = 'red'; + + +window.DEFAULT_PORTAL_IMG = 'http://commondatastorage.googleapis.com/ingress/img/default-portal-image.png'; +window.NOMINATIM = 'http://nominatim.openstreetmap.org/search?format=json&limit=1&q='; // INGRESS CONSTANTS ///////////////////////////////////////////////// // http://decodeingress.me/2012/11/18/ingress-portal-levels-and-link-range/ @@ -148,28 +154,19 @@ var MAX_XM_PER_LEVEL = [0, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000]; var MIN_AP_FOR_LEVEL = [0, 10000, 30000, 70000, 150000, 300000, 600000, 1200000]; var HACK_RANGE = 40; // in meters, max. distance from portal to be able to access it var OCTANTS = ['E', 'NE', 'N', 'NW', 'W', 'SW', 'S', 'SE']; -var DEFAULT_PORTAL_IMG = 'http://commondatastorage.googleapis.com/ingress/img/default-portal-image.png'; var DESTROY_RESONATOR = 75; //AP for destroying portal var DESTROY_LINK = 187; //AP for destroying link var DESTROY_FIELD = 750; //AP for destroying field // OTHER MORE-OR-LESS CONSTANTS ////////////////////////////////////// -var NOMINATIM = 'http://nominatim.openstreetmap.org/search?format=json&limit=1&q='; -var DEG2RAD = Math.PI / 180; var TEAM_NONE = 0, TEAM_RES = 1, TEAM_ENL = 2; var TEAM_TO_CSS = ['none', 'res', 'enl']; var TYPE_UNKNOWN = 0, TYPE_PORTAL = 1, TYPE_LINK = 2, TYPE_FIELD = 3, TYPE_PLAYER = 4, TYPE_CHAT = 5, TYPE_RESONATOR = 6; -// make PLAYER variable available in site context -var PLAYER = window.PLAYER; -var CHAT_SHRINKED = 60; -// Minimum zoom level resonator will display -var RESONATOR_DISPLAY_ZOOM_LEVEL = 17; - -// Constants for resonator positioning var SLOT_TO_LAT = [0, Math.sqrt(2)/2, 1, Math.sqrt(2)/2, 0, -Math.sqrt(2)/2, -1, -Math.sqrt(2)/2]; var SLOT_TO_LNG = [1, Math.sqrt(2)/2, 0, -Math.sqrt(2)/2, -1, -Math.sqrt(2)/2, 0, Math.sqrt(2)/2]; var EARTH_RADIUS=6378137; +var DEG2RAD = Math.PI / 180; // STORAGE /////////////////////////////////////////////////////////// // global variables used for storage. Most likely READ ONLY. Proper From 7e70c0a8bbcce0de0d78159ffa68f34ec27449fb Mon Sep 17 00:00:00 2001 From: vita10gy Date: Tue, 12 Feb 2013 23:44:10 -0600 Subject: [PATCH 21/46] Ditched orange, introduced dashes Ditched orange as the indicator of missing resonator in favor of dashed circle. Corrected /plugin/Readme.md --- README.md | 1 + plugins/README.md | 5 +++-- plugins/show-portal-weakness.user.js | 14 +++++++------- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index bdbe428d..af629764 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ Contributors [sorgo](https://github.com/sorgo), [Xelio](https://github.com/Xelio), [ZauberNerd](https://github.com/ZauberNerd) +[vita10gy](https://github.com/vita10gy) Hacking diff --git a/plugins/README.md b/plugins/README.md index 891daddd..779f22df 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -10,13 +10,14 @@ Available Plugins ----------------- - [**Guess Player Level**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/guess-player-levels.user.js) looks for the highest placed resonator per player in the current view to guess the player level. -- [**Highlight Weakened Portals**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/show-portal-weakness.user.js) fill portals with red or orange to indicate portal's state of disrepair. The brighter the color the more attention needed (recharge, shields, resonators). Red means general attention needed. Orange means at least one resonator is gone. +- [**Highlight Weakened Portals**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/show-portal-weakness.user.js) fill portals with red or orange to indicate portal's state of disrepair. The brighter the color the more attention needed (recharge, shields, resonators). A dashed portal means a resonator is missing. Hacking ------- -Plugins may be developed in the same way as the total conversion script. Plugins may provide features tailored to specific needs and are allowed to change things as they see fit. You can provide them separately oder submit a pull request to have them managed in this repository. There are currently no hooks that allow integration with the main script, but I will add those if the need arises. Simply open a bug report. +Plugins may be developed in the same way as the total conversion script. Plugins may provide features tailored to specific needs and are allowed to change things as they see fit. You can provide them separately or submit a pull request to have them managed in this repository. +If you think a hook in the main script is required, simply open a bug report. You can use the guess player level script as an example to get you started. Just update the names and the part between `// PLUGIN START` and `// PLUGIN END` and you should be able to develop your plugin. The other code ensures your plugin is executed after the main script. diff --git a/plugins/show-portal-weakness.user.js b/plugins/show-portal-weakness.user.js index 34647d78..48e60682 100644 --- a/plugins/show-portal-weakness.user.js +++ b/plugins/show-portal-weakness.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @id iitc-plugin-show-portal-weakness@vita10gy // @name iitc: show portal weakness -// @version 0.1 +// @version 0.2 // @namespace https://github.com/breunigs/ingress-intel-total-conversion // @updateURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/show-portal-weekness.user.js // @downloadURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/show-portal-weekness.user.js @@ -74,7 +74,7 @@ window.plugin.portalWeakness.portalAdded = function(data) { { if(mod == null) { - portal_weakness += .05; + portal_weakness += .03; } }); //Ding the portal for every missing resonator. @@ -99,20 +99,20 @@ window.plugin.portalWeakness.portalAdded = function(data) { if(portal_weakness>0) { var color = 'red'; + var fill_opacity = Math.round((portal_weakness*.8 + .2)*100)/100; + var params = {fillColor: color, fillOpacity: fill_opacity, radius: data.portal.options.radius+1}; if(resCount<8) { - color = 'orange'; + params["dashArray"] = "4,6"; } - var fill_opacity = Math.round((portal_weakness*.7 + .3)*100)/100; - data.portal.setStyle({fillColor: color, fillOpacity: fill_opacity}); + data.portal.setStyle(params); } } - - } var setup = function() { window.addHook('portalAdded', window.plugin.portalWeakness.portalAdded); + window.COLOR_SELECTED_PORTAL = '#f0f'; } // PLUGIN END ////////////////////////////////////////////////////////// From aa89e348f484f3799cac3e1c355fabad453005dd Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 10:04:10 +0100 Subject: [PATCH 22/46] fixes in readme, also add Leaflet.draw attribution --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index af629764..f8f334e3 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ Features - hack range (yellow circle) and link range (large red circle) for portals. Click on the range link in the sidebar to zoom to link range. - double clicking a portal zooms in and focuses it - display of XM and AP rewards for redeemed passcodes +- [extend it even more with the use of plugins](https://github.com/breunigs/ingress-intel-total-conversion/plugins) Install @@ -70,9 +71,7 @@ Please do! (Obviously, Resistance folks must send in complete patches while Enlightenment gals and guys may just open feature request ☺) - -Contributors ------------- +**So far, these people have contributed:** [Bananeweizen](https://github.com/Bananeweizen), [cmrn](https://github.com/cmrn), @@ -85,9 +84,9 @@ Contributors [Pirozek](https://github.com/Pirozek), [Scrool](https://github.com/Scrool), [sorgo](https://github.com/sorgo), +[vita10gy](https://github.com/vita10gy), [Xelio](https://github.com/Xelio), [ZauberNerd](https://github.com/ZauberNerd) -[vita10gy](https://github.com/vita10gy) Hacking @@ -116,9 +115,10 @@ Attribution & License This project is licensed under the permissive ISC license. Parts imported from other projects remain under their respective licenses: -- [load.js by Chris O'Hara; MIT](https://github.com/chriso/load.js) - [autolink-js by Bryan Woods; MIT](https://github.com/bryanwoods/autolink-js) +- [load.js by Chris O'Hara; MIT](https://github.com/chriso/load.js) - [leaflet.js; custom license (but appears free)](http://leafletjs.com/) +- [leaflet.draw.js; by jacobtoye; MIT](https://github.com/Leaflet/Leaflet.draw) - [`leaflet_google.js` by Pavel Shramov; same as Leaftlet](https://github.com/shramov/leaflet-plugins) (modified, though) - StackOverflow-CopyPasta is attributed in the source; [CC-Wiki](https://creativecommons.org/licenses/by-sa/3.0/) - all Ingress/Niantic related stuff obviously remains non-free and is still copyrighted by Niantic/Google From 939c87cf206419e5fe6944a9e9b77d2042b80aae Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 10:04:27 +0100 Subject: [PATCH 23/46] add note about how to handle external dependencies --- plugins/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/README.md b/plugins/README.md index 779f22df..c5d1b10d 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -23,6 +23,11 @@ You can use the guess player level script as an example to get you started. Just If you happen the write general purpose functions for your plugin, consider adding them to the main script instead. For example, if you write a `getResoCountFromPortal(details)` function it may be very well added to `code/portal_info.js`. +External Dependencies +--------------------- + +If you have external dependencies put them into `external/` and add a version number to their filename. I will put them in `dist/` once required. Don’t forget to add a note about author and license in main `README.md`. + Available Hooks --------------- From d32dd2d80cdc7fb8a7e8e1cebcadfc7a82039568 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 10:04:43 +0100 Subject: [PATCH 24/46] support more external files and images --- pack-release.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pack-release.sh b/pack-release.sh index 8ffd8790..d19213e7 100755 --- a/pack-release.sh +++ b/pack-release.sh @@ -3,7 +3,7 @@ ./build.py cp iitc-debug.user.js dist/total-conversion-build.user.js cp style.css dist/style.css -cp external/leaflet_google.js dist/leaflet_google.js -cp external/autolink.js dist/autolink.js +cp external/* dist/ +cp -r images/ dist/images echo 'Change path of style.css to dist/style.css' From 090e52720340f09efda8fc0cdc13c9fdb783cc66 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 10:07:08 +0100 Subject: [PATCH 25/46] add leaflet.draw to available dependencies --- dist/images/draw-circle.png | Bin 0 -> 1066 bytes dist/images/draw-marker-icon.png | Bin 0 -> 311 bytes dist/images/draw-polygon.png | Bin 0 -> 318 bytes dist/images/draw-polyline.png | Bin 0 -> 266 bytes dist/images/draw-rectangle.png | Bin 0 -> 138 bytes dist/leaflet.draw.0.1.6.css | 118 +++++++++++++++++++++++++++++++ dist/leaflet.draw.0.1.6.js | 6 ++ external/leaflet.draw.0.1.6.css | 118 +++++++++++++++++++++++++++++++ external/leaflet.draw.0.1.6.js | 6 ++ images/draw-circle.png | Bin 0 -> 1066 bytes images/draw-marker-icon.png | Bin 0 -> 311 bytes images/draw-polygon.png | Bin 0 -> 318 bytes images/draw-polyline.png | Bin 0 -> 266 bytes images/draw-rectangle.png | Bin 0 -> 138 bytes 14 files changed, 248 insertions(+) create mode 100644 dist/images/draw-circle.png create mode 100644 dist/images/draw-marker-icon.png create mode 100644 dist/images/draw-polygon.png create mode 100644 dist/images/draw-polyline.png create mode 100644 dist/images/draw-rectangle.png create mode 100644 dist/leaflet.draw.0.1.6.css create mode 100644 dist/leaflet.draw.0.1.6.js create mode 100644 external/leaflet.draw.0.1.6.css create mode 100644 external/leaflet.draw.0.1.6.js create mode 100644 images/draw-circle.png create mode 100644 images/draw-marker-icon.png create mode 100644 images/draw-polygon.png create mode 100644 images/draw-polyline.png create mode 100644 images/draw-rectangle.png diff --git a/dist/images/draw-circle.png b/dist/images/draw-circle.png new file mode 100644 index 0000000000000000000000000000000000000000..0cb17b8f17fc58fff797a0feeccd29ce6b6cca38 GIT binary patch literal 1066 zcmaJ=O-vI(7~Lom#YG8;Nl^}y#RC$$zb&Pk7A)OX8ZDC2NG}+c-J#vU?yS25Eu0WY zMWZGrcrYOb5d#NX2wC20_YH^DqNdedgL57@?@c zz{uusE`3SXkjbhZhAo*kVN+D3w`8l@1jJwr<_#;#{CxJD0fruBhJ$H7ZO383=%01q z(Ck1~o1M_YI@8+&A|;s!m=LR=WKLSHT#7Qgx-waN#~cH8A$TIn?3v1?2SFS;5CmD? zukl?x=n_~#3WP$TP9X9E&+#HBh<+g?OQOv4pz<*!nxl`)86{bXMRrl9fUzxeT(MYW zixP{RJST+1VNXL8{RH86XDqCi{Fd8RRZyU-Ifji5WC2f69Ya$%$`Ge}DVX-YtmRh9 zL<+{0RGSl6-b<+pOsD@3HO+mri!<=R?>~jz?2HY$40O?yqmhdnZ}URga@>I`Mot!? z$!Zk`3kV~(fNT&S3W8z7(oxafMW@qp%5t%4X)vWk8Nz1`Lze|99_SX6fxdtu2tq=L z36dC(#U)-$^4(%0T;(cAn=+w=t6cqn8?4Fo8o{(lWCc3LG}Mz0GQn=bvQgWMSW~aU z)oXi^YH~SZhV!oVuWPOzk>2r^`%OzW`)v;`((4XsYW?X-iadzbloHGOhPB_DbH`t{ zC(4iMow?g*XsJcH_sG}h>yh4$F6s8@63o5+b?Zfa$B~cQ57wI6>4kUnW#1ym{Fswl z2fvJ!k2O8nq#qVC+w}1DEqaCSeSfyqcgT13>xcWV?0RNnS?wr~+-W*@s*LE3{^k*S zbB(QQUOylI&VQ2@g=K0glIN2r8jaP@hv}0o(?Vb#gOs{J-MDDj`K>E=z1N#c3@Gb; Hqw{|N5l2ws literal 0 HcmV?d00001 diff --git a/dist/images/draw-marker-icon.png b/dist/images/draw-marker-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f26437fc1ae98ccfc91765131222fd1995f4fa71 GIT binary patch literal 311 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uGBwbBK{D72XiEBhjaDG}zd16s2gJVj5QmTSy zZen_BP-%>CN3^6At3?eN=iz?$tqhh1E7BKk|4ie1_1?!koe5{hR*&e^H;6kvj5cm`>)=A zd1SQgBTz|_r;B3=b-0qIGq6vTMKK^!ds9d*W9@B;AGi@1) e&oO9ZGuGd(VJVxaQ1K9G8-u5-pUXO@geCw#AzVKI literal 0 HcmV?d00001 diff --git a/dist/images/draw-polygon.png b/dist/images/draw-polygon.png new file mode 100644 index 0000000000000000000000000000000000000000..579102ddb69e7ead8e7e8f757dfc487de367acb9 GIT binary patch literal 318 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2@wC9V-A!TD(=<%vb942~)JNvR5+ zxryniL8*x;m4zo$ZGeg%c)B=-RNR^}aUtI!2cEY6#^fZS&I87sa~wW%JrL|Mm&j+} zoW{U+yrNmsq~gc~VU=hmCieQ1^(RvcPG)@4-5d9R+jY&ax!GTrcRpZs3uT>D!R|dF zOz?*SyCTPdqnCV>CR)f@H1e`C9<_XLqqbbewnU;p^HLdG_=faPENc!hA5rRZWZ&Yo zIOm}7nFAsz57dsn`XM5-kiV}@O69ItLWbZDof$Kf zHdhZbIovJpu>^C#$ptWRk1 zIrhnZ#TSho>eqc>{WHb*SPop1z5KuAMWW*)3!#OH_8kdI$14}ldao(t.y-e.y)*(n.x-e.x)}}),L.Polyline.include({intersects:function(){var e=this._originalPoints,t=e?e.length:0,n,r,i,s,o,u;if(this._tooFewPointsForIntersection())return!1;for(n=t-1;n>=3;n--){i=e[n-1],s=e[n];if(this._lineSegmentsIntersectsRange(i,s,n-2))return!0}return!1},newLatLngIntersects:function(e,t){return this._map?this.newPointIntersects(this._map.latLngToLayerPoint(e),t):!1},newPointIntersects:function(e,t){var n=this._originalPoints,r=n?n.length:0,i=n?n[r-1]:null,s=r-2;return this._tooFewPointsForIntersection(1)?!1:this._lineSegmentsIntersectsRange(i,e,s,t?1:0)},_tooFewPointsForIntersection:function(e){var t=this._originalPoints,n=t?t.length:0;return n+=e||0,!this._originalPoints||n<=3},_lineSegmentsIntersectsRange:function(e,t,n,r){var i=this._originalPoints,s,o;r=r||0;for(var u=n;u>r;u--){s=i[u-1],o=i[u];if(L.LineUtil.segmentsIntersect(e,t,s,o))return!0}return!1}}),L.Polygon.include({intersects:function(){var e,t=this._originalPoints,n,r,i,s;return this._tooFewPointsForIntersection()?!1:(e=L.Polyline.prototype.intersects.call(this),e?!0:(n=t.length,r=t[0],i=t[n-1],s=n-2,this._lineSegmentsIntersectsRange(i,r,s,1)))}}),L.Handler.Draw=L.Handler.extend({includes:L.Mixin.Events,initialize:function(e,t){this._map=e,this._container=e._container,this._overlayPane=e._panes.overlayPane,this._popupPane=e._panes.popupPane,t&&t.shapeOptions&&(t.shapeOptions=L.Util.extend({},this.options.shapeOptions,t.shapeOptions)),L.Util.extend(this.options,t)},enable:function(){this.fire("activated"),this._map.fire("drawing",{drawingType:this.type}),L.Handler.prototype.enable.call(this)},disable:function(){this._map.fire("drawing-disabled",{drawingType:this.type}),L.Handler.prototype.disable.call(this)},addHooks:function(){this._map&&(L.DomUtil.disableTextSelection(),this._label=L.DomUtil.create("div","leaflet-draw-label",this._popupPane),this._singleLineLabel=!1,L.DomEvent.addListener(this._container,"keyup",this._cancelDrawing,this))},removeHooks:function(){this._map&&(L.DomUtil.enableTextSelection(),this._popupPane.removeChild(this._label),delete this._label,L.DomEvent.removeListener(this._container,"keyup",this._cancelDrawing))},_updateLabelText:function(e){e.subtext=e.subtext||"",e.subtext.length===0&&!this._singleLineLabel?(L.DomUtil.addClass(this._label,"leaflet-draw-label-single"),this._singleLineLabel=!0):e.subtext.length>0&&this._singleLineLabel&&(L.DomUtil.removeClass(this._label,"leaflet-draw-label-single"),this._singleLineLabel=!1),this._label.innerHTML=(e.subtext.length>0?''+e.subtext+""+"
":"")+""+e.text+""},_updateLabelPosition:function(e){L.DomUtil.setPosition(this._label,e)},_cancelDrawing:function(e){e.keyCode===27&&this.disable()}}),L.Polyline.Draw=L.Handler.Draw.extend({Poly:L.Polyline,type:"polyline",options:{allowIntersection:!0,drawError:{color:"#b00b00",message:"Error: shape edges cannot cross!",timeout:2500},icon:new L.DivIcon({iconSize:new L.Point(8,8),className:"leaflet-div-icon leaflet-editing-icon"}),guidelineDistance:20,shapeOptions:{stroke:!0,color:"#f06eaa",weight:4,opacity:.5,fill:!1,clickable:!0},zIndexOffset:2e3},initialize:function(e,t){t&&t.drawError&&(t.drawError=L.Util.extend({},this.options.drawError,t.drawError)),L.Handler.Draw.prototype.initialize.call(this,e,t)},addHooks:function(){L.Handler.Draw.prototype.addHooks.call(this),this._map&&(this._markers=[],this._markerGroup=new L.LayerGroup,this._map.addLayer(this._markerGroup),this._poly=new L.Polyline([],this.options.shapeOptions),this._updateLabelText(this._getLabelText()),this._mouseMarker||(this._mouseMarker=L.marker(this._map.getCenter(),{icon:L.divIcon({className:"leaflet-mouse-marker",iconAnchor:[20,20],iconSize:[40,40]}),opacity:0,zIndexOffset:this.options.zIndexOffset})),this._mouseMarker.on("click",this._onClick,this).addTo(this._map),this._map.on("mousemove",this._onMouseMove,this))},removeHooks:function(){L.Handler.Draw.prototype.removeHooks.call(this),this._clearHideErrorTimeout(),this._cleanUpShape(),this._map.removeLayer(this._markerGroup),delete this._markerGroup,delete this._markers,this._map.removeLayer(this._poly),delete this._poly,this._mouseMarker.off("click",this._onClick),this._map.removeLayer(this._mouseMarker),delete this._mouseMarker,this._clearGuides(),this._map.off("mousemove",this._onMouseMove)},_finishShape:function(){if(!this.options.allowIntersection&&this._poly.newLatLngIntersects(this._poly.getLatLngs()[0],!0)){this._showErrorLabel();return}if(!this._shapeIsValid()){this._showErrorLabel();return}this._map.fire("draw:poly-created",{poly:new this.Poly(this._poly.getLatLngs(),this.options.shapeOptions)}),this.disable()},_shapeIsValid:function(){return!0},_onMouseMove:function(e){var t=e.layerPoint,n=e.latlng,r=this._markers.length;this._currentLatLng=n,this._updateLabelPosition(t),r>0&&(this._updateLabelText(this._getLabelText()),this._clearGuides(),this._drawGuide(this._map.latLngToLayerPoint(this._markers[r-1].getLatLng()),t)),this._mouseMarker.setLatLng(n),L.DomEvent.preventDefault(e.originalEvent)},_onClick:function(e){var t=e.target.getLatLng(),n=this._markers.length;if(n>0&&!this.options.allowIntersection&&this._poly.newLatLngIntersects(t)){this._showErrorLabel();return}this._errorShown&&this._hideErrorLabel(),this._markers.push(this._createMarker(t)),this._poly.addLatLng(t),this._poly.getLatLngs().length===2&&this._map.addLayer(this._poly),this._updateMarkerHandler(),this._vertexAdded(t)},_updateMarkerHandler:function(){this._markers.length>1&&this._markers[this._markers.length-1].on("click",this._finishShape,this),this._markers.length>2&&this._markers[this._markers.length-2].off("click",this._finishShape)},_createMarker:function(e){var t=new L.Marker(e,{icon:this.options.icon,zIndexOffset:this.options.zIndexOffset*2});return this._markerGroup.addLayer(t),t},_drawGuide:function(e,t){var n=Math.floor(Math.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2))),r,i,s,o;this._guidesContainer||(this._guidesContainer=L.DomUtil.create("div","leaflet-draw-guides",this._overlayPane));for(r=this.options.guidelineDistance;r1e3?(t/1e3).toFixed(2)+" km":Math.ceil(t)+" m",this._markers.length===1?e={text:"Click to continue drawing line.",subtext:n}:e={text:"Click last point to finish line.",subtext:n}),e},_showErrorLabel:function(){this._errorShown=!0,L.DomUtil.addClass(this._label,"leaflet-error-draw-label"),L.DomUtil.addClass(this._label,"leaflet-flash-anim"),L.Handler.Draw.prototype._updateLabelText.call(this,{text:this.options.drawError.message}),this._updateGuideColor(this.options.drawError.color),this._poly.setStyle({color:this.options.drawError.color}),this._clearHideErrorTimeout(),this._hideErrorTimeout=setTimeout(L.Util.bind(this._hideErrorLabel,this),this.options.drawError.timeout)},_hideErrorLabel:function(){this._errorShown=!1,this._clearHideErrorTimeout(),L.DomUtil.removeClass(this._label,"leaflet-error-draw-label"),L.DomUtil.removeClass(this._label,"leaflet-flash-anim"),this._updateLabelText(this._getLabelText()),this._updateGuideColor(this.options.shapeOptions.color),this._poly.setStyle({color:this.options.shapeOptions.color})},_clearHideErrorTimeout:function(){this._hideErrorTimeout&&(clearTimeout(this._hideErrorTimeout),this._hideErrorTimeout=null)},_vertexAdded:function(e){this._markers.length===1?this._measurementRunningTotal=0:this._measurementRunningTotal+=e.distanceTo(this._markers[this._markers.length-2].getLatLng())},_cleanUpShape:function(){this._markers.length>0&&this._markers[this._markers.length-1].off("click",this._finishShape)}}),L.Polygon.Draw=L.Polyline.Draw.extend({Poly:L.Polygon,type:"polygon",options:{shapeOptions:{stroke:!0,color:"#f06eaa",weight:4,opacity:.5,fill:!0,fillColor:null,fillOpacity:.2,clickable:!1}},_updateMarkerHandler:function(){this._markers.length===1&&this._markers[0].on("click",this._finishShape,this)},_getLabelText:function(){var e;return this._markers.length===0?e="Click to start drawing shape.":this._markers.length<3?e="Click to continue drawing shape.":e="Click first point to close this shape.",{text:e}},_shapeIsValid:function(){return this._markers.length>=3},_vertexAdded:function(e){},_cleanUpShape:function(){this._markers.length>0&&this._markers[0].off("click",this._finishShape)}}),L.SimpleShape={},L.SimpleShape.Draw=L.Handler.Draw.extend({addHooks:function(){L.Handler.Draw.prototype.addHooks.call(this),this._map&&(this._map.dragging.disable(),this._container.style.cursor="crosshair",this._updateLabelText({text:this._initialLabelText}),this._map.on("mousedown",this._onMouseDown,this).on("mousemove",this._onMouseMove,this))},removeHooks:function(){L.Handler.Draw.prototype.removeHooks.call(this),this._map&&(this._map.dragging.enable(),this._container.style.cursor="",this._map.off("mousedown",this._onMouseDown,this).off("mousemove",this._onMouseMove,this),L.DomEvent.off(document,"mouseup",this._onMouseUp),this._shape&&(this._map.removeLayer(this._shape),delete this._shape)),this._isDrawing=!1},_onMouseDown:function(e){this._isDrawing=!0,this._startLatLng=e.latlng,L.DomEvent.on(document,"mouseup",this._onMouseUp,this).preventDefault(e.originalEvent)},_onMouseMove:function(e){var t=e.layerPoint,n=e.latlng;this._updateLabelPosition(t),this._isDrawing&&(this._updateLabelText({text:"Release mouse to finish drawing."}),this._drawShape(n))},_onMouseUp:function(e){this._shape&&this._fireCreatedEvent(),this.disable()}}),L.Circle.Draw=L.SimpleShape.Draw.extend({type:"circle",options:{shapeOptions:{stroke:!0,color:"#f06eaa",weight:4,opacity:.5,fill:!0,fillColor:null,fillOpacity:.2,clickable:!0}},_initialLabelText:"Click and drag to draw circle.",_drawShape:function(e){this._shape?this._shape.setRadius(this._startLatLng.distanceTo(e)):(this._shape=new L.Circle(this._startLatLng,this._startLatLng.distanceTo(e),this.options.shapeOptions),this._map.addLayer(this._shape))},_fireCreatedEvent:function(){this._map.fire("draw:circle-created",{circ:new L.Circle(this._startLatLng,this._shape.getRadius(),this.options.shapeOptions)})}}),L.Rectangle.Draw=L.SimpleShape.Draw.extend({type:"rectangle",options:{shapeOptions:{stroke:!0,color:"#f06eaa",weight:4,opacity:.5,fill:!0,fillColor:null,fillOpacity:.2,clickable:!0}},_initialLabelText:"Click and drag to draw rectangle.",_drawShape:function(e){this._shape?this._shape.setBounds(new L.LatLngBounds(this._startLatLng,e)):(this._shape=new L.Rectangle(new L.LatLngBounds(this._startLatLng,e),this.options.shapeOptions),this._map.addLayer(this._shape))},_fireCreatedEvent:function(){this._map.fire("draw:rectangle-created",{rect:new L.Rectangle(this._shape.getBounds(),this.options.shapeOptions)})}}),L.Marker.Draw=L.Handler.Draw.extend({type:"marker",options:{icon:new L.Icon.Default,zIndexOffset:2e3},addHooks:function(){L.Handler.Draw.prototype.addHooks.call(this),this._map&&(this._updateLabelText({text:"Click map to place marker."}),this._map.on("mousemove",this._onMouseMove,this))},removeHooks:function(){L.Handler.Draw.prototype.removeHooks.call(this),this._map&&(this._marker&&(this._marker.off("click",this._onClick),this._map.off("click",this._onClick).removeLayer(this._marker),delete this._marker),this._map.off("mousemove",this._onMouseMove))},_onMouseMove:function(e){var t=e.layerPoint,n=e.latlng;this._updateLabelPosition(t),this._marker?this._marker.setLatLng(n):(this._marker=new L.Marker(n,{icon:this.options.icon,zIndexOffset:this.options.zIndexOffset}),this._marker.on("click",this._onClick,this),this._map.on("click",this._onClick,this).addLayer(this._marker))},_onClick:function(e){this._map.fire("draw:marker-created",{marker:new L.Marker(this._marker.getLatLng(),{icon:this.options.icon})}),this.disable()}}),L.Map.mergeOptions({drawControl:!1}),L.Control.Draw=L.Control.extend({options:{position:"topleft",polyline:{title:"Draw a polyline"},polygon:{title:"Draw a polygon"},rectangle:{title:"Draw a rectangle"},circle:{title:"Draw a circle"},marker:{title:"Add a marker"}},initialize:function(e){L.Util.extend(this.options,e)},onAdd:function(e){var t="leaflet-control-draw",n="leaflet-bar",r=n+"-part",i=L.DomUtil.create("div",t+" "+n),s=[];return this.handlers={},this.options.polyline&&(this.handlers.polyline=new L.Polyline.Draw(e,this.options.polyline),s.push(this._createButton(this.options.polyline.title,t+"-polyline "+r,i,this.handlers.polyline.enable,this.handlers.polyline)),this.handlers.polyline.on("activated",this._disableInactiveModes,this)),this.options.polygon&&(this.handlers.polygon=new L.Polygon.Draw(e,this.options.polygon),s.push(this._createButton(this.options.polygon.title,t+"-polygon "+r,i,this.handlers.polygon.enable,this.handlers.polygon)),this.handlers.polygon.on("activated",this._disableInactiveModes,this)),this.options.rectangle&&(this.handlers.rectangle=new L.Rectangle.Draw(e,this.options.rectangle),s.push(this._createButton(this.options.rectangle.title,t+"-rectangle "+r,i,this.handlers.rectangle.enable,this.handlers.rectangle)),this.handlers.rectangle.on("activated",this._disableInactiveModes,this)),this.options.circle&&(this.handlers.circle=new L.Circle.Draw(e,this.options.circle),s.push(this._createButton(this.options.circle.title,t+"-circle "+r,i,this.handlers.circle.enable,this.handlers.circle)),this.handlers.circle.on("activated",this._disableInactiveModes,this)),this.options.marker&&(this.handlers.marker=new L.Marker.Draw(e,this.options.marker),s.push(this._createButton(this.options.marker.title,t+"-marker "+r,i,this.handlers.marker.enable,this.handlers.marker)),this.handlers.marker.on("activated",this._disableInactiveModes,this)),L.DomUtil.addClass(s[0],r+"-top"),L.DomUtil.addClass(s[s.length-1],r+"-bottom"),i},_createButton:function(e,t,n,r,i){var s=L.DomUtil.create("a",t,n);return s.href="#",s.title=e,L.DomEvent.on(s,"click",L.DomEvent.stopPropagation).on(s,"mousedown",L.DomEvent.stopPropagation).on(s,"dblclick",L.DomEvent.stopPropagation).on(s,"click",L.DomEvent.preventDefault).on(s,"click",r,i),s},_disableInactiveModes:function(){for(var e in this.handlers)this.handlers.hasOwnProperty(e)&&this.handlers[e].enabled()&&this.handlers[e].disable()}}),L.Map.addInitHook(function(){this.options.drawControl&&(this.drawControl=new L.Control.Draw,this.addControl(this.drawControl))})})(this); \ No newline at end of file diff --git a/external/leaflet.draw.0.1.6.css b/external/leaflet.draw.0.1.6.css new file mode 100644 index 00000000..c5ad833c --- /dev/null +++ b/external/leaflet.draw.0.1.6.css @@ -0,0 +1,118 @@ +/* Leaflet controls */ + +.leaflet-container .leaflet-control-draw { + margin-left: 13px; + margin-top: 12px; +} + +.leaflet-control-draw a { + background-position: 50% 50%; + background-repeat: no-repeat; + display: block; + width: 22px; + height: 22px; +} + +.leaflet-control-draw a:hover { + background-color: #fff; +} + +.leaflet-touch .leaflet-control-draw a { + width: 27px; + height: 27px; +} + +.leaflet-control-draw-polyline { + background-image: url(images/draw-polyline.png); +} + +.leaflet-control-draw-polygon { + background-image: url(images/draw-polygon.png); +} + +.leaflet-control-draw-rectangle { + background-image: url(images/draw-rectangle.png); +} + +.leaflet-control-draw-circle { + background-image: url(images/draw-circle.png); +} + +.leaflet-control-draw-marker { + background-image: url(images/draw-marker-icon.png); +} + +.leaflet-mouse-marker { + background-color: #fff; + cursor: crosshair; +} + +.leaflet-draw-label { + background-color: #fff; + border: 1px solid #ccc; + color: #222; + font: 12px/18px "Helvetica Neue", Arial, Helvetica, sans-serif; + margin-left: 20px; + margin-top: -21px; + padding: 2px 4px; + position: absolute; + white-space: nowrap; + z-index: 6; +} + +.leaflet-error-draw-label { + background-color: #F2DEDE; + border-color: #E6B6BD; + color: #B94A48; +} + +.leaflet-draw-label-single { + margin-top: -12px +} + +.leaflet-draw-label-subtext { + color: #999; +} + +.leaflet-draw-guide-dash { + font-size: 1%; + opacity: 0.6; + position: absolute; + width: 5px; + height: 5px; +} + +.leaflet-flash-anim { + -webkit-animation-duration: 0.66s; + -moz-animation-duration: 0.66s; + -o-animation-duration: 0.66s; + animation-duration: 0.66s; + -webkit-animation-fill-mode: both; + -moz-animation-fill-mode: both; + -o-animation-fill-mode: both; + animation-fill-mode: both; + -webkit-animation-name: leaflet-flash; + -moz-animation-name: leaflet-flash; + -o-animation-name: leaflet-flash; + animation-name: leaflet-flash; +} + +@-webkit-keyframes leaflet-flash { + 0%, 50%, 100% { opacity: 1; } + 25%, 75% { opacity: 0.3; } +} + +@-moz-keyframes leaflet-flash { + 0%, 50%, 100% { opacity: 1; } + 25%, 75% { opacity: 0.3; } +} + +@-o-keyframes leaflet-flash { + 0%, 50%, 100% { opacity: 1; } + 25%, 75% { opacity: 0.3; } +} + +@keyframes leaflet-flash { + 0%, 50%, 100% { opacity: 1; } + 25%, 75% { opacity: 0; } +} \ No newline at end of file diff --git a/external/leaflet.draw.0.1.6.js b/external/leaflet.draw.0.1.6.js new file mode 100644 index 00000000..49bb67b5 --- /dev/null +++ b/external/leaflet.draw.0.1.6.js @@ -0,0 +1,6 @@ +/* + Copyright (c) 2012, Smartrak, Jacob Toye + Leaflet.draw is an open-source JavaScript library for drawing shapes/markers on leaflet powered maps. + https://github.com/jacobtoye/Leaflet.draw +*/ +(function(e,t){L.drawVersion="0.1.6",L.Util.extend(L.LineUtil,{segmentsIntersect:function(e,t,n,r){return this._checkCounterclockwise(e,n,r)!==this._checkCounterclockwise(t,n,r)&&this._checkCounterclockwise(e,t,n)!==this._checkCounterclockwise(e,t,r)},_checkCounterclockwise:function(e,t,n){return(n.y-e.y)*(t.x-e.x)>(t.y-e.y)*(n.x-e.x)}}),L.Polyline.include({intersects:function(){var e=this._originalPoints,t=e?e.length:0,n,r,i,s,o,u;if(this._tooFewPointsForIntersection())return!1;for(n=t-1;n>=3;n--){i=e[n-1],s=e[n];if(this._lineSegmentsIntersectsRange(i,s,n-2))return!0}return!1},newLatLngIntersects:function(e,t){return this._map?this.newPointIntersects(this._map.latLngToLayerPoint(e),t):!1},newPointIntersects:function(e,t){var n=this._originalPoints,r=n?n.length:0,i=n?n[r-1]:null,s=r-2;return this._tooFewPointsForIntersection(1)?!1:this._lineSegmentsIntersectsRange(i,e,s,t?1:0)},_tooFewPointsForIntersection:function(e){var t=this._originalPoints,n=t?t.length:0;return n+=e||0,!this._originalPoints||n<=3},_lineSegmentsIntersectsRange:function(e,t,n,r){var i=this._originalPoints,s,o;r=r||0;for(var u=n;u>r;u--){s=i[u-1],o=i[u];if(L.LineUtil.segmentsIntersect(e,t,s,o))return!0}return!1}}),L.Polygon.include({intersects:function(){var e,t=this._originalPoints,n,r,i,s;return this._tooFewPointsForIntersection()?!1:(e=L.Polyline.prototype.intersects.call(this),e?!0:(n=t.length,r=t[0],i=t[n-1],s=n-2,this._lineSegmentsIntersectsRange(i,r,s,1)))}}),L.Handler.Draw=L.Handler.extend({includes:L.Mixin.Events,initialize:function(e,t){this._map=e,this._container=e._container,this._overlayPane=e._panes.overlayPane,this._popupPane=e._panes.popupPane,t&&t.shapeOptions&&(t.shapeOptions=L.Util.extend({},this.options.shapeOptions,t.shapeOptions)),L.Util.extend(this.options,t)},enable:function(){this.fire("activated"),this._map.fire("drawing",{drawingType:this.type}),L.Handler.prototype.enable.call(this)},disable:function(){this._map.fire("drawing-disabled",{drawingType:this.type}),L.Handler.prototype.disable.call(this)},addHooks:function(){this._map&&(L.DomUtil.disableTextSelection(),this._label=L.DomUtil.create("div","leaflet-draw-label",this._popupPane),this._singleLineLabel=!1,L.DomEvent.addListener(this._container,"keyup",this._cancelDrawing,this))},removeHooks:function(){this._map&&(L.DomUtil.enableTextSelection(),this._popupPane.removeChild(this._label),delete this._label,L.DomEvent.removeListener(this._container,"keyup",this._cancelDrawing))},_updateLabelText:function(e){e.subtext=e.subtext||"",e.subtext.length===0&&!this._singleLineLabel?(L.DomUtil.addClass(this._label,"leaflet-draw-label-single"),this._singleLineLabel=!0):e.subtext.length>0&&this._singleLineLabel&&(L.DomUtil.removeClass(this._label,"leaflet-draw-label-single"),this._singleLineLabel=!1),this._label.innerHTML=(e.subtext.length>0?''+e.subtext+""+"
":"")+""+e.text+""},_updateLabelPosition:function(e){L.DomUtil.setPosition(this._label,e)},_cancelDrawing:function(e){e.keyCode===27&&this.disable()}}),L.Polyline.Draw=L.Handler.Draw.extend({Poly:L.Polyline,type:"polyline",options:{allowIntersection:!0,drawError:{color:"#b00b00",message:"Error: shape edges cannot cross!",timeout:2500},icon:new L.DivIcon({iconSize:new L.Point(8,8),className:"leaflet-div-icon leaflet-editing-icon"}),guidelineDistance:20,shapeOptions:{stroke:!0,color:"#f06eaa",weight:4,opacity:.5,fill:!1,clickable:!0},zIndexOffset:2e3},initialize:function(e,t){t&&t.drawError&&(t.drawError=L.Util.extend({},this.options.drawError,t.drawError)),L.Handler.Draw.prototype.initialize.call(this,e,t)},addHooks:function(){L.Handler.Draw.prototype.addHooks.call(this),this._map&&(this._markers=[],this._markerGroup=new L.LayerGroup,this._map.addLayer(this._markerGroup),this._poly=new L.Polyline([],this.options.shapeOptions),this._updateLabelText(this._getLabelText()),this._mouseMarker||(this._mouseMarker=L.marker(this._map.getCenter(),{icon:L.divIcon({className:"leaflet-mouse-marker",iconAnchor:[20,20],iconSize:[40,40]}),opacity:0,zIndexOffset:this.options.zIndexOffset})),this._mouseMarker.on("click",this._onClick,this).addTo(this._map),this._map.on("mousemove",this._onMouseMove,this))},removeHooks:function(){L.Handler.Draw.prototype.removeHooks.call(this),this._clearHideErrorTimeout(),this._cleanUpShape(),this._map.removeLayer(this._markerGroup),delete this._markerGroup,delete this._markers,this._map.removeLayer(this._poly),delete this._poly,this._mouseMarker.off("click",this._onClick),this._map.removeLayer(this._mouseMarker),delete this._mouseMarker,this._clearGuides(),this._map.off("mousemove",this._onMouseMove)},_finishShape:function(){if(!this.options.allowIntersection&&this._poly.newLatLngIntersects(this._poly.getLatLngs()[0],!0)){this._showErrorLabel();return}if(!this._shapeIsValid()){this._showErrorLabel();return}this._map.fire("draw:poly-created",{poly:new this.Poly(this._poly.getLatLngs(),this.options.shapeOptions)}),this.disable()},_shapeIsValid:function(){return!0},_onMouseMove:function(e){var t=e.layerPoint,n=e.latlng,r=this._markers.length;this._currentLatLng=n,this._updateLabelPosition(t),r>0&&(this._updateLabelText(this._getLabelText()),this._clearGuides(),this._drawGuide(this._map.latLngToLayerPoint(this._markers[r-1].getLatLng()),t)),this._mouseMarker.setLatLng(n),L.DomEvent.preventDefault(e.originalEvent)},_onClick:function(e){var t=e.target.getLatLng(),n=this._markers.length;if(n>0&&!this.options.allowIntersection&&this._poly.newLatLngIntersects(t)){this._showErrorLabel();return}this._errorShown&&this._hideErrorLabel(),this._markers.push(this._createMarker(t)),this._poly.addLatLng(t),this._poly.getLatLngs().length===2&&this._map.addLayer(this._poly),this._updateMarkerHandler(),this._vertexAdded(t)},_updateMarkerHandler:function(){this._markers.length>1&&this._markers[this._markers.length-1].on("click",this._finishShape,this),this._markers.length>2&&this._markers[this._markers.length-2].off("click",this._finishShape)},_createMarker:function(e){var t=new L.Marker(e,{icon:this.options.icon,zIndexOffset:this.options.zIndexOffset*2});return this._markerGroup.addLayer(t),t},_drawGuide:function(e,t){var n=Math.floor(Math.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2))),r,i,s,o;this._guidesContainer||(this._guidesContainer=L.DomUtil.create("div","leaflet-draw-guides",this._overlayPane));for(r=this.options.guidelineDistance;r1e3?(t/1e3).toFixed(2)+" km":Math.ceil(t)+" m",this._markers.length===1?e={text:"Click to continue drawing line.",subtext:n}:e={text:"Click last point to finish line.",subtext:n}),e},_showErrorLabel:function(){this._errorShown=!0,L.DomUtil.addClass(this._label,"leaflet-error-draw-label"),L.DomUtil.addClass(this._label,"leaflet-flash-anim"),L.Handler.Draw.prototype._updateLabelText.call(this,{text:this.options.drawError.message}),this._updateGuideColor(this.options.drawError.color),this._poly.setStyle({color:this.options.drawError.color}),this._clearHideErrorTimeout(),this._hideErrorTimeout=setTimeout(L.Util.bind(this._hideErrorLabel,this),this.options.drawError.timeout)},_hideErrorLabel:function(){this._errorShown=!1,this._clearHideErrorTimeout(),L.DomUtil.removeClass(this._label,"leaflet-error-draw-label"),L.DomUtil.removeClass(this._label,"leaflet-flash-anim"),this._updateLabelText(this._getLabelText()),this._updateGuideColor(this.options.shapeOptions.color),this._poly.setStyle({color:this.options.shapeOptions.color})},_clearHideErrorTimeout:function(){this._hideErrorTimeout&&(clearTimeout(this._hideErrorTimeout),this._hideErrorTimeout=null)},_vertexAdded:function(e){this._markers.length===1?this._measurementRunningTotal=0:this._measurementRunningTotal+=e.distanceTo(this._markers[this._markers.length-2].getLatLng())},_cleanUpShape:function(){this._markers.length>0&&this._markers[this._markers.length-1].off("click",this._finishShape)}}),L.Polygon.Draw=L.Polyline.Draw.extend({Poly:L.Polygon,type:"polygon",options:{shapeOptions:{stroke:!0,color:"#f06eaa",weight:4,opacity:.5,fill:!0,fillColor:null,fillOpacity:.2,clickable:!1}},_updateMarkerHandler:function(){this._markers.length===1&&this._markers[0].on("click",this._finishShape,this)},_getLabelText:function(){var e;return this._markers.length===0?e="Click to start drawing shape.":this._markers.length<3?e="Click to continue drawing shape.":e="Click first point to close this shape.",{text:e}},_shapeIsValid:function(){return this._markers.length>=3},_vertexAdded:function(e){},_cleanUpShape:function(){this._markers.length>0&&this._markers[0].off("click",this._finishShape)}}),L.SimpleShape={},L.SimpleShape.Draw=L.Handler.Draw.extend({addHooks:function(){L.Handler.Draw.prototype.addHooks.call(this),this._map&&(this._map.dragging.disable(),this._container.style.cursor="crosshair",this._updateLabelText({text:this._initialLabelText}),this._map.on("mousedown",this._onMouseDown,this).on("mousemove",this._onMouseMove,this))},removeHooks:function(){L.Handler.Draw.prototype.removeHooks.call(this),this._map&&(this._map.dragging.enable(),this._container.style.cursor="",this._map.off("mousedown",this._onMouseDown,this).off("mousemove",this._onMouseMove,this),L.DomEvent.off(document,"mouseup",this._onMouseUp),this._shape&&(this._map.removeLayer(this._shape),delete this._shape)),this._isDrawing=!1},_onMouseDown:function(e){this._isDrawing=!0,this._startLatLng=e.latlng,L.DomEvent.on(document,"mouseup",this._onMouseUp,this).preventDefault(e.originalEvent)},_onMouseMove:function(e){var t=e.layerPoint,n=e.latlng;this._updateLabelPosition(t),this._isDrawing&&(this._updateLabelText({text:"Release mouse to finish drawing."}),this._drawShape(n))},_onMouseUp:function(e){this._shape&&this._fireCreatedEvent(),this.disable()}}),L.Circle.Draw=L.SimpleShape.Draw.extend({type:"circle",options:{shapeOptions:{stroke:!0,color:"#f06eaa",weight:4,opacity:.5,fill:!0,fillColor:null,fillOpacity:.2,clickable:!0}},_initialLabelText:"Click and drag to draw circle.",_drawShape:function(e){this._shape?this._shape.setRadius(this._startLatLng.distanceTo(e)):(this._shape=new L.Circle(this._startLatLng,this._startLatLng.distanceTo(e),this.options.shapeOptions),this._map.addLayer(this._shape))},_fireCreatedEvent:function(){this._map.fire("draw:circle-created",{circ:new L.Circle(this._startLatLng,this._shape.getRadius(),this.options.shapeOptions)})}}),L.Rectangle.Draw=L.SimpleShape.Draw.extend({type:"rectangle",options:{shapeOptions:{stroke:!0,color:"#f06eaa",weight:4,opacity:.5,fill:!0,fillColor:null,fillOpacity:.2,clickable:!0}},_initialLabelText:"Click and drag to draw rectangle.",_drawShape:function(e){this._shape?this._shape.setBounds(new L.LatLngBounds(this._startLatLng,e)):(this._shape=new L.Rectangle(new L.LatLngBounds(this._startLatLng,e),this.options.shapeOptions),this._map.addLayer(this._shape))},_fireCreatedEvent:function(){this._map.fire("draw:rectangle-created",{rect:new L.Rectangle(this._shape.getBounds(),this.options.shapeOptions)})}}),L.Marker.Draw=L.Handler.Draw.extend({type:"marker",options:{icon:new L.Icon.Default,zIndexOffset:2e3},addHooks:function(){L.Handler.Draw.prototype.addHooks.call(this),this._map&&(this._updateLabelText({text:"Click map to place marker."}),this._map.on("mousemove",this._onMouseMove,this))},removeHooks:function(){L.Handler.Draw.prototype.removeHooks.call(this),this._map&&(this._marker&&(this._marker.off("click",this._onClick),this._map.off("click",this._onClick).removeLayer(this._marker),delete this._marker),this._map.off("mousemove",this._onMouseMove))},_onMouseMove:function(e){var t=e.layerPoint,n=e.latlng;this._updateLabelPosition(t),this._marker?this._marker.setLatLng(n):(this._marker=new L.Marker(n,{icon:this.options.icon,zIndexOffset:this.options.zIndexOffset}),this._marker.on("click",this._onClick,this),this._map.on("click",this._onClick,this).addLayer(this._marker))},_onClick:function(e){this._map.fire("draw:marker-created",{marker:new L.Marker(this._marker.getLatLng(),{icon:this.options.icon})}),this.disable()}}),L.Map.mergeOptions({drawControl:!1}),L.Control.Draw=L.Control.extend({options:{position:"topleft",polyline:{title:"Draw a polyline"},polygon:{title:"Draw a polygon"},rectangle:{title:"Draw a rectangle"},circle:{title:"Draw a circle"},marker:{title:"Add a marker"}},initialize:function(e){L.Util.extend(this.options,e)},onAdd:function(e){var t="leaflet-control-draw",n="leaflet-bar",r=n+"-part",i=L.DomUtil.create("div",t+" "+n),s=[];return this.handlers={},this.options.polyline&&(this.handlers.polyline=new L.Polyline.Draw(e,this.options.polyline),s.push(this._createButton(this.options.polyline.title,t+"-polyline "+r,i,this.handlers.polyline.enable,this.handlers.polyline)),this.handlers.polyline.on("activated",this._disableInactiveModes,this)),this.options.polygon&&(this.handlers.polygon=new L.Polygon.Draw(e,this.options.polygon),s.push(this._createButton(this.options.polygon.title,t+"-polygon "+r,i,this.handlers.polygon.enable,this.handlers.polygon)),this.handlers.polygon.on("activated",this._disableInactiveModes,this)),this.options.rectangle&&(this.handlers.rectangle=new L.Rectangle.Draw(e,this.options.rectangle),s.push(this._createButton(this.options.rectangle.title,t+"-rectangle "+r,i,this.handlers.rectangle.enable,this.handlers.rectangle)),this.handlers.rectangle.on("activated",this._disableInactiveModes,this)),this.options.circle&&(this.handlers.circle=new L.Circle.Draw(e,this.options.circle),s.push(this._createButton(this.options.circle.title,t+"-circle "+r,i,this.handlers.circle.enable,this.handlers.circle)),this.handlers.circle.on("activated",this._disableInactiveModes,this)),this.options.marker&&(this.handlers.marker=new L.Marker.Draw(e,this.options.marker),s.push(this._createButton(this.options.marker.title,t+"-marker "+r,i,this.handlers.marker.enable,this.handlers.marker)),this.handlers.marker.on("activated",this._disableInactiveModes,this)),L.DomUtil.addClass(s[0],r+"-top"),L.DomUtil.addClass(s[s.length-1],r+"-bottom"),i},_createButton:function(e,t,n,r,i){var s=L.DomUtil.create("a",t,n);return s.href="#",s.title=e,L.DomEvent.on(s,"click",L.DomEvent.stopPropagation).on(s,"mousedown",L.DomEvent.stopPropagation).on(s,"dblclick",L.DomEvent.stopPropagation).on(s,"click",L.DomEvent.preventDefault).on(s,"click",r,i),s},_disableInactiveModes:function(){for(var e in this.handlers)this.handlers.hasOwnProperty(e)&&this.handlers[e].enabled()&&this.handlers[e].disable()}}),L.Map.addInitHook(function(){this.options.drawControl&&(this.drawControl=new L.Control.Draw,this.addControl(this.drawControl))})})(this); \ No newline at end of file diff --git a/images/draw-circle.png b/images/draw-circle.png new file mode 100644 index 0000000000000000000000000000000000000000..0cb17b8f17fc58fff797a0feeccd29ce6b6cca38 GIT binary patch literal 1066 zcmaJ=O-vI(7~Lom#YG8;Nl^}y#RC$$zb&Pk7A)OX8ZDC2NG}+c-J#vU?yS25Eu0WY zMWZGrcrYOb5d#NX2wC20_YH^DqNdedgL57@?@c zz{uusE`3SXkjbhZhAo*kVN+D3w`8l@1jJwr<_#;#{CxJD0fruBhJ$H7ZO383=%01q z(Ck1~o1M_YI@8+&A|;s!m=LR=WKLSHT#7Qgx-waN#~cH8A$TIn?3v1?2SFS;5CmD? zukl?x=n_~#3WP$TP9X9E&+#HBh<+g?OQOv4pz<*!nxl`)86{bXMRrl9fUzxeT(MYW zixP{RJST+1VNXL8{RH86XDqCi{Fd8RRZyU-Ifji5WC2f69Ya$%$`Ge}DVX-YtmRh9 zL<+{0RGSl6-b<+pOsD@3HO+mri!<=R?>~jz?2HY$40O?yqmhdnZ}URga@>I`Mot!? z$!Zk`3kV~(fNT&S3W8z7(oxafMW@qp%5t%4X)vWk8Nz1`Lze|99_SX6fxdtu2tq=L z36dC(#U)-$^4(%0T;(cAn=+w=t6cqn8?4Fo8o{(lWCc3LG}Mz0GQn=bvQgWMSW~aU z)oXi^YH~SZhV!oVuWPOzk>2r^`%OzW`)v;`((4XsYW?X-iadzbloHGOhPB_DbH`t{ zC(4iMow?g*XsJcH_sG}h>yh4$F6s8@63o5+b?Zfa$B~cQ57wI6>4kUnW#1ym{Fswl z2fvJ!k2O8nq#qVC+w}1DEqaCSeSfyqcgT13>xcWV?0RNnS?wr~+-W*@s*LE3{^k*S zbB(QQUOylI&VQ2@g=K0glIN2r8jaP@hv}0o(?Vb#gOs{J-MDDj`K>E=z1N#c3@Gb; Hqw{|N5l2ws literal 0 HcmV?d00001 diff --git a/images/draw-marker-icon.png b/images/draw-marker-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f26437fc1ae98ccfc91765131222fd1995f4fa71 GIT binary patch literal 311 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uGBwbBK{D72XiEBhjaDG}zd16s2gJVj5QmTSy zZen_BP-%>CN3^6At3?eN=iz?$tqhh1E7BKk|4ie1_1?!koe5{hR*&e^H;6kvj5cm`>)=A zd1SQgBTz|_r;B3=b-0qIGq6vTMKK^!ds9d*W9@B;AGi@1) e&oO9ZGuGd(VJVxaQ1K9G8-u5-pUXO@geCw#AzVKI literal 0 HcmV?d00001 diff --git a/images/draw-polygon.png b/images/draw-polygon.png new file mode 100644 index 0000000000000000000000000000000000000000..579102ddb69e7ead8e7e8f757dfc487de367acb9 GIT binary patch literal 318 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2@wC9V-A!TD(=<%vb942~)JNvR5+ zxryniL8*x;m4zo$ZGeg%c)B=-RNR^}aUtI!2cEY6#^fZS&I87sa~wW%JrL|Mm&j+} zoW{U+yrNmsq~gc~VU=hmCieQ1^(RvcPG)@4-5d9R+jY&ax!GTrcRpZs3uT>D!R|dF zOz?*SyCTPdqnCV>CR)f@H1e`C9<_XLqqbbewnU;p^HLdG_=faPENc!hA5rRZWZ&Yo zIOm}7nFAsz57dsn`XM5-kiV}@O69ItLWbZDof$Kf zHdhZbIovJpu>^C#$ptWRk1 zIrhnZ#TSho>eqc>{WHb*SPop1z5KuAMWW*)3!#OH_8kdI$14}ldao Date: Wed, 13 Feb 2013 12:13:56 +0100 Subject: [PATCH 26/46] Added saithis to the contributors list --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index bdbe428d..9592e38d 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ Contributors [OshiHidra](https://github.com/OshiHidra), [phoenixsong6](https://github.com/phoenixsong6), [Pirozek](https://github.com/Pirozek), +[saithis](https://github.com/saithis), [Scrool](https://github.com/Scrool), [sorgo](https://github.com/sorgo), [Xelio](https://github.com/Xelio), From 164d067d4a6d57edcf5691a43cc322f30afc493a Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 12:35:51 +0100 Subject: [PATCH 27/46] fix scroll back issues for public chats --- code/chat.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/chat.js b/code/chat.js index 4e7b7893..6df67f1d 100644 --- a/code/chat.js +++ b/code/chat.js @@ -196,9 +196,9 @@ window.chat.handlePublic = function(data, textStatus, jqXHR) { if(data.result.length === 0) return; - var old = chat.getOldestTimestamp(true); + var old = chat.getOldestTimestamp(false); chat.writeDataToHash(data, chat._publicData, true); - var oldMsgsWereAdded = old !== chat.getOldestTimestamp(true); + var oldMsgsWereAdded = old !== chat.getOldestTimestamp(false); switch(chat.getActive()) { case 'public': window.chat.renderPublic(oldMsgsWereAdded); break; From fbd892e88db24b26b0eb7c34d7a01e814b372b6e Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 12:36:06 +0100 Subject: [PATCH 28/46] also show anonymous messages such as 'field decyed'. Fixes #145 --- code/chat.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/code/chat.js b/code/chat.js index 6df67f1d..e5b69e26 100644 --- a/code/chat.js +++ b/code/chat.js @@ -250,10 +250,12 @@ window.chat.writeDataToHash = function(newData, storageHash, skipSecureMsgs) { // avoid duplicates if(json[0] in storageHash) return true; + var skipThisEntry = false; + var time = json[1]; var team = json[2].plext.team === 'ALIENS' ? TEAM_ENL : TEAM_RES; var auto = json[2].plext.plextType !== 'PLAYER_GENERATED'; - var msg = '', nick, pguid; + var msg = '', nick = '', pguid; $.each(json[2].plext.markup, function(ind, markup) { switch(markup[0]) { case 'SENDER': // user generated messages @@ -281,12 +283,12 @@ window.chat.writeDataToHash = function(newData, storageHash, skipSecureMsgs) { case 'SECURE': if(skipSecureMsgs) { - nick = null; + skipThisEntry = true; return false; // breaks $.each } } }); - if(!nick) return true; // aka next + if(skipThisEntry) return true; // format: timestamp, autogenerated, HTML message, player guid storageHash[json[0]] = [json[1], auto, chat.renderMsg(msg, nick, time, team), pguid]; From 63127f7890db7a49a24419f395e27a8ef7c88641 Mon Sep 17 00:00:00 2001 From: Peter Sorger Date: Wed, 13 Feb 2013 15:21:52 +0100 Subject: [PATCH 29/46] Added capture AP to AP Gain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added AP for capturing a portal (500), deploying a resonator (8×125) and Competition bonus (250). Actually no more shield AP's in Ingress. --- code/portal_detail_display_tools.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/code/portal_detail_display_tools.js b/code/portal_detail_display_tools.js index 33571d6c..6486db42 100644 --- a/code/portal_detail_display_tools.js +++ b/code/portal_detail_display_tools.js @@ -1,4 +1,3 @@ - // PORTAL DETAILS DISPLAY //////////////////////////////////////////// // hand any of these functions the details-hash of a portal, and they // will return pretty, displayable HTML or parts thereof. @@ -154,13 +153,16 @@ window.getDestroyAP = function(d) { var resoAp = resoCount * DESTROY_RESONATOR; var linkAp = linkCount * DESTROY_LINK; var fieldAp = fieldCount * DESTROY_FIELD; - var sum = resoAp + linkAp + fieldAp; + var sum = resoAp + linkAp + fieldAp + 1750; function tt(text) { - var t = 'Destroy:\n'; + var t = 'Destroy & Capture:\n'; t += resoCount + '×\tResonators\t= ' + digits(resoAp) + '\n'; t += linkCount + '×\tLinks\t= ' + digits(linkAp) + '\n'; t += fieldCount + '×\tFields\t= ' + digits(fieldAp) + '\n'; + t += '1×\tCapture\t= 500\n'; + t += '8×\tDeploy\t= 1000\n'; + t += '1×\tBonus\t= 250\n'; t += 'Sum: ' + digits(sum) + ' AP'; return '' + digits(text) + ''; } From 5876d0cab6ea01a012da64ab4280abc523b645d7 Mon Sep 17 00:00:00 2001 From: Peter Sorger Date: Wed, 13 Feb 2013 16:10:24 +0100 Subject: [PATCH 30/46] use constants --- code/portal_detail_display_tools.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/portal_detail_display_tools.js b/code/portal_detail_display_tools.js index 6486db42..026d9502 100644 --- a/code/portal_detail_display_tools.js +++ b/code/portal_detail_display_tools.js @@ -153,16 +153,16 @@ window.getDestroyAP = function(d) { var resoAp = resoCount * DESTROY_RESONATOR; var linkAp = linkCount * DESTROY_LINK; var fieldAp = fieldCount * DESTROY_FIELD; - var sum = resoAp + linkAp + fieldAp + 1750; + var sum = resoAp + linkAp + fieldAp + CAPTURE_PORTAL + 8*DEPLOY_RESONATOR + COMPLETITION_BONUS; function tt(text) { var t = 'Destroy & Capture:\n'; t += resoCount + '×\tResonators\t= ' + digits(resoAp) + '\n'; t += linkCount + '×\tLinks\t= ' + digits(linkAp) + '\n'; t += fieldCount + '×\tFields\t= ' + digits(fieldAp) + '\n'; - t += '1×\tCapture\t= 500\n'; - t += '8×\tDeploy\t= 1000\n'; - t += '1×\tBonus\t= 250\n'; + t += '1×\tCapture\t= ' + CAPTURE_PORTAL + '\n'; + t += '8×\tDeploy\t= ' + DEPLOY_RESONATOR + '\n'; + t += '1×\tBonus\t= ' + COMPLETITION_BONUS + '\n'; t += 'Sum: ' + digits(sum) + ' AP'; return '' + digits(text) + ''; } From 82029efa2b632a7d37ebe2066f2be7d3e16adf63 Mon Sep 17 00:00:00 2001 From: Peter Sorger Date: Wed, 13 Feb 2013 16:11:24 +0100 Subject: [PATCH 31/46] added constants --- main.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main.js b/main.js index 320d0c9a..d417f55b 100644 --- a/main.js +++ b/main.js @@ -157,6 +157,9 @@ var OCTANTS = ['E', 'NE', 'N', 'NW', 'W', 'SW', 'S', 'SE']; var DESTROY_RESONATOR = 75; //AP for destroying portal var DESTROY_LINK = 187; //AP for destroying link var DESTROY_FIELD = 750; //AP for destroying field +var CAPTURE_PORTAL = 500; //AP for capturing a portal +var DEPLOY_RESONATOR = 125; //AP for deploying a resonator +var COMPLETITION_BONUS = 250; //AP for deploying all resonators on portal // OTHER MORE-OR-LESS CONSTANTS ////////////////////////////////////// var TEAM_NONE = 0, TEAM_RES = 1, TEAM_ENL = 2; From 4ff027a22ed4e6c2196b568a0f3dcb003b34a63e Mon Sep 17 00:00:00 2001 From: Peter Sorger Date: Wed, 13 Feb 2013 16:16:58 +0100 Subject: [PATCH 32/46] typo --- main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.js b/main.js index d417f55b..5400cfc1 100644 --- a/main.js +++ b/main.js @@ -159,7 +159,7 @@ var DESTROY_LINK = 187; //AP for destroying link var DESTROY_FIELD = 750; //AP for destroying field var CAPTURE_PORTAL = 500; //AP for capturing a portal var DEPLOY_RESONATOR = 125; //AP for deploying a resonator -var COMPLETITION_BONUS = 250; //AP for deploying all resonators on portal +var COMPLETION_BONUS = 250; //AP for deploying all resonators on portal // OTHER MORE-OR-LESS CONSTANTS ////////////////////////////////////// var TEAM_NONE = 0, TEAM_RES = 1, TEAM_ENL = 2; From d9463de1e4086cc8e65836a03c4d52e62a6bba2c Mon Sep 17 00:00:00 2001 From: Peter Sorger Date: Wed, 13 Feb 2013 16:17:31 +0100 Subject: [PATCH 33/46] typo --- code/portal_detail_display_tools.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/portal_detail_display_tools.js b/code/portal_detail_display_tools.js index 026d9502..67c66362 100644 --- a/code/portal_detail_display_tools.js +++ b/code/portal_detail_display_tools.js @@ -153,7 +153,7 @@ window.getDestroyAP = function(d) { var resoAp = resoCount * DESTROY_RESONATOR; var linkAp = linkCount * DESTROY_LINK; var fieldAp = fieldCount * DESTROY_FIELD; - var sum = resoAp + linkAp + fieldAp + CAPTURE_PORTAL + 8*DEPLOY_RESONATOR + COMPLETITION_BONUS; + var sum = resoAp + linkAp + fieldAp + CAPTURE_PORTAL + 8*DEPLOY_RESONATOR + COMPLETION_BONUS; function tt(text) { var t = 'Destroy & Capture:\n'; From cf17fef6992ad48328ff72015972cb49164e8e50 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 16:28:20 +0100 Subject: [PATCH 34/46] =?UTF-8?q?maybe=20fix=20#152=20(haven=E2=80=99t=20c?= =?UTF-8?q?hecked)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/chat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/chat.js b/code/chat.js index e5b69e26..d570decc 100644 --- a/code/chat.js +++ b/code/chat.js @@ -271,7 +271,7 @@ window.chat.writeDataToHash = function(newData, storageHash, skipSecureMsgs) { break; case 'TEXT': - var tmp = markup[1].plain.autoLink(); + var tmp = $('
').text(markup[1].plain).html().autoLink(); msg += tmp.replace(window.PLAYER['nickMatcher'], '$1'); break; From 1e6161ad2e1934e88e5017c446c759db8b9d5de2 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 17:44:41 +0100 Subject: [PATCH 35/46] make layerChooser available to plugins so they can add layers of their own --- code/boot.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/boot.js b/code/boot.js index 7b1956a9..44aeb3a2 100644 --- a/code/boot.js +++ b/code/boot.js @@ -83,7 +83,7 @@ window.setupMap = function() { map.addLayer(linksLayer, true); addLayers['Links'] = linksLayer; - map.addControl(new L.Control.Layers({ + window.layerChooser = new L.Control.Layers({ 'OSM Cloudmade Midnight': views[0], 'OSM Cloudmade Minimal': views[1], 'OSM Mapnik': views[2], @@ -91,7 +91,9 @@ window.setupMap = function() { 'Google Roads': views[4], 'Google Satellite': views[5], 'Google Hybrid': views[6] - }, addLayers)); + }, addLayers); + + map.addControl(window.layerChooser); map.attributionControl.setPrefix(''); // listen for changes and store them in cookies map.on('moveend', window.storeMapPosition); From ae9eaba8c286436cc5822dfe11656c19f61838ca Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 17:45:07 +0100 Subject: [PATCH 36/46] further refine tooltips to be more visible against the map --- style.css | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/style.css b/style.css index f179dc6a..46ffb18c 100644 --- a/style.css +++ b/style.css @@ -450,6 +450,10 @@ h3 { border: 1px solid #666; } +.mods span:not([title]) { + cursor: auto; +} + .res .mods span, .res .meter { border: 1px solid #0076b6; } @@ -615,14 +619,20 @@ aside:nth-child(odd) span { /* tooltips */ .ui-tooltip { - background: #1E425D; - border: 1px solid #20A8B1; - box-shadow:0 0 7px #000; - color: #EEEEEE; - font-family: Verdana, sans-serif; - font-size:13px; max-width: 300px; - padding: 8px; position: absolute; z-index: 9999; + background-color: #fff; + border: 1px solid #ccc; + color: #222; + font: 13px/15px "Helvetica Neue", Arial, Helvetica, sans-serif; + padding: 2px 4px; +} + +td { + padding: 0; +} + +td + td { + padding-left: 4px; } From 1f00e70419bc1d9fe27303aa48f65b94c8dac934 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 17:46:25 +0100 Subject: [PATCH 37/46] add draw plugin. See #135 --- plugins/draw-tools.user.js | 206 +++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 plugins/draw-tools.user.js diff --git a/plugins/draw-tools.user.js b/plugins/draw-tools.user.js new file mode 100644 index 00000000..7167d8cd --- /dev/null +++ b/plugins/draw-tools.user.js @@ -0,0 +1,206 @@ +// ==UserScript== +// @id iitc-plugin-draw-tools@breunigs +// @name iitc: draw tools +// @version 0.1 +// @namespace https://github.com/breunigs/ingress-intel-total-conversion +// @updateURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/draw-tools.user.js +// @downloadURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/draw-tools.user.js +// @description Allows you to draw things into the current map so you may plan your next move +// @include http://www.ingress.com/intel* +// @match http://www.ingress.com/intel* +// ==/UserScript== + +function wrapper() { +// ensure plugin framework is there, even if iitc is not yet loaded +if(typeof window.plugin !== 'function') window.plugin = function() {}; + + +// PLUGIN START //////////////////////////////////////////////////////// + +var DRAW_TOOLS_SHAPE_OPTIONS = { + color: '#BB56FF', + fill: false, + opacity: 1, + weight: 4, + clickable: false +}; + +// use own namespace for plugin +window.plugin.drawTools = function() {}; + +window.plugin.drawTools.loadExternals = function() { + var base = 'http://breunigs.github.com/ingress-intel-total-conversion/dist'; + $('head').append(''); + load(base+'/leaflet.draw.0.1.6.js').thenRun(window.plugin.drawTools.boot); +} + + +window.plugin.drawTools.addStyles = function() { + $('head').append(''); +} + +// renders buttons which are not originally part of Leaflet.draw, such +// as the clear-drawings button. +window.plugin.drawTools.addCustomButtons = function() { + $('.leaflet-control-draw .leaflet-bar-part-bottom').removeClass('leaflet-bar-part-bottom'); + + var undo = $('') + .click(function() { + var last = null; + window.plugin.drawTools.drawnItems.eachLayer(function(l) { + last = l; + }); + if(last) window.plugin.drawTools.drawnItems.removeLayer(last); + } + ); + + var clear = $('') + .click(function() { + window.plugin.drawTools.drawnItems.clearLayers(); + } + ); + + $('.leaflet-control-draw').append(undo).append(clear); +} + +// renders the draw control buttons in the top left corner +window.plugin.drawTools.addDrawControl = function() { + var drawControl = new L.Control.Draw({ + rectangle: false, + polygon: false, + + polyline: { + shapeOptions: DRAW_TOOLS_SHAPE_OPTIONS + }, + + circle: { + shapeOptions: DRAW_TOOLS_SHAPE_OPTIONS + } + }); + map.addControl(drawControl); + plugin.drawTools.addCustomButtons(); +} + +// hacks into circle to render the radius of the circle while drawing +// and to allow the center of the circle to snap to a nearby portal. +window.plugin.drawTools.enhanceCircle = function() { + // replace _onMouseMove function to also display the radius of the + // circle + L.Circle.Draw.prototype._onMouseMove = function (e) { + var layerPoint = e.layerPoint, + latlng = e.latlng; + + this._updateLabelPosition(layerPoint); + if (this._isDrawing) { + var dist = this._startLatLng.distanceTo(latlng); + dist = dist > 1000 + ? (dist / 1000).toFixed(2) + ' km' + : Math.ceil(dist) + ' m'; + this._updateLabelText({ + text: 'Release mouse to finish drawing. ', + subtext: 'radius: ' +dist } + ); + this._drawShape(latlng); + } + } + + // replace _onMouseDown to implement snapping + L.Circle.Draw.prototype._onMouseDown = function (e) { + this._isDrawing = true; + + var snapTo = window.plugin.drawTools.getSnapLatLng(e.containerPoint); + this._startLatLng = snapTo || e.latlng; + + L.DomEvent + .on(document, 'mouseup', this._onMouseUp, this) + .preventDefault(e.originalEvent); + } +} + +// hacks into PolyLine to implement snapping and to remove the polyline +// markers when they are not required anymore for finishing the line. +// Otherwise they get in the way and make it harder to create a closed +// polyline. +window.plugin.drawTools.enhancePolyLine = function() { + // hack in snapping + L.Polyline.Draw.prototype._onClickOld = L.Polyline.Draw.prototype._onClick; + L.Polyline.Draw.prototype._onClick = function(e) { + var cp = map.latLngToContainerPoint(e.target.getLatLng()); + var snapTo = window.plugin.drawTools.getSnapLatLng(cp); + if(snapTo) e.target._latlng = snapTo; + return this._onClickOld(e); + } + + // remove polyline markers because they get in the way + L.Polyline.Draw.prototype._updateMarkerHandler = function() { + if(this._markers.length >= 2) + this._markerGroup.removeLayer(this._markers.shift()); + + if(this._markers.length >= 1) + this._markers[this._markers.length - 1].on('click', this._finishShape(), this); + } +} + +// given a container point it tries to find the most suitable portal to +// snap to. It takes the CircleMarker’s radius and weight into account. +// Will return null if nothing to snap to or a LatLng instance. +window.plugin.drawTools.getSnapLatLng = function(containerPoint) { + var candidates = []; + $.each(window.portals, function(guid, portal) { + var ll = portal.getLatLng(); + var pp = map.latLngToContainerPoint(ll); + var size = portal.options.weight + portal.options.radius; + var dist = pp.distanceTo(containerPoint); + if(dist > size) return true; + candidates.push([dist, ll]); + }); + + if(candidates.length === 0) return; + candidates = candidates.sort(function(a, b) { return a[0]-b[0]; }); + return candidates[0][1]; +} + +window.plugin.drawTools.boot = function() { + plugin.drawTools.enhanceCircle(); + plugin.drawTools.enhancePolyLine(); + plugin.drawTools.addStyles(); + plugin.drawTools.addDrawControl(); + + window.plugin.drawTools.drawnItems = new L.LayerGroup(); + var drawnItems = window.plugin.drawTools.drawnItems; + map.on('draw:poly-created', function (e) { + drawnItems.addLayer(e.poly); + }); + + + map.on('draw:circle-created', function (e) { + drawnItems.addLayer(e.circ); + }); + + map.on('draw:marker-created', function (e) { + drawnItems.addLayer(e.marker); + //e.marker.dragging.enable(); + }); + + window.layerChooser.addOverlay(drawnItems, 'Drawn Items'); + map.addLayer(drawnItems); +} + + +var setup = window.plugin.drawTools.loadExternals; + +// PLUGIN END ////////////////////////////////////////////////////////// + +if(window.iitcLoaded && typeof setup === 'function') { + setup(); +} else { + if(window.bootPlugins) + window.bootPlugins.push(setup); + else + window.bootPlugins = [setup]; +} +} // wrapper end +// inject code into site context +var script = document.createElement('script'); +script.appendChild(document.createTextNode('('+ wrapper +')();')); +(document.body || document.head || document.documentElement).appendChild(script); From 250cd99167cc1f11b397a9291003137092fa4527 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 18:10:42 +0100 Subject: [PATCH 38/46] add draw plugin description --- plugins/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/README.md b/plugins/README.md index c5d1b10d..739f840a 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -11,6 +11,7 @@ Available Plugins - [**Guess Player Level**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/guess-player-levels.user.js) looks for the highest placed resonator per player in the current view to guess the player level. - [**Highlight Weakened Portals**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/show-portal-weakness.user.js) fill portals with red or orange to indicate portal's state of disrepair. The brighter the color the more attention needed (recharge, shields, resonators). A dashed portal means a resonator is missing. +- [**Draw Tools**](https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/draw-tools.user.js) allows to draw circles and lines on the map to aid you with planning your next big field. Hacking From e76c17f2c78ab4005c528585273113fba18215db Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 18:11:24 +0100 Subject: [PATCH 39/46] color Leaflet marker icon accordingly --- dist/images/marker-icon.png | Bin 0 -> 1444 bytes dist/images/marker-icon@2x.png | Bin 0 -> 2786 bytes dist/images/marker-shadow.png | Bin 0 -> 797 bytes images/marker-icon.png | Bin 0 -> 1444 bytes images/marker-icon@2x.png | Bin 0 -> 2786 bytes images/marker-shadow.png | Bin 0 -> 797 bytes plugins/draw-tools.user.js | 3 +++ 7 files changed, 3 insertions(+) create mode 100644 dist/images/marker-icon.png create mode 100644 dist/images/marker-icon@2x.png create mode 100644 dist/images/marker-shadow.png create mode 100644 images/marker-icon.png create mode 100644 images/marker-icon@2x.png create mode 100644 images/marker-shadow.png diff --git a/dist/images/marker-icon.png b/dist/images/marker-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..519b1c57444c45ea9564cac97d4116f41d11bbff GIT binary patch literal 1444 zcmYjP2~bm46#alDfS^&M2CGv+9n^vgMQw+zWC3CpNF)k{C}^<~c7llFR0&vwGGL|P zR4ApisEB}J2^d)dVF`pK5+Y?63IkOULn2yCus8l0rgz@I|NL|BJNLXdKh>MzVPUq# z3_%bJiYJK$Z%cUgm>5BROOMgQ%QVWx`+TjWVQeXrh?s8 zEU`4b{pM`YPNT^ut~tQCBcg7|YCxho=!pA7G1vw(Py$)FG5xrY;?M~?AdZd(Z{WY$Uy9DE z3GA#5>V%1)FADAweb@E)Tz4I}yDqG!KD?(PvbQ0sw=r5S=E=pePnzPMG{^TfU+j}4 zC|WKnTCeoW(g(XT279wd@o)S&r-RROBcge6@$m^)`TV5hYuD2=%c~k1o1~px-93HEfswJvsp*;7*?*qT z&A)!FQZ1;}8ja@7$5>p6xB7VZG5&>ET6(Y5Eki5{6l(bKk5Wi(K6uOXO)13n%&o|? zQ$xa_1a3m4Y_X#LmfbK>#;UX*9?r?edPIpwqvtneV)Enp!V4qg%564=+;PmFq;>}0 z6(_=1#x>3?6)y~=Jk3ms^`p)^`IWSu%e}RL)0M>E!oIn4SMy~B z-L>wgt2-%Nx&h9Vgd-Q4L^~&X0VLh`g1Cl zVDDm_yUyJtC~-Dtcjh_*KAg`!pFDFh(YrBL5sAr(&$sc)k@WLgBE`~W=d$)IER**Z zQ(ZW`YQ5T47UP!64Gde87-cJ4Xxc16gcbH@ZeF+EO*%_k$hAWbl-NprwbEW+evtwx zxL`_Xpj~&(v-shVGVMsxe((BKG|6XH8H{$-kr=BWPBrarR`~;C>Z{<4^LL|O4!X%B z$k|hIyB-x)1mAFY?I5f3I{nKAqXJ^k#u(P7&3ifKdvsJMm(EG`);UbbCbsHl2}zZ` z+KMy2!$H?GRkU_7(R}sZuR0@Yjs>(jN&D4Te-sXeRfV299BW_07Yx6o&4ta{hL$Uo z&*ENn@b{g4dTHC(kfofRIr?U7i6j5DwZ$#44b*3RJ98tJIdZOkZfB zOr`JAhtxoUh9Zo?wv={?ea!Uu{r2qdcK3Gfy=U&+J9j4WB;VX~&)Ive^{ut``%aeq z|LXgC@YAc#`oonS7d$v&)dby7*8LsA&x9$$)p|Z!&(B`|{jF~vQieafwDS}hcA<>C zQ=dEanHR)vmA_Y?mkFn~jDVECTbL&7DmPLF=CiN*d;X`-ug>RAT$}&p%j@z#e_>5N z=d(|ScYToBBiyHV?;A7%v#xmJbSeFza4+WeW8(?n8If3g(^H{r zIXNOqgsews|Kn$#JhM@~&T$vSiBU;8BP*63E0k z)&seaYLFS<(WTGx``fjip-Nj!0>g;_fDrAYnV=mJ9rP{z?v`AGs3Y^jZ!cXrq7aF3 zBPX1q#ywvMl`$Nlvyc54jDStpCUgrQtQL)V6r^3a zGO1NmDPE*Jso?tM@Hj)+qH;r$RVGt6fYv1ccfcd z9|gD{*w|BeR)O*(`pK#td>yH&O&K`)JO2@dv*lFd%BPHiS8pk`L>5% z3gZHG7^^IYc2-L-wo#UQ>I*v@jq_$+q6dP#gOPZ(5)gt1O9C(HB|!u#5h%yr7Y+ok zQg_bhRv*sMkwIgBb2^%y0c|~MGKkcalgH|P= z#O0_5nQFaM5#U*5xmUu_A~s+%^@L6$vY#*X79M5Ux~YV6A#|SuApz_Z5W`ifE*b;5n4v}`g&;u1A zVy}6GrtY&#I_oB~d&hy2LvW6J%_2mwIo4g8{krYZ=|UKty>6%`1TX?qmVTVNkNxQB zx`}L={bG>ec^;^x9~&u0mrY&aHxRj*FHG#{)&PZJTM2~T-86Oa%D*=BzvtSw>tG;& z48}2JVq`Vlz;SiAgAP^Qi@_032z{^ngIMk;X+4J0ink2ejJrvgAb|5{V zWfj$nt&zk*rTAOJ#8FY1%R_SBn+&xC0&fr`LIWwL@EF_I;P*`XDY{#%3^Djv8XhS7m=?Dy*)=1O7Db{YM_kE<5i{^$T8?Z*l2tF$J;}@L$Tj^HsSg> zqd)qv6*>L==%X-E+~RokHpS1486^e}VVHbVe!Q zofZr!9lzBf)4Pw@hK(Yzz2XMl-D4KsOd;~v6@Bj4O3<6x9vV0{3O80H^7GO2->CwJ zDCq7LPqvzf+ZK_IBwoL3%z`tj?*FRLEDF<=dRvpw_T$*Op`d*@8g#kXrp&pk=5D+S zUKm-297h1T-6|rf4biS+Y9H?}bVj1W8>vKB?7i1kkRTJRpA3mamJ~j*QsFN;Dq(4P z-TIb9#k%PMZI3XnFp=05Z=)iEkM~{?o}7g@6-2{&*%ydyV@1CYLse;ly+Aa=NUd%# zIW}%8h=z6A4z-Ojb)D?0@_I+bd#^;L*(8XD^)b1OL>AY5&aTRzv^VffDJt>Yy;-15 zc+#3ggmFcA>W$G+jS2AuU6P5C_!Fqu#%VmWbiOkFzeJM}RXP$!sx<_vrHHrukMyA&r!VwM3 z=VZ;e$XAr$u|`J4(O?iv)*I8aW?kfK%-i5OulVAjWZggpvKR~_iT`SCG%{=ErG|gM zSCQW4r~j{)1kpeS4Lym*w5-{el)P6sj6#eE`@{o?3U!f@M59a5cvm(Umz4birFf7= z8Vn&S@r1T0N{)~W_NgL~+q1#ClvZa+;TtISo)zOuJYg+_aK0Y5K^Y7qiG5m&zatyW zOKs&2l;g?Npm;c06O?s5_Nd}|)92FZ@Bq}L!M?;vJwd#@)Z<7Igy!f(l@esdH@QyO>=^}|v^;D;4t-QQDiD$jp zjK?bx;hi_flW0uNT7BV38S-y0zP#y-(ea?N1fKc5Hxz_jYHz2toJeddlN}W%lo;xR z$`nL{cTCfhXnbu*kcd6lX?Qk`3dSafmEqq1AVaSeNj%RP=8z#0qjH0z;yv5+tk6Hs zOs45z;*cW2g=b~h4ljxQpE^z}|I1Rcz4OnXesu28`iHS3D%aTC%%l7RO8*d(XMV5V z?&={)f-7#d{=-Y+^1a+-Lt*m?zt=t2WP4}jup$wOj7{2vqtQ0(h(t2W6C%roC5cF6R6=Cb ouq6`7EC9orL?rSd&}=>b10ign0T{@M*8l(j07*qoM6N<$g3ty=U;qFB literal 0 HcmV?d00001 diff --git a/dist/images/marker-shadow.png b/dist/images/marker-shadow.png new file mode 100644 index 0000000000000000000000000000000000000000..d1e773c715a9b508ebea055c4bb4b0a2ad7f6e52 GIT binary patch literal 797 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 literal 0 HcmV?d00001 diff --git a/images/marker-shadow.png b/images/marker-shadow.png new file mode 100644 index 0000000000000000000000000000000000000000..d1e773c715a9b508ebea055c4bb4b0a2ad7f6e52 GIT binary patch literal 797 zcmV+&1LFLNP)oNwbRQ6Eq$4M3RDU@$ z<4cV9zWLV=bA&uX9wCpA{{f^4$D#k>GcX53-UQqf>_LzMU@frMz|MwbfQGbY0?ccG zBj_wh0?6Tv;HWR0`x;m^Bm<;sCm_85SGspFBn6|A!tDh$nR`wGorGkyL7j?F3#OJq zIswLIz;iF7f|LMnF(pXPAY*GYpsw%&e_WjlnV`C$6@#Q7GZu1$Q8>&p8=(iJj8o|T~0u%hM*Yg_d(Av{WS$h&pM%nlEAonVL0;DkN|xc zn)9F+aMDk#VtAMb0c=kIb1pU-$e4$3pwo&qVh(Umlw3_IU_dFcFe(In6*x}D4LHLhFZ4N=V2ZR+>XHU5D&uY$npJ7Eu?{iAK>UxC?4uyg4+iD z!nst**H%2zhOBxc7C7Tv{f^`%hqT1KpU@Vf6+C2|bGaR(1~TU5D-1;&HXT~PMc2Lu z{Q%^i6vvox&EMFT7I_)R$xq1779I8kE@?|D*cLWnP0a@a)xJA`o*^$^V(yN)b`kV7 z=o@jbFF4j{KeuQh'); load(base+'/leaflet.draw.0.1.6.js').thenRun(window.plugin.drawTools.boot); + // overwrite default Leaflet Marker icon. + L.Icon.Default.imagePath = base + '/images'; } From fb3d3a78114895cb02eeb0300231b5a96f602f8a Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 18:15:33 +0100 Subject: [PATCH 40/46] fix error when drawing polylines --- plugins/draw-tools.user.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/draw-tools.user.js b/plugins/draw-tools.user.js index 78e9afbe..98fdef2e 100644 --- a/plugins/draw-tools.user.js +++ b/plugins/draw-tools.user.js @@ -136,11 +136,13 @@ window.plugin.drawTools.enhancePolyLine = function() { // remove polyline markers because they get in the way L.Polyline.Draw.prototype._updateMarkerHandler = function() { + if(!this._markers) return; + if(this._markers.length >= 2) this._markerGroup.removeLayer(this._markers.shift()); if(this._markers.length >= 1) - this._markers[this._markers.length - 1].on('click', this._finishShape(), this); + this._markers[this._markers.length - 1].on('click', this._finishShape, this); } } From 7f3be4dd668294eefcc3a7d5de937cae998fb7b4 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 18:43:09 +0100 Subject: [PATCH 41/46] allow dragging of markers --- plugins/draw-tools.user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/draw-tools.user.js b/plugins/draw-tools.user.js index 98fdef2e..34a5f6e0 100644 --- a/plugins/draw-tools.user.js +++ b/plugins/draw-tools.user.js @@ -184,7 +184,7 @@ window.plugin.drawTools.boot = function() { map.on('draw:marker-created', function (e) { drawnItems.addLayer(e.marker); - //e.marker.dragging.enable(); + e.marker.dragging.enable(); }); window.layerChooser.addOverlay(drawnItems, 'Drawn Items'); From 6cca87a1d9f1bb4917d1d36ef930d397391de9fb Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 18:48:21 +0100 Subject: [PATCH 42/46] fix left over typo from previous commit --- code/portal_detail_display_tools.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/portal_detail_display_tools.js b/code/portal_detail_display_tools.js index 67c66362..d0ead99d 100644 --- a/code/portal_detail_display_tools.js +++ b/code/portal_detail_display_tools.js @@ -162,7 +162,7 @@ window.getDestroyAP = function(d) { t += fieldCount + '×\tFields\t= ' + digits(fieldAp) + '\n'; t += '1×\tCapture\t= ' + CAPTURE_PORTAL + '\n'; t += '8×\tDeploy\t= ' + DEPLOY_RESONATOR + '\n'; - t += '1×\tBonus\t= ' + COMPLETITION_BONUS + '\n'; + t += '1×\tBonus\t= ' + COMPLETION_BONUS + '\n'; t += 'Sum: ' + digits(sum) + ' AP'; return '' + digits(text) + ''; } From b3ec8ccd48b3eb9010deeaa74645a387f3a74bb6 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 19:40:00 +0100 Subject: [PATCH 43/46] draw lines between portals and resonators (fixes #88 #151) The lines look great against a dark background but are barely visible against OSM CloudMade Minimal. Not sure what could be done about that though, other than drawing differently for each. --- code/map_data.js | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/code/map_data.js b/code/map_data.js index 791d9705..adc5f3c6 100644 --- a/code/map_data.js +++ b/code/map_data.js @@ -299,6 +299,7 @@ window.renderResonators = function(ent, portalLayer) { var portalLevel = getPortalLevel(ent[2]); if(portalLevel < getMinPortalLevel() && ent[0] != selectedPortal) return; + var portalLatLng = [ent[2].locationE6.latE6/1E6, ent[2].locationE6.lngE6/1E6]; var layerGroup = portalsLayers[parseInt(portalLevel)]; var reRendered = false; @@ -329,7 +330,11 @@ window.renderResonators = function(ent, portalLayer) { var lat0 = ent[2].locationE6.latE6/1E6 + dLat * 180/Math.PI; var lon0 = ent[2].locationE6.lngE6/1E6 + dLon * 180/Math.PI; var Rlatlng = [lat0, lon0]; - var r = L.circleMarker(Rlatlng, { + + var resoGuid = portalResonatorGuid(ent[0], i); + + // the resonator + var reso = L.circleMarker(Rlatlng, { radius: 3, // #AAAAAA outline seems easier to see the fill opacity color: '#AAAAAA', @@ -337,14 +342,34 @@ window.renderResonators = function(ent, portalLayer) { weight: 1, fillColor: COLORS_LVL[rdata.level], fillOpacity: rdata.energyTotal/RESO_NRG[rdata.level], - clickable: false, - level: rdata.level, - details: rdata, - pDetails: ent[2], - guid: portalResonatorGuid(ent[0], i) }); + guid: resoGuid // need this here as well for add/remove events + }); - r.on('remove', function() { delete window.resonators[this.options.guid]; }); - r.on('add', function() { window.resonators[this.options.guid] = this; }); + // line connecting reso to portal + var conn = L.polyline([Rlatlng, portalLatLng], { + weight: 2, + color: '#FFFFFF', + opacity: 0.2, + dashArray: '10,4', + fill: false, + clickable: false}); + + + // put both in one group, so they can be handled by the same logic. + var r = L.layerGroup([reso, conn]); + r.options = { + level: rdata.level, + details: rdata, + pDetails: ent[2], + guid: resoGuid + }; + + // However, LayerGroups (and FeatureGroups) don’t fire add/remove + // events, thus this listener will be attached to the resonator. It + // doesn’t matter to which element these are bound since Leaflet + // will add/remove all elements of the LayerGroup at once. + reso.on('remove', function() { delete window.resonators[this.options.guid]; }); + reso.on('add', function() { window.resonators[this.options.guid] = r; }); r.addTo(portalsLayers[parseInt(portalLevel)]); reRendered = true; From a63370cae98528e4360b6f7593525e3c5a6f8b38 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 19:52:29 +0100 Subject: [PATCH 44/46] fix Leaflet not saving base layer properly --- code/boot.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/boot.js b/code/boot.js index 44aeb3a2..e0397ebe 100644 --- a/code/boot.js +++ b/code/boot.js @@ -113,8 +113,10 @@ window.setupMap = function() { console.log('Remove all resonators'); }); - $("[name='leaflet-base-layers']").change(function () { - writeCookie('ingress.intelmap.type', $(this).parent().index()); + + map.on('baselayerchange', function () { + var selInd = $('[name=leaflet-base-layers]:checked').parent().index(); + writeCookie('ingress.intelmap.type', selInd); }); // map update status handling From 3bbca3935308c16b544a3be8fef25fd3f242d4ff Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 20:01:44 +0100 Subject: [PATCH 45/46] add sanity checks to lat/lng to avoid issues like #153 (fixes #153) --- code/location.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/code/location.js b/code/location.js index 7258ff83..2860a9a5 100644 --- a/code/location.js +++ b/code/location.js @@ -5,11 +5,17 @@ // retrieves current position from map and stores it cookies window.storeMapPosition = function() { var m = window.map.getCenter(); - writeCookie('ingress.intelmap.lat', m['lat']); - writeCookie('ingress.intelmap.lng', m['lng']); + + if(m['lat'] >= -90 && m['lat'] <= 90) + writeCookie('ingress.intelmap.lat', m['lat']); + + if(m['lng'] >= -180 && m['lng'] <= 180) + writeCookie('ingress.intelmap.lng', m['lng']); + writeCookie('ingress.intelmap.zoom', window.map.getZoom()); } + // either retrieves the last shown position from a cookie, from the // URL or if neither is present, via Geolocation. If that fails, it // returns a map that shows the whole world. @@ -28,6 +34,10 @@ window.getPosition = function() { var lat = parseFloat(readCookie('ingress.intelmap.lat')) || 0.0; var lng = parseFloat(readCookie('ingress.intelmap.lng')) || 0.0; var z = parseInt(readCookie('ingress.intelmap.zoom')) || 17; + + if(lat < -90 || lat > 90) lat = 0.0; + if(lng < -180 || lng > 180) lng = 0.0; + return {center: new L.LatLng(lat, lng), zoom: z > 18 ? 18 : z}; } From 841223f8372ec60f24c223ccd9be4186a8c8ba91 Mon Sep 17 00:00:00 2001 From: Stefan Breunig Date: Wed, 13 Feb 2013 20:20:29 +0100 Subject: [PATCH 46/46] the patches to avoid re-rendering would not update the portal details if there were only minor changes (resos destroyed or energy level changed). This likely lead to the sidebar showing outdates information. The patch should solve #154, but please check carefully. --- code/map_data.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/code/map_data.js b/code/map_data.js index adc5f3c6..072c8259 100644 --- a/code/map_data.js +++ b/code/map_data.js @@ -225,9 +225,14 @@ window.renderPortal = function(ent) { var oo = old.options; var u = oo.team !== team; u = u || oo.level !== portalLevel; - // nothing for the portal changed, so don’t update. Let resonators - // manage themselves if they want to be updated. - if(!u) return renderResonators(ent, old); + // nothing changed that requires re-rendering the portal. + if(!u) { + // let resos handle themselves if they need to be redrawn + renderResonators(ent, old); + // update stored details for portal details in sidebar. + old.options.details = ent[2]; + return; + } // there were changes, remove old portal removeByGuid(ent[0]); }