From c75caa91dd0f89bf520e8640eb6b54beb8698f55 Mon Sep 17 00:00:00 2001 From: Xelio Date: Thu, 28 Feb 2013 14:40:35 +0800 Subject: [PATCH 1/4] Fix flicker portal in portal render limit handler Change: Extract portal handle process from "handleDataResponse" to "handlePortalData" Add "action" property to object returned by $.ajax() to identity type of request Delay low level portal render until no active request of map data. --- code/map_data.js | 33 ++++++++----- code/portal_render_limit.js | 93 +++++++++++++++++++++++++++++++++++-- code/utils_misc.js | 4 +- 3 files changed, 113 insertions(+), 17 deletions(-) diff --git a/code/map_data.js b/code/map_data.js index 363240c4..300be338 100644 --- a/code/map_data.js +++ b/code/map_data.js @@ -49,7 +49,7 @@ window.requestData = function() { $.each(tiles, function(ind, tls) { data = { minLevelOfDetail: -1 }; data.boundsParamsList = tls; - window.requests.add(window.postAjax('getThinnedEntitiesV2', data, window.handleDataResponse)); + window.requests.add(window.postAjax('getThinnedEntitiesV2', data, window.handleDataResponse, portalRenderLimit.handleFailRequest)); }); } @@ -59,11 +59,10 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { if(!data || !data.result) { window.failedRequestCount++; console.warn(data); + portalRenderLimit.handleFailRequest(); return; } - var portalUpdateAvailable = false; - var portalInUrlAvailable = false; var m = data.result.map; // defer rendering of portals because there is no z-index in SVG. // this means that what’s rendered last ends up on top. While the @@ -72,8 +71,6 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { // https://github.com/Leaflet/Leaflet/issues/185 var ppp = []; var p2f = {}; - // Reset new portals count of Portal Render Limit handler - portalRenderLimit.resetCounting(); $.each(m, function(qk, val) { $.each(val.deletedGameEntityGuids, function(ind, guid) { if(getTypeByGuid(guid) === TYPE_FIELD && window.fields[guid] !== undefined) { @@ -92,8 +89,6 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { // format for portals: { controllingTeam, turret } if(ent[2].turret !== undefined) { - if(selectedPortal === ent[0]) portalUpdateAvailable = true; - if(urlPortal && ent[0] == urlPortal) portalInUrlAvailable = true; var latlng = [ent[2].locationE6.latE6/1E6, ent[2].locationE6.lngE6/1E6]; if(!window.getPaddedBounds().contains(latlng) @@ -102,7 +97,7 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { ) return; - portalRenderLimit.pushPortal(ent); + ppp.push(ent); // delay portal render } else if(ent[2].edge !== undefined) { renderLink(ent); @@ -118,7 +113,7 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { } }); }); - + $.each(ppp, function(ind, portal) { if(portal[2].portalV2['linkedFields'] === undefined) { portal[2].portalV2['linkedFields'] = []; @@ -128,12 +123,28 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { portal[2].portalV2['linkedFields'] = uniqueArray(p2f[portal[0]]); } }); + + // Process the portals with portal render limit handler first + ppp = portalRenderLimit.processPortals(ppp); + handlePortalData(ppp); + + resolvePlayerNames(); + renderUpdateStatus(); +} + +window.handlePortalData = function(ppp) { + var portalUpdateAvailable = false; + var portalInUrlAvailable = false; // Preserve and restore "selectedPortal" between portal re-render if(portalUpdateAvailable) var oldSelectedPortal = selectedPortal; runHooks('portalDataLoaded', {portals : ppp}); - $.each(ppp, function(ind, portal) { renderPortal(portal); }); + $.each(ppp, function(ind, portal) { + if(selectedPortal === portal[0]) portalUpdateAvailable = true; + if(urlPortal && portal[0] == urlPortal) portalInUrlAvailable = true; + renderPortal(portal); + }); var selectedPortalLayer = portals[oldSelectedPortal]; if(portalUpdateAvailable && selectedPortalLayer) selectedPortal = oldSelectedPortal; @@ -150,8 +161,6 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { } if(portalUpdateAvailable) renderPortalDetails(selectedPortal); - resolvePlayerNames(); - renderUpdateStatus(); } // removes entities that are still handled by Leaflet, although they diff --git a/code/portal_render_limit.js b/code/portal_render_limit.js index 58961023..f80bd7b9 100644 --- a/code/portal_render_limit.js +++ b/code/portal_render_limit.js @@ -3,9 +3,22 @@ // Functions to handle hiding low level portal when portal render // limit is reached. // -// After initialized and reset in window.requestData(), portals in -// response data will pass to function "pushPortal". Each new portal -// not on the map will add 1 to newPortalsPerLevel[portal level]. +// On initialization, previous minLevel will preserve to previousMinLevel +// with zoom level difference. +// +// After initialized and reset in window.requestData(), "processPortals" +// intercept all portals data in "handleDataResponse". Put the count of +// new portals to newPortalsPerLevel[portal level]. And split portals +// into two parts base on previousMinLevel. Portals with level >= +// previousMinLevel will return as result and continue to render. +// Others will save to portalsPreviousMinLevel. If there is no more +// active request of map data, portals will not split and +// portalsPreviousMinLevel will add back to result and render base on +// current minLevel. +// +// "handleFailRequest" is added to handle the case when the last request +// failed and "processPortals" didn't get called. It will get +// portalsPreviousMinLevel base on current minLevel and render them. // // "getMinLevel" will be called by "getMinPortalLevel" in utils_misc.js // to determine min portal level to draw on map. @@ -28,12 +41,25 @@ window.portalRenderLimit = function() {} window.portalRenderLimit.initialized = false; window.portalRenderLimit.minLevelSet = false; window.portalRenderLimit.minLevel = -1; +window.portalRenderLimit.previousMinLevel = -1; +window.portalRenderLimit.previousZoomLevel; window.portalRenderLimit.newPortalsPerLevel = new Array(MAX_PORTAL_LEVEL + 1); +window.portalRenderLimit.portalsPreviousMinLevel = new Array(MAX_PORTAL_LEVEL + 1); window.portalRenderLimit.init = function () { + var currentZoomLevel = map.getZoom(); + if(!portalRenderLimit.previousZoomLevel) portalRenderLimit.previousZoomLevel = currentZoomLevel; + if(portalRenderLimit.minLevelSet) { + var zoomDiff = currentZoomLevel - portalRenderLimit.previousZoomLevel; + portalRenderLimit.previousMinLevel = Math.max(portalRenderLimit.minLevel - zoomDiff, -1); + portalRenderLimit.previousMinLevel = Math.min(portalRenderLimit.previousMinLevel, MAX_PORTAL_LEVEL); + } + portalRenderLimit.previousZoomLevel = currentZoomLevel; + portalRenderLimit.initialized = true; portalRenderLimit.minLevel = -1; portalRenderLimit.resetCounting(); + portalRenderLimit.resetPortalsPreviousMinLevel(); } window.portalRenderLimit.resetCounting = function() { @@ -43,7 +69,45 @@ window.portalRenderLimit.resetCounting = function() { } } -window.portalRenderLimit.pushPortal = function(ent) { +window.portalRenderLimit.resetPortalsPreviousMinLevel = function() { + for(var i = 0; i <= MAX_PORTAL_LEVEL; i++) { + portalRenderLimit.portalsPreviousMinLevel[i] = new Array(); + } +} + +window.portalRenderLimit.processPortals = function(ppp) { + portalRenderLimit.resetCounting(); + var resultPortals = new Array(); + + $.each(ppp, function(ind, portal) { + portalRenderLimit.countPortal(portal); + + if(!portalRenderLimit.isLastRequest()) { + var portalLevel = parseInt(getPortalLevel(portal[2])); + if(portalLevel < portalRenderLimit.previousMinLevel) { + portalRenderLimit.portalsPreviousMinLevel[portalLevel].push(portal); + }else{ + resultPortals.push(portal); + } + } + }); + + if(portalRenderLimit.isLastRequest()) { + resultPortals = portalRenderLimit.getLowLevelPortals(ppp); + portalRenderLimit.resetPortalsPreviousMinLevel(); + } + return resultPortals; +} + +window.portalRenderLimit.handleFailRequest = function() { + if(portalRenderLimit.isLastRequest()) { + var ppp = portalRenderLimit.getLowLevelPortals(null); + portalRenderLimit.resetPortalsPreviousMinLevel(); + handlePortalData(ppp); + } +} + +window.portalRenderLimit.countPortal = function(ent) { var portalGuid = ent[0]; var portalLevel = parseInt(getPortalLevel(ent[2])); var layerGroup = portalsLayers[portalLevel]; @@ -52,6 +116,27 @@ window.portalRenderLimit.pushPortal = function(ent) { portalRenderLimit.newPortalsPerLevel[portalLevel]++; } +window.portalRenderLimit.getLowLevelPortals = function(appendTo) { + var resultPortals = appendTo ? appendTo : new Array(); + for(var i = portalRenderLimit.getMinLevel(); + i < portalRenderLimit.previousMinLevel; + i++) { + $.merge(resultPortals, portalRenderLimit.portalsPreviousMinLevel[i]); + } + return resultPortals; +} + +window.portalRenderLimit.isLastRequest = function() { + var result = true; + $.each(window.activeRequests, function(ind, req) { + if(req.action === 'getThinnedEntitiesV2') { + result = false; + return false; + } + }); + return result; +} + window.portalRenderLimit.getMinLevel = function() { if(!portalRenderLimit.initialized) return -1; if(!portalRenderLimit.minLevelSet) portalRenderLimit.setMinLevel(); diff --git a/code/utils_misc.js b/code/utils_misc.js index 1e5e0a87..451d565e 100644 --- a/code/utils_misc.js +++ b/code/utils_misc.js @@ -58,7 +58,7 @@ window.postAjax = function(action, data, success, error) { data = JSON.stringify($.extend({method: 'dashboard.'+action}, data)); var remove = function(data, textStatus, jqXHR) { window.requests.remove(jqXHR); }; var errCnt = function(jqXHR) { window.failedRequestCount++; window.requests.remove(jqXHR); }; - return $.ajax({ + var result = $.ajax({ // use full URL to avoid issues depending on how people set their // slash. See: // https://github.com/breunigs/ingress-intel-total-conversion/issues/56 @@ -73,6 +73,8 @@ window.postAjax = function(action, data, success, error) { req.setRequestHeader('X-CSRFToken', readCookie('csrftoken')); } }); + result.action = action; + return result; } // converts unix timestamps to HH:mm:ss format if it was today; From c9d7300a052114b491e49879d539ffe3fca98b78 Mon Sep 17 00:00:00 2001 From: Xelio Date: Fri, 1 Mar 2013 13:57:35 +0800 Subject: [PATCH 2/4] Code Restructure --- code/map_data.js | 11 +++--- code/portal_render_limit.js | 70 +++++++++++++++++++++---------------- 2 files changed, 45 insertions(+), 36 deletions(-) diff --git a/code/map_data.js b/code/map_data.js index 300be338..c620e404 100644 --- a/code/map_data.js +++ b/code/map_data.js @@ -125,22 +125,23 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { }); // Process the portals with portal render limit handler first - ppp = portalRenderLimit.processPortals(ppp); - handlePortalData(ppp); + // Low level portal will hold until last request + var newPpp = portalRenderLimit.splitOrMergeLowLevelPortals(ppp); + handlePortalData(newPpp); resolvePlayerNames(); renderUpdateStatus(); } -window.handlePortalData = function(ppp) { +window.handlePortalData = function(portals) { var portalUpdateAvailable = false; var portalInUrlAvailable = false; // Preserve and restore "selectedPortal" between portal re-render if(portalUpdateAvailable) var oldSelectedPortal = selectedPortal; - runHooks('portalDataLoaded', {portals : ppp}); - $.each(ppp, function(ind, portal) { + runHooks('portalDataLoaded', {portals : portals}); + $.each(portals, function(ind, portal) { if(selectedPortal === portal[0]) portalUpdateAvailable = true; if(urlPortal && portal[0] == urlPortal) portalInUrlAvailable = true; renderPortal(portal); diff --git a/code/portal_render_limit.js b/code/portal_render_limit.js index f80bd7b9..a726e729 100644 --- a/code/portal_render_limit.js +++ b/code/portal_render_limit.js @@ -48,14 +48,17 @@ window.portalRenderLimit.portalsPreviousMinLevel = new Array(MAX_PORTAL_LEVEL + window.portalRenderLimit.init = function () { var currentZoomLevel = map.getZoom(); - if(!portalRenderLimit.previousZoomLevel) portalRenderLimit.previousZoomLevel = currentZoomLevel; + portalRenderLimit.previousZoomLevel = portalRenderLimit.previousZoomLevel || currentZoomLevel; + + // If there is a minLevel set in previous run, calculate previousMinLevel with it. if(portalRenderLimit.minLevelSet) { var zoomDiff = currentZoomLevel - portalRenderLimit.previousZoomLevel; portalRenderLimit.previousMinLevel = Math.max(portalRenderLimit.minLevel - zoomDiff, -1); portalRenderLimit.previousMinLevel = Math.min(portalRenderLimit.previousMinLevel, MAX_PORTAL_LEVEL); } + portalRenderLimit.previousZoomLevel = currentZoomLevel; - + portalRenderLimit.initialized = true; portalRenderLimit.minLevel = -1; portalRenderLimit.resetCounting(); @@ -75,54 +78,59 @@ window.portalRenderLimit.resetPortalsPreviousMinLevel = function() { } } -window.portalRenderLimit.processPortals = function(ppp) { +window.portalRenderLimit.splitOrMergeLowLevelPortals = function(originPortals) { portalRenderLimit.resetCounting(); - var resultPortals = new Array(); + portalRenderLimit.countingPortals(originPortals); - $.each(ppp, function(ind, portal) { - portalRenderLimit.countPortal(portal); + var resultPortals = portalRenderLimit.isLastRequest() + ? portalRenderLimit.mergeLowLevelPortals(originPortals) + : portalRenderLimit.splitLowLevelPortals(originPortals); - if(!portalRenderLimit.isLastRequest()) { - var portalLevel = parseInt(getPortalLevel(portal[2])); - if(portalLevel < portalRenderLimit.previousMinLevel) { - portalRenderLimit.portalsPreviousMinLevel[portalLevel].push(portal); - }else{ - resultPortals.push(portal); - } - } - }); - - if(portalRenderLimit.isLastRequest()) { - resultPortals = portalRenderLimit.getLowLevelPortals(ppp); - portalRenderLimit.resetPortalsPreviousMinLevel(); - } return resultPortals; } window.portalRenderLimit.handleFailRequest = function() { if(portalRenderLimit.isLastRequest()) { - var ppp = portalRenderLimit.getLowLevelPortals(null); - portalRenderLimit.resetPortalsPreviousMinLevel(); - handlePortalData(ppp); + var resultPortals = portalRenderLimit.mergeLowLevelPortals(null); + handlePortalData(resultPortals); } } -window.portalRenderLimit.countPortal = function(ent) { - var portalGuid = ent[0]; - var portalLevel = parseInt(getPortalLevel(ent[2])); - var layerGroup = portalsLayers[portalLevel]; - - if(findEntityInLeaflet(layerGroup, window.portals, ent[0])) return; - portalRenderLimit.newPortalsPerLevel[portalLevel]++; +window.portalRenderLimit.countingPortals = function(portals) { + $.each(portals, function(ind, portal) { + var portalGuid = portal[0]; + var portalLevel = parseInt(getPortalLevel(portal[2])); + var layerGroup = portalsLayers[portalLevel]; + + if(findEntityInLeaflet(layerGroup, window.portals, portalGuid)) return true; + + portalRenderLimit.newPortalsPerLevel[portalLevel]++; + }); } -window.portalRenderLimit.getLowLevelPortals = function(appendTo) { +window.portalRenderLimit.splitLowLevelPortals = function(portals) { + var resultPortals = new Array(); + $.each(portals, function(ind, portal) { + var portalLevel = parseInt(getPortalLevel(portal[2])); + if(portalLevel < portalRenderLimit.previousMinLevel) { + portalRenderLimit.portalsPreviousMinLevel[portalLevel].push(portal); + }else{ + resultPortals.push(portal); + } + }); + return resultPortals; +} + +window.portalRenderLimit.mergeLowLevelPortals = function(appendTo) { var resultPortals = appendTo ? appendTo : new Array(); for(var i = portalRenderLimit.getMinLevel(); i < portalRenderLimit.previousMinLevel; i++) { $.merge(resultPortals, portalRenderLimit.portalsPreviousMinLevel[i]); } + + // Reset portalsPreviousMinLevel, ensure they return only once + portalRenderLimit.resetPortalsPreviousMinLevel(); return resultPortals; } From a679710198419186301ee6290a508ecd6a87e955 Mon Sep 17 00:00:00 2001 From: Xelio Date: Fri, 1 Mar 2013 15:00:49 +0800 Subject: [PATCH 3/4] Code restructure 2 --- code/map_data.js | 4 ++-- code/portal_render_limit.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/map_data.js b/code/map_data.js index c620e404..517e84bb 100644 --- a/code/map_data.js +++ b/code/map_data.js @@ -127,13 +127,13 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { // Process the portals with portal render limit handler first // Low level portal will hold until last request var newPpp = portalRenderLimit.splitOrMergeLowLevelPortals(ppp); - handlePortalData(newPpp); + handlePortalsRender(newPpp); resolvePlayerNames(); renderUpdateStatus(); } -window.handlePortalData = function(portals) { +window.handlePortalsRender = function(portals) { var portalUpdateAvailable = false; var portalInUrlAvailable = false; diff --git a/code/portal_render_limit.js b/code/portal_render_limit.js index a726e729..0ab58107 100644 --- a/code/portal_render_limit.js +++ b/code/portal_render_limit.js @@ -92,7 +92,7 @@ window.portalRenderLimit.splitOrMergeLowLevelPortals = function(originPortals) { window.portalRenderLimit.handleFailRequest = function() { if(portalRenderLimit.isLastRequest()) { var resultPortals = portalRenderLimit.mergeLowLevelPortals(null); - handlePortalData(resultPortals); + handlePortalsRender(resultPortals); } } From 4113991201585bc6a1d42cbf68b6425e1f55a7a8 Mon Sep 17 00:00:00 2001 From: Xelio Date: Fri, 1 Mar 2013 15:31:15 +0800 Subject: [PATCH 4/4] Code restructure 3 --- code/map_data.js | 12 ++++++++++-- code/portal_render_limit.js | 20 +------------------- code/request_handling.js | 11 +++++++++++ 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/code/map_data.js b/code/map_data.js index 517e84bb..b7afe533 100644 --- a/code/map_data.js +++ b/code/map_data.js @@ -49,17 +49,25 @@ window.requestData = function() { $.each(tiles, function(ind, tls) { data = { minLevelOfDetail: -1 }; data.boundsParamsList = tls; - window.requests.add(window.postAjax('getThinnedEntitiesV2', data, window.handleDataResponse, portalRenderLimit.handleFailRequest)); + window.requests.add(window.postAjax('getThinnedEntitiesV2', data, window.handleDataResponse, window.handleFailedRequest)); }); } +// Handle failed map data request +window.handleFailedRequest = function() { + if(requests.isLastRequest('getThinnedEntitiesV2')) { + var leftOverPortals = portalRenderLimit.mergeLowLevelPortals(null); + handlePortalsRender(leftOverPortals); + } +} + // works on map data response and ensures entities are drawn/updated. window.handleDataResponse = function(data, textStatus, jqXHR) { // remove from active ajax queries list if(!data || !data.result) { window.failedRequestCount++; console.warn(data); - portalRenderLimit.handleFailRequest(); + handleFailedRequest(); return; } diff --git a/code/portal_render_limit.js b/code/portal_render_limit.js index 0ab58107..ec4e93a2 100644 --- a/code/portal_render_limit.js +++ b/code/portal_render_limit.js @@ -82,20 +82,13 @@ window.portalRenderLimit.splitOrMergeLowLevelPortals = function(originPortals) { portalRenderLimit.resetCounting(); portalRenderLimit.countingPortals(originPortals); - var resultPortals = portalRenderLimit.isLastRequest() + var resultPortals = requests.isLastRequest('getThinnedEntitiesV2') ? portalRenderLimit.mergeLowLevelPortals(originPortals) : portalRenderLimit.splitLowLevelPortals(originPortals); return resultPortals; } -window.portalRenderLimit.handleFailRequest = function() { - if(portalRenderLimit.isLastRequest()) { - var resultPortals = portalRenderLimit.mergeLowLevelPortals(null); - handlePortalsRender(resultPortals); - } -} - window.portalRenderLimit.countingPortals = function(portals) { $.each(portals, function(ind, portal) { var portalGuid = portal[0]; @@ -134,17 +127,6 @@ window.portalRenderLimit.mergeLowLevelPortals = function(appendTo) { return resultPortals; } -window.portalRenderLimit.isLastRequest = function() { - var result = true; - $.each(window.activeRequests, function(ind, req) { - if(req.action === 'getThinnedEntitiesV2') { - result = false; - return false; - } - }); - return result; -} - window.portalRenderLimit.getMinLevel = function() { if(!portalRenderLimit.initialized) return -1; if(!portalRenderLimit.minLevelSet) portalRenderLimit.setMinLevel(); diff --git a/code/request_handling.js b/code/request_handling.js index 6fe0acd3..6766fd5f 100644 --- a/code/request_handling.js +++ b/code/request_handling.js @@ -111,3 +111,14 @@ window.requests._callOnRefreshFunctions = function() { window.requests.addRefreshFunction = function(f) { window.requests._onRefreshFunctions.push(f); } + +window.requests.isLastRequest = function(action) { + var result = true; + $.each(window.activeRequests, function(ind, req) { + if(req.action === action) { + result = false; + return false; + } + }); + return result; +} \ No newline at end of file