diff --git a/code/map_data.js b/code/map_data.js index 363240c4..b7afe533 100644 --- a/code/map_data.js +++ b/code/map_data.js @@ -49,21 +49,28 @@ 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, 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); + handleFailedRequest(); 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 +79,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 +97,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 +105,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 +121,7 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { } }); }); - + $.each(ppp, function(ind, portal) { if(portal[2].portalV2['linkedFields'] === undefined) { portal[2].portalV2['linkedFields'] = []; @@ -128,12 +131,29 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { portal[2].portalV2['linkedFields'] = uniqueArray(p2f[portal[0]]); } }); + + // Process the portals with portal render limit handler first + // Low level portal will hold until last request + var newPpp = portalRenderLimit.splitOrMergeLowLevelPortals(ppp); + handlePortalsRender(newPpp); + + resolvePlayerNames(); + renderUpdateStatus(); +} + +window.handlePortalsRender = 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) { renderPortal(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); + }); var selectedPortalLayer = portals[oldSelectedPortal]; if(portalUpdateAvailable && selectedPortalLayer) selectedPortal = oldSelectedPortal; @@ -150,8 +170,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..ec4e93a2 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,28 @@ 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(); + 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(); + portalRenderLimit.resetPortalsPreviousMinLevel(); } window.portalRenderLimit.resetCounting = function() { @@ -43,13 +72,59 @@ window.portalRenderLimit.resetCounting = function() { } } -window.portalRenderLimit.pushPortal = 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.resetPortalsPreviousMinLevel = function() { + for(var i = 0; i <= MAX_PORTAL_LEVEL; i++) { + portalRenderLimit.portalsPreviousMinLevel[i] = new Array(); + } +} + +window.portalRenderLimit.splitOrMergeLowLevelPortals = function(originPortals) { + portalRenderLimit.resetCounting(); + portalRenderLimit.countingPortals(originPortals); + + var resultPortals = requests.isLastRequest('getThinnedEntitiesV2') + ? portalRenderLimit.mergeLowLevelPortals(originPortals) + : portalRenderLimit.splitLowLevelPortals(originPortals); + + return resultPortals; +} + +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.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; } window.portalRenderLimit.getMinLevel = function() { 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 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;