Ext.ns('S100'); // Create the map and the markers. Each places layer will be managed by a cluster, to support turning // on/off the pins. S100.Map = function(mapId, latLng) { this.mapId = mapId; this.latLng = latLng; this.layers = {}; this.baseLayers = []; this.init(); this.setupEvents(); }; S100.Map.prototype.init = function() { // this.setupStores(); this.createMap(); this.setupControls(); }; S100.Map.prototype.setupEvents = function() { // Ext.fly(this.mapId).on('click', function() { // console.log('clicked') // }, this) // Ext.fly(this.mapId).on('click', function() { // this.closeInfoWindows(); // }, this) }; S100.Map.prototype.setupStores = function() { // console.log(this.baseLayers) Ext.iterate(S100.Map.places, function(layerName, layer) { // console.log(S100.Map.places[layer.name]) this[layerName+'Store'] = new Ext.data.JsonStore({ // store configs // autoDestroy: true, storeId: layerName+'Store', proxy: { type: 'memory', data: S100.Map.places[layerName] // reader: { // type: 'json', // root: layerName, // idProperty: 'id' // } }, //alternatively, a Ext.data.Model name can be given (see Ext.data.Store for an example) fields: ['name'] }); }, this); }; S100.Map.prototype.createMap = function() { var mapOptions = { zoom: 11, center: this.latLng, // navigationControl: false, navigationControlOptions: { style: google.maps.NavigationControlStyle.SMALL }, // scaleControl: true, streetViewControl: true, mapTypeControlOptions: { mapTypeIds: [google.maps.MapTypeId.ROADMAP, google.maps.MapTypeId.TERRAIN, 's100map'], position: google.maps.ControlPosition.RIGHT // style: google.maps.MapTypeControlStyle.DROPDOWN_MENU } }; this.map = new google.maps.Map(Ext.fly(this.mapId).dom, mapOptions); this.map.mapTypes.set('s100map', this.setupStyledMap("S100 Map")); this.map.setMapTypeId('s100map'); // Make the info window close when clicking anywhere on the map. google.maps.event.addListener(this.map, 'click', this.closeInfoWindows.createDelegate(this)); }; S100.Map.prototype.setupControls = function() { this.layerControls = Ext.get(document.createElement('div')); this.layerControls.addClass('s100-map-controls layer-controls'); this.map.controls[google.maps.ControlPosition.TOP_RIGHT].push(this.layerControls.dom); this.filterControl = Ext.get(document.createElement('div')); this.filterControl.addClass('s100-map-controls filter-controls'); this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(this.filterControl.dom); this.setupLegend(); this.setupKeyworkFilterNav(); }; S100.Map.prototype.setupKeyworkFilterNav = function() { var tpl = new Ext.XTemplate( '' ); this.filterControl.insertFirst({ id: 'keyword-filter', cls: 'keyword-filter', html: tpl.apply(S100.Map.keywords) }).on('change', this.onKeywordFilterSelect, this); }; S100.Map.prototype.onKeywordFilterSelect = function(evt, target) { this.addFilterLayer('keyword', Ext.get(target).getValue(true)); }; S100.Map.prototype.setupLegend = function() { this.legend = Ext.get(document.createElement('div')); this.legend.set({'id': 's100-map-legend'}); var spec = { tag: 'ol', cn: [ {tag: 'li', cls: 's100-person', html: 'Seattle 100
Person'}, {tag: 'li', cls: 'c100-person', html: 'Community 100
Person'}, {tag: 'li', cls: 's100-place', html: 'Seattle 100
Place'}, {tag: 'li', cls: 'c100-place', html: 'Community 100
Place'} ] }; this.legend.insertFirst({ id: 'map-legend', el: 'div', cn: spec }).on('click', this.onLayerToggleNavClick, this); this.map.controls[google.maps.ControlPosition.RIGHT].push(this.legend.dom); }; // Add an initial layer to draw later S100.Map.prototype.addBaseLayer = function(layerName, layerTitle) { this.baseLayers.push({name: layerName, title: layerTitle}); }; // Draws all the initial layers S100.Map.prototype.drawBaseLayers = function() { // TODO check if the layers are already drawn Ext.each(this.baseLayers, function(layer) { this.setupLayer(layer.name, layer.title); }, this); }; // Sets up a new layer on the map stage S100.Map.prototype.setupLayer = function(layerName, layerTitle, data, isFilterLayer) { // If we already have this layer draw it back if (this.getLayer(layerName)) { var l = this.getLayer(layerName); this.addLayerToggleNav(l); l.draw(); return l; } var layer = new S100.MapLayer(this, layerName, layerTitle, data); this.layers[layerName] = layer; if (!isFilterLayer) { this.addLayerToggleNav(layer); } return layer; }; // Finds data by type and slug for a person or filters by keyword S100.Map.prototype.addFilterLayer = function(type, key) { // Assemble the data for the layer var ids = [], data, layerName, layerTitle, filterLayer, places = [], people = []; if ('person' == type) { data = {}; Ext.each(S100.Map.places[type], function(item) { if (key == item.slug) { // Get the ids for the person's places Ext.each(item.places, function(placeItem) { ids.push(placeItem.id); }); data = item; // Get place items for found ids Ext.each(S100.Map.places['place'], function(placeItem) { if (ids.indexOf(placeItem.id) > -1) { places.push(placeItem); if (places.length == ids.length) return false; // Stop loop } }); // overwrite the places on item data.places = places; return false; } }); layerTitle = data.name; layerName = data.slug; } else if ('keyword' == type) { var keywordName; data = []; Ext.iterate(S100.Map.places, function(modelName, model, placeModels) { Ext.each(model, function(item) { Ext.each(item.keywords, function(keyword) { if (key == keyword.id) { data.push(item); keywordName = keyword.name; } }); }); }); if (keywordName) { layerTitle = keywordName; layerName = keywordName.urlize(); } } // Clear out all the layers and add a new filter layer if (!Ext.isEmpty(data)) { this.clearLayers(); filterLayer = this.setupLayer(layerName, layerTitle, data, true); this.setFilter(filterLayer); this.map.setCenter(this.latLng); this.map.setZoom(12); } }; // Sets up a filter for the map, which clears all layers and layers toggle buttons. // Should replace the toggle buttons with an indicator // of what is being filtered (keywords, person, etc) S100.Map.prototype.setFilter = function(filterLayer) { this.removeFilterControlNav(); this.filterLayer = filterLayer; this.activeFilter = filterLayer.getName(); this.filterControl.insertFirst({ el: 'div', cls: 'active filter-name', html: filterLayer.getTitle() }); this.filterControl.insertFirst({ el: 'div', cls: 'layer-control remove-filter', html: 'Remove Filter' }).on('click', this.onRemoveFilterClick, this); }; S100.Map.prototype.onRemoveFilterClick = function() { location.hash = ''; this.activeFilter = null; this.filterControl.purgeAllListeners(); this.removeFilterControlNav(); this.setupKeyworkFilterNav(); this.clearLayer(this.filterLayer); this.drawBaseLayers(); }; S100.Map.prototype.removeFilterControlNav = function(layer) { if (!this.filterControl.first()) return; var filterNavNodes = Ext.get(this.filterControl).select('.layer-control, .keyword-filter, .filter-name'); filterNavNodes.removeAllListeners(); filterNavNodes.remove(); }; S100.Map.prototype.hideLayer = function(layer) { layer.clearLayer(); }; S100.Map.prototype.clearLayer = function(layer) { this.removeLayerToggleNav(layer); layer.clearLayer(); }; S100.Map.prototype.clearLayers = function() { Ext.iterate(this.layers, function(layerName, layer) { this.clearLayer(layer); }, this); }; S100.Map.prototype.setupStyledMap = function(mapName) { var mapStyles = [ { // featureType: "all", // elementType: "all", stylers: [ { saturation: -100 } ] } ]; // Give the new style a button name var styledMapOptions = { name: mapName }; return new google.maps.StyledMapType(mapStyles, styledMapOptions); }; S100.Map.prototype.addLayerToggleNav = function(layer) { if (this.layerControls.child('#toggle-'+layer.getName())) return; this.layerControls.insertFirst({ id: 'toggle-'+layer.getName(), el: 'div', "data-layer-name": layer.getName(), cls: 'active toggle-layer toggle-'+layer.getName(), html: layer.getTitle() }).on('click', this.onLayerToggleNavClick, this); }; S100.Map.prototype.removeLayerToggleNav = function(layer) { var layerNav = Ext.get('toggle-'+layer.getName()); if (layerNav) { // Ext.removeNode(layerNav); layerNav.removeAllListeners(); layerNav.remove(); } }; S100.Map.prototype.onLayerToggleNavClick = function(evt, target) { target = Ext.get(target); var layer = this.getLayer(Ext.get(target).getAttribute('data-layer-name')); target.toggleClass('active'); if (target.hasClass('active')) { this.setupLayer(layer.getName()); } else { this.hideLayer(layer); } }; S100.Map.prototype.closeInfoWindows = function() { Ext.iterate(this.layers, function(layerName, layer, obj) { obj[layerName].closeInfoWindow(); }); }; S100.Map.prototype.getLayer = function(layerName) { return this.layers[layerName]; }; S100.Map.prototype.getDomId = function() { return this.mapId; };