Last active
December 30, 2015 23:59
-
-
Save clintconklin/7904705 to your computer and use it in GitHub Desktop.
jquery map plugin for retrieving json data and plotting the results in an arbitrary container; for more details, see http://blog.clintconklin.com/plotting-google-map-points-in-a-custom-arbitrary-element/
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
/* | |
options: | |
- datasource (requred): where to fetch the json data from | |
- bounds (required): the bounds option should come in like so: | |
{ | |
'lat': { | |
'from': 36.32, | |
'to': 39.28 | |
}, | |
'lng': { | |
'from': -75.15, | |
'to': -83.41 | |
} | |
} | |
- typeEvents (optional; default - all): restrict type of event | |
- numEvents (optional; default - 5): the number of events to show on the map | |
- markerOffset(optional; defaults to 0) - any additional marker offset; specify like so: | |
{ | |
'x': -7, | |
'y': -7 | |
} | |
*/ | |
(function($) { | |
var _PI = 3.1415926535898; | |
var methods = { | |
'init': function(options) { | |
return this.each(function() { | |
var $this = $(this), | |
data = $this.data('map'); | |
if (!data) { // plugin not initialized; setup | |
var typeEvents = (typeof options.typeEvents != 'undefined') ? options.typeEvents : 'all'; | |
var numEvents = (typeof options.numEvents != 'undefined') ? options.numEvents : 5; | |
var markerOffset = (typeof options.markerOffset != 'undefined') ? options.markerOffset : { 'x': 0, 'y': 0}; | |
options.bounds.lng.delta = options.bounds.lng.to - options.bounds.lng.from; | |
options.bounds.lat.bottomDegree = options.bounds.lat.to * _PI / 180; | |
var dimensions = { | |
'width': $this.width(), | |
'height': $this.height() | |
}; | |
var marker = { | |
'class': options.markerClass || 'marker', | |
'offset': null | |
}; | |
var tempMarker = $('<span class="' + (options.markerClass || 'marker') + '"></span>'); | |
// get our marker offsets | |
tempMarker.css({ 'position': 'absolute', 'opacity': 0 }); | |
$this.append(tempMarker); | |
marker.offset = { | |
'x': Math.round(tempMarker.width() / 2) + markerOffset.x, | |
'y': Math.round(tempMarker.height() / 2) + markerOffset.y | |
}; | |
tempMarker = tempMarker.remove(); | |
tempMarker = null; | |
var events = []; | |
$.ajax({ | |
'dataType': 'json', | |
'dataFilter': function(response, type) { | |
response = response.trim(); | |
if (response.substr(0, 2) == '//') { | |
response = response.substr(2, response.length); | |
} | |
return response; | |
}, | |
'url': options.datasource + '&type=' + encodeURIComponent(typeEvents) + '&results_per_page=' + encodeURIComponent(numEvents), | |
'success': function(response) { | |
var results = [], keys = response.RECORDS.COLUMNS, values = response.RECORDS.DATA; | |
// parse the cf json into something a little less unruly | |
for (var x = 0, length = values.length; x < length; x++) { | |
var currentValues = values[x]; | |
var parsed = {}; | |
for (var y = 0, valuesLength = currentValues.length; y < valuesLength; y++) { | |
parsed[keys[y].toLowerCase()] = currentValues[y]; | |
} | |
results.push(parsed); | |
} | |
for (x = 0; x < results.length; x++) { | |
events.push({ | |
'id': results[x].uid, | |
'url': results[x].url, | |
'name': results[x].name, | |
'date': results[x].date, | |
'summary': results[x].summary, | |
'desc': results[x].description, | |
'lat': results[x].lat, | |
'lng': results[x].lng, | |
'thumbnail': results[x].thumbnail | |
}); | |
} | |
$this.data('map', { | |
'tgarget': $this, | |
'bounds': options.bounds, | |
'events': events, | |
'dimensions': dimensions, | |
'marker': marker | |
}); | |
$this.map('populate'); | |
} | |
}); | |
} | |
}); | |
}, // init | |
'populate': function() { | |
return this.each(function() { | |
var $this = $(this), | |
data = $this.data('map'); | |
var markers = []; | |
$.each(data.events, function(index, event) { | |
var coords = $this.map('getXY', { 'lat': event.lat, 'lng': event.lng }); | |
// the id is a temp hack that won't work if there are multiple maps on a page; probably need to add an id to the init options | |
var marker = $('<a id="marker-' + index + '" class="' + data.marker['class'] + '"></a>'); | |
marker.css({ | |
'position': 'absolute', | |
'left': (coords.x - data.marker.offset.x) + 'px', | |
'top': (coords.y - data.marker.offset.y) + 'px' | |
}); | |
var desc = $(event.desc); // objects are easier to manipulate with script | |
if (event.thumbnail && event.thumbnail != '') { | |
desc.prepend($('<div class="popover-img"><img src="' + event.thumbnail + '" /></div>')) | |
} | |
if (event.friendly_url) { | |
desc.append($('<span> </span><a href="' + event.friendly_url + '">Read more.</a>')); | |
} | |
desc = desc.html(); | |
marker.popoverextended({ | |
'placement': 'top', | |
'html': true, | |
'title': event.name, | |
'content': desc, | |
'addClass': 'popover-map' | |
}); | |
marker.on('show', function() { | |
$.each(markers, function(x, m) { | |
if (m.attr('id') != 'marker-' + index) { | |
m.popoverextended('hide'); | |
} | |
}); | |
}); | |
marker.appendTo(data.target); | |
markers.push(marker); | |
}); | |
}); | |
}, // populate | |
/* | |
http://stackoverflow.com/questions/6172355/how-to-convert-lat-long-to-an-xy-coordinate-system-e-g-utm-and-then-map-this | |
Assuming this map does not cross prime meridian | |
Assuming pixel 0,0 is upper left, and pixel 600,800 is lower right. | |
Assuming map is Northern Hemisphere Only (no part of map is southern hemisphere) | |
Determine the left-most longitude in your 800x600 image (X) | |
Determine the east-most longitude in your 800x600 image (Y) | |
Determine Longitude-Diff (Z = Y - X) | |
Determine north-most latitude in your 800x600 image (A) | |
Determine south-most latitude in your 800x600 image (B) | |
Determine Longitude-Diff (C = A - B) | |
Given a Latitude and Longitude, to determine which pixel they clicked on: | |
J = Input Longitude | |
K = Input Latitude | |
Calculate X-pixel | |
XPixel = CInt(((Y - J) / CDbl(Z)) * 800) | |
Calculate Y-pixel | |
YPixel = CInt(((A - K) / CDbl(C)) * 600) | |
*/ | |
'getXY': function(coords) { | |
var $this = $(this), | |
data = $this.data('map'); | |
var x = data.bounds.lng.to; | |
var y = data.bounds.lng.from; | |
var z = y - x; | |
var a = data.bounds.lat.from; | |
var b = data.bounds.lat.to; | |
var c = a - b; | |
return { | |
'x': (((y - coords.lng) / z) * data.dimensions.width), | |
'y': (((a - coords.lat) / c) * data.dimensions.height) | |
}; | |
}, | |
'destroy': function() { | |
return this.each(function() { | |
var $this = $(this), | |
data = $this.data('map'); | |
$(window).unbind('.map'); | |
data.map.remove(); | |
$this.removeData('map'); | |
}); | |
} // destroy | |
}; // methods | |
$.fn.map = function(method) { | |
if (methods[method]) { | |
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); | |
} else if (typeof method === 'object' || !method) { | |
return methods.init.apply(this, arguments); | |
} else { | |
$.error('Method ' + method + ' does not exist on jQuery.map'); | |
} | |
}; | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment