File: ia\factories\MapFactory.js
/**
* Factory for creating maps.
*
* @author J Clare
* @class ia.MapFactory
* @param {ia.ComponentConfig} config The component config.
* @param {ia.Report} report The report object.
* @param {Object} componentGroup Hash table containing the Data and Interaction Groups that the component belongs to:
* {dataGroup:ia.DataGroup, interactionGroup:ia.InteractionGroup, comparisonInteractionGroup:ia.InteractionGroup}.
*/
ia.MapFactory = function(config, report, componentGroup)
{
var me = this;
// Data and Interaction groups that the components belongs to.
var interactionGroup = componentGroup.interactionGroup;
var dataGroup = componentGroup.dataGroup;
var comparisonInteractionGroup = componentGroup.comparisonInteractionGroup;
// This code executes every time the map data has changed.
dataGroup.mapData.addEventListener(ia.DataEvent.MAP_DATA_CHANGED, function(event)
{
onMapDataChange();
});
// This code executes every time the data groups thematic has changed.
// The thematic will change after any data change so only render
// here to avoid multiple rendering.
dataGroup.addEventListener(ia.Event.THEMATIC_CHANGED, function(event)
{
if (buildingMap) thematicChanged = true;
else
{
me.update();
me.render();
}
});
// This code executes every time a filter has changed.
dataGroup.addEventListener(ia.FilterEvent.FILTER_CHANGED, function(event)
{
if (event.filterFeatures.length > 0)
activeMap.zoomToFeatures(event.filterFeatures, [mapData.baseLayer]); // Zoom to filtered features.
else
activeMap.controller.zoomFull(); // Zoom full when filter is removed.
});
// Panel.
var panel;
// Map.
var thematicChanged = false; // Indicates that the thematic has changed.
var buildingMap = false; // Indicates that the map is currently being built.
var mapData; // ia.MapData
var map; // ia.Map
var gMap; // ia.GoogleMap
var activeMap; // Can be and ia.Map or ia.GoogleMap.
// Bounding box set from url parameters.
var bBoxFromParams;
if (report.url.params["bbox"+dataGroup.suffix])
{
var bb = report.url.params["bbox"+dataGroup.suffix].split(",");
bBoxFromParams = new ia.BoundingBox(parseFloat(bb[0]),
parseFloat(bb[1]),
parseFloat(bb[2]),
parseFloat(bb[3]));
}
// Updates the map when the map data has changed
function onMapDataChange()
{
// Second layer of double base layer reports are added to same map as first layer.
if (config === undefined)
{
updateDoubleBaseLayer();
}
else
{
// Remove any previous layers from the interaction group.
var mapLayers = map.getLayers();
for (var i = 0; i < mapLayers.length; i++)
{
var layer = mapLayers[i];
interactionGroup.removeComponent(layer);
}
// Remove map layers.
map.removeLayers();
// Set special properties for baselayers.
for (var i = 0; i < mapData.baseLayers.length; i++)
{
var layer = mapData.baseLayers[i];
layer.dataLabel = report.config.getComponent(config.id).getProperty("tip");
layer.interactive = true;
layer.tipFunction = function(item)
{
var s = ia.tipFunction(item, config.id);
return s;
};
layer.highlightColor = report.highlightColor;
layer.selectionColor = report.selectionColor;
layer.highlightOpacity = report.highlightOpacity;
layer.selectionOpacity = report.selectionOpacity;
interactionGroup.addComponent(layer);
}
// Add layers to map first to maintain layer order.
for (var i = 0; i < mapData.layers.length; i++)
{
var layer = mapData.layers[i];
map.addLayer(mapData.layers[i]);
}
// Set the bounding box.
map.controller.defaultBBox = mapData.mapBBox;
if (!mapData.useGoogleMaps)
{
if (bBoxFromParams) map.controller.zoomToBBox(bBoxFromParams);
else map.controller.zoomFull();
}
else map.render();
bBoxFromParams = undefined;
if (thematicChanged)
{
thematicChanged = false;
me.update();
me.render();
}
}
};
// Updates the double base layer.
function updateDoubleBaseLayer()
{
map = report.getComponent("map");
activeMap = report.getComponent("activeMap");
mapData.noneBaseLayers = []; // Remove non-base layers from layer list.
var layer = mapData.baseLayers[1];
if (report.config.template === ia.DOUBLE_BASELAYER_REPORT)
{
layer.dataLabel = report.config.getComponent("map").getProperty("tip"+dataGroup.suffix);
layer.highlightColor = report.highlightColor;
layer.selectionColor = report.selectionColor;
layer.highlightOpacity = report.highlightOpacity;
layer.selectionOpacity = report.selectionOpacity;
layer.interactive = true;
layer.dataLabel = report.config.getComponent("map").getProperty("tip"+dataGroup.suffix);
layer.tipFunction = function(item)
{
var s = ia.tipFunction(item, "map", dataGroup.suffix);
return s;
};
interactionGroup.addComponent(layer);
}
else if (report.config.template === ia.DOUBLE_BASELAYER_REPORT_NEW)
{
layer.showDataTips = false;
layer.showLabels = false;
}
map.addLayer(layer);
};
/**
* Builds the component.
*
* @method build
* @param {Function} callbackFunction Called on completion of function, with the component id as the parameter.
*/
this.build = function(callbackFunction)
{
mapData = dataGroup.mapData;
// Second layer of double base layer reports are added to same map as first layer.
if (config === undefined)
{
updateDoubleBaseLayer();
if (callbackFunction !== undefined) callbackFunction.call(null, config ? config.id : 'map'); // Return
}
else
{
buildingMap = true;
// Panel.
panel = report.getWidget(config.id);
panel.exportFunction = function() {map.exportData(report.config.getProperty("saveImageText"));};
// Empty panel.
panel.content.empty();
// Map.
map = new ia.Map(config.id);
report.addComponent(config.id, map);
// Add listeners for map bounding box events.
function bBoxEventHandler(event)
{
// Update the map bbox url param.
var bb = map.getBBox();
report.url.params["bbox"+dataGroup.suffix] = bb.getXMin() + "," + bb.getYMin() + "," + bb.getXMax() + "," + bb.getYMax();
}
map.addEventListener(ia.BBoxEvent.BBOX_TRANSLATE, bBoxEventHandler);
map.addEventListener(ia.BBoxEvent.BBOX_SCALE, bBoxEventHandler);
var minZoom = config.getProperty("minZoomAllowed");
var maxZoom = config.getProperty("maxZoomAllowed");
if (mapData.useGoogleMaps)
{
gMap = new ia.GoogleMap(config.id,
mapData.googleMapType,
mapData.googleApiKey,
minZoom,
maxZoom,
config.getProperty("googleGreyscaleText"),
config.getProperty("googleOffText"));
activeMap = gMap;
gMap.addEventListener(ia.Event.MAP_READY, function()
{
// Set map bounding box.
if (mapData.mapBBox.getXMin() < -20000000) mapData.mapBBox.setXMin(-20000000);
if (mapData.mapBBox.getXMax() > 20000000) mapData.mapBBox.setXMax(20000000);
gMap.controller.defaultBBox = mapData.mapBBox;
if (bBoxFromParams) gMap.controller.zoomToBBox(bBoxFromParams);
else gMap.controller.zoomFull();
// Add IA Map as an overlay.
gMap.addMapOverlay(map);
});
report.addComponent("gMap"+dataGroup.suffix, gMap);
}
else
{
if (minZoom !== -1) map.minZoom = minZoom;
if (maxZoom !== -1) map.maxZoom = maxZoom
map.useNavigation(true);
activeMap = map;
}
map.addEventListener(ia.Event.MAP_READY, function()
{
onMapDataChange();
buildingMap = false;
if (callbackFunction !== undefined) callbackFunction.call(null, config.id);
});
// Append the map panel - this will trigger the MAP_READY event.
report.addComponent("activeMap"+dataGroup.suffix, activeMap);
panel.append(activeMap.container);
// Map copyright.
var copyright = $j('<div id="map-copyright" class="ia-map-copyright"></div>');
var txt = config.getProperty("copyrightText");
if (txt !== "" && txt !== undefined)
{
copyright.html(txt);
panel.append(copyright);
}
// Evaluation message.
if (report.evaluation) report.displayEvaluationMessage(panel);
// Map Tools.
var includeSearchTool = config.getProperty("includeSearchTool");
if (includeSearchTool === undefined) includeSearchTool = false;
if (includeSearchTool && dataGroup.suffix === "")
{
// For geocoding autocomplete ui.
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://code.jquery.com/ui/1.9.2/jquery-ui.js";
document.body.appendChild(script);
}
var mapTools = new ia.MapTools(activeMap, dataGroup, interactionGroup, mapData.useGoogleMaps, includeSearchTool);
mapTools.clearButtonText = config.getProperty("clearButtonText");
mapTools.filterButtonText = config.getProperty("filterButtonText");
mapTools.filterFunction = function()
{
if (interactionGroup.getSelection().length > 0)
dataGroup.setFilteredFeatures(interactionGroup.getSelection());
else if (dataGroup.getFilteredFeatures().length > 0)
dataGroup.clearFilter();
}
mapTools.clearFunction = function()
{
interactionGroup.clearSelection();
}
panel.append(mapTools.container);
report.addComponent("mapTools"+dataGroup.suffix, mapTools);
mapTools.render();
}
};
/**
* Updates the component.
*
* @method update
* @param {Function} callbackFunction Called on completion of function, with the component id as the parameter.
*/
this.update = function(callbackFunction)
{
mapData.baseLayer.setData(dataGroup.indicatorData);
if (callbackFunction !== undefined) callbackFunction.call(null, config ? config.id : 'map');
};
/**
* Renders the component.
*
* @method render
* @param {Function} callbackFunction Called on completion of function, with the component id as the parameter.
*/
this.render = function(callbackFunction)
{
map.render();
if (callbackFunction !== undefined) callbackFunction.call(null, config ? config.id : 'map');
};
};