Created
June 8, 2017 20:48
-
-
Save lkacenja/e27d9390ca2e74647289b7922547ded0 to your computer and use it in GitHub Desktop.
Js powering GOK trail map.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function ($, Drupal, window, document, undefined) { | |
// Establish namespaces | |
Drupal.trails = Drupal.trails || {}; | |
Drupal.trails.Views = Drupal.trails.Views || {}; | |
// Establish global pubsub | |
Backbone.pubSub = Backbone.pubSub || _.extend({}, Backbone.Events); | |
// Map config specific vars | |
var styles = [ | |
{ | |
featureType: "poi", | |
stylers: [ | |
{ visibility: "off" } | |
] | |
} | |
], | |
defaults = { | |
zoom: 7, | |
center: new google.maps.LatLng(38.717697, -98.292612), | |
styles: styles | |
}; | |
// Cheap template | |
function infoBoxTemplate(item) { | |
var output = item.node_title; | |
if (item.field_trails_in_network_node_title) { | |
output += ' in ' + item.field_trails_in_network_node_title; | |
} | |
output += '<div class="map-triangle"><div class="left-triangle"><div></div></div><div class="right-triangle"><div></div></div></div>'; | |
return output; | |
} | |
function infoBoxMediaTemplate(item) { | |
var output = "<a href='" + item.link + "'>"; | |
output += "<img src='" + item.large + "'/></a>"; | |
return output; | |
} | |
// VIEWS | |
Drupal.trails.Views.app = Backbone.View.extend({ | |
initialize : function(element) { | |
_.bindAll(this, 'renderInfoBox'); | |
// Some high level vars | |
this.markers = []; | |
this.mediaMarkers = []; | |
this.media = {}; | |
this.activeData = {}; | |
this.clicked = false; | |
// Check for settings | |
if (Drupal.settings.trailMap) { | |
if (Drupal.settings.trailMap.args) { | |
this.args = Drupal.settings.trailMap.args; | |
} | |
if (Drupal.settings.trailMap.activeTrail) { | |
this.activeTrail = Drupal.settings.trailMap.activeTrail; | |
} | |
if (Drupal.settings.trailMap.center) { | |
this.center = Drupal.settings.trailMap.center; | |
} | |
} | |
// Set element | |
this.setElement(element); | |
// Catch event from not-front-fitler-block.js | |
Backbone.pubSub.on('notFrontFilter:change', this.updateView, this); | |
// Subscribe to state change. | |
Backbone.pubSub.on('app:changeState', this.handleStateChange, this); | |
// Create a preloader and store it. | |
var preloader = new Drupal.trails.Views.Preloader; | |
this.preloader = preloader.render(); | |
// No Results | |
var noResults = new Drupal.trails.Views.NoResults; | |
this.noResults = noResults.render(); | |
// Create a new Google map instance and store it. | |
this.map = new google.maps.Map(this.el, defaults); | |
google.maps.event.addListener(this.map, 'zoom_changed', this.handleEvent(this, this.handleZoom)); | |
google.maps.event.addListener(this.map, 'click', this.handleEvent(this, this.handleOffClick)); | |
this.handleEvent(this, this.handleZoom).call(this.map); | |
// View-wide info box one per map. | |
this.infoBox = new InfoBox(); | |
google.maps.event.addListener(this.infoBox, 'closeclick', this.handleEvent(this, this.handleOffClick)); | |
// Trigger a single fetch with no filters for initial load. | |
Backbone.pubSub.trigger('notFrontFilter:change'); | |
}, | |
updateView : function(data) { | |
Backbone.pubSub.trigger('app:changeState', 'loading'); | |
if (this.args) { | |
data = data || {}; | |
data['arguments'] = this.args; | |
} | |
$.ajax({ | |
'url' : Drupal.settings.basePath + 'gdc/load/view/trails_landing_page/page/computed/node_trails_computed__trails_computed_trail', | |
'success' : this.handleResponse, | |
'type' : 'POST', | |
'data' : {'ajaxPost' : data}, | |
'context' : this, | |
'cache': false | |
}); | |
}, | |
handleResponse : function(data) { | |
var x, m, point, marker, feature, center; | |
// Clear the map | |
this.clear(); | |
data = JSON.parse(data); | |
if (!data || (data && data.length == 0)) { | |
$(this.el).append(this.noResults); | |
} | |
else { | |
this.noResults.detach(); | |
} | |
this.currentData = data; | |
for (x in data) { | |
// Markers | |
if (!data[x].start && console && console.log) { | |
console.log("Corrupt Dataset Skipped: "); | |
console.log(data[x]); | |
continue; | |
} | |
marker = new google.maps.Marker({ | |
position: new google.maps.LatLng(data[x].start.coordinates[1], data[x].start.coordinates[0]), | |
map: this.map, | |
id: x | |
}); | |
if (data[x].dont_show_trail == "dont_show") { | |
marker.setVisible(false); | |
} | |
marker.addListener('mouseover', this.handleEvent(this, this.handleMouseOver)); | |
marker.addListener('mouseout', this.handleEvent(this, this.handleMouseOut)); | |
marker.addListener('click', this.handleEvent(this, this.handleClick)); | |
this.markers.push(marker); | |
// Features (i.e. tracts are added via data layer) | |
if (data[x].geom) { | |
feature = {}; | |
feature.type = 'Feature'; | |
feature.id = x; | |
feature.geometry = data[x].geom; | |
feature.properties = feature.properties || {}; | |
if (this.activeTrail && this.activeTrail == data[x].nid) { | |
feature.properties.color = '#519D14'; | |
} | |
else { | |
feature.properties.color = '#000000'; | |
} | |
this.map.data.addGeoJson(feature); | |
} | |
if (data[x].media && data[x].media.length > 0) { | |
for (m in data[x].media) { | |
marker = new google.maps.Marker({ | |
position: new google.maps.LatLng(data[x].media[m].coordinates[1], data[x].media[m].coordinates[0]), | |
map: this.map, | |
id: data[x].media[m].link, | |
icon: data[x].media[m].tiny | |
}); | |
this.media[data[x].media[m].link] = data[x].media[m]; | |
marker.addListener('click', this.handleEvent(this, this.handleMediaClick)); | |
this.mediaMarkers.push(marker); | |
} | |
} | |
} | |
if (this.center) { | |
this.map.setZoom(12); | |
center = new google.maps.LatLng(this.center[1], this.center[0]); | |
this.map.panTo(center); | |
} | |
this.defaultDataStyles(); | |
this.handleEvent(this, this.handleZoom).call(this.map); | |
// View-wide info box one per map. | |
this.map.data.addListener('mouseover', this.handleEvent(this, this.handleMouseOver)); | |
this.map.data.addListener('mouseout', this.handleEvent(this, this.handleMouseOut)); | |
this.map.data.addListener('click', this.handleEvent(this, this.handleClick)); | |
Backbone.pubSub.trigger('app:changeState', 'ready'); | |
}, | |
clear: function() { | |
var x, | |
dataLayer = this.map.data; | |
for (x in this.markers) { | |
if (this.markers[x]) { | |
this.markers[x].setMap(null); | |
//this.markers[x] = null; | |
} | |
} | |
for (x in this.mediaMarkers) { | |
this.mediaMarkers[x].setMap(null); | |
} | |
this.markers = []; | |
this.mediaMarkers = []; | |
dataLayer.forEach( | |
function(feature) { | |
dataLayer.remove(feature); | |
} | |
); | |
}, | |
defaultDataStyles: function() { | |
var dataLayer = this.map.data; | |
dataLayer.map.data.forEach( | |
function(feature) { | |
var color = feature.getProperty('color'); | |
dataLayer.overrideStyle(feature, {strokeColor: color, fillColor: color}); | |
} | |
); | |
}, | |
renderInfoBox: function(item, marker, template) { | |
var height, $content, content = template.call(this, item); | |
this.infoBox.close(); | |
$content = $(content); | |
height = parseInt($content.height(), 10); | |
this.infoBox.setOptions({pixelOffset: new google.maps.Size(-100, -(height + 105))}); | |
this.infoBox.setContent(content); | |
this.infoBox.open(this.map, marker); | |
}, | |
deactivateFeature: function(id) { | |
var color, feature = this.map.data.getFeatureById(id); | |
if (feature) { | |
color = feature.getProperty('color'); | |
this.map.data.overrideStyle(feature, {strokeColor: color, fillColor: color}); | |
} | |
}, | |
// Sort of a kludge to handle our need of both contexts: | |
// Google Maps event context and this view. | |
// ctx is always this view and this is Google Maps. | |
handleEvent: function(ctx, callback) { | |
return function(e) { | |
callback.call(this, e, ctx); | |
} | |
}, | |
handleMouseOver: function(e, ctx) { | |
var id, feature; | |
if (typeof(e.feature) != 'undefined') { | |
feature = e.feature; | |
id = feature.getId(); | |
} | |
else if (this.id) { | |
id = this.id; | |
feature = ctx.map.data.getFeatureById(id); | |
} | |
ctx.map.data.overrideStyle(feature, {strokeColor: '#FFDE00'}); | |
}, | |
handleMouseOut: function(e, ctx) { | |
var id, feature; | |
if (typeof(e.feature) != 'undefined') { | |
feature = e.feature; | |
id = feature.getId(); | |
} | |
else if (this.id) { | |
id = this.id; | |
feature = ctx.map.data.getFeatureById(id); | |
} | |
if (id !== ctx.clicked) { | |
ctx.deactivateFeature(id); | |
} | |
}, | |
handleClick: function(e, ctx) { | |
var id; | |
if (ctx.clicked) { | |
ctx.deactivateFeature(ctx.clicked); | |
} | |
if (typeof(e.feature) != 'undefined') { | |
id = e.feature.getId(); | |
} | |
else if (this.id) { | |
id = this.id; | |
} | |
if (id && ctx.currentData[id]) { | |
ctx.clicked = id; | |
ctx.renderInfoBox(ctx.currentData[id], ctx.markers[id], infoBoxTemplate); | |
} | |
}, | |
handleOffClick: function(e, ctx) { | |
ctx.clicked = null; | |
ctx.infoBox.close(); | |
ctx.defaultDataStyles(); | |
}, | |
handleMediaClick: function (e, ctx) { | |
var id, media; | |
if (this.id) { | |
id = this.id; | |
media = ctx.media[id]; | |
ctx.renderInfoBox(media, this, infoBoxMediaTemplate); | |
} | |
}, | |
handleZoom: function(e, ctx) { | |
if (this.zoom >= 9) { | |
ctx.map.data.setStyle({visible: true}); | |
} | |
else { | |
ctx.map.data.setStyle({visible: false}); | |
} | |
}, | |
handleStateChange: function(state) { | |
if (state == 'ready') { | |
this.preloader.detach(); | |
$(this.el).css('opacity', 1); | |
} | |
if (state == 'loading') { | |
$(this.el).after(this.preloader); | |
$(this.el).css('opacity', .5); | |
} | |
} | |
}); | |
// Preloader | |
Drupal.trails.Views.Preloader = Backbone.View.extend({ | |
initialize : function() { | |
_.bindAll(this, 'render'); | |
}, | |
render : function() { | |
return this.template(); | |
}, | |
template : function() { | |
$img = $('<img/>'); | |
$img.attr({'src' : '/sites/all/modules/custom/goc_dynamic_components/js/preloader.gif', id : 'preloader'}); | |
$img.css({position : 'absolute', top : 254, left : 318}); | |
$wrapper = $('<div/>').attr('id', 'add-preloader'); | |
$wrapper.css({'position' : 'absolute', 'top': 0, 'left': 0, 'width' : 680, 'height' : 552, 'z-index' : 100}); | |
$wrapper.append($img); | |
return $wrapper; | |
} | |
}); | |
Drupal.trails.Views.NoResults = Backbone.View.extend({ | |
initialize : function() { | |
_.bindAll(this, 'render'); | |
}, | |
render : function() { | |
return this.template(); | |
}, | |
template : function() { | |
var msg = "Your search returned no results. Please try again.", | |
$div = $('<div/>'); | |
$div.addClass('no-results').text(msg); | |
return $div; | |
} | |
}); | |
Drupal.behaviors.trails = { | |
attach : function() { | |
$('#trail-map').once( | |
'trails', | |
function() { | |
// Fire everything off. | |
var App = new Drupal.trails.Views.app($(this)); | |
} | |
); | |
} | |
}; | |
})(jQuery, Drupal, this, this.document); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment