Last active
June 2, 2016 18:51
-
-
Save douglas-johnson/147065639b220b24fafc42950b043bc9 to your computer and use it in GitHub Desktop.
Javascript module for creating map points and maintaining their location resize.
This file contains hidden or 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($){ | |
var $mapBody = null, | |
$mapArticles = null, | |
mapAspect = 5 / 3, | |
mapFullWidth = 1600, | |
mapBreakWidth = 1024, | |
mapWidth = 1600, | |
mapHeight = 960 | |
; | |
var mapPoints = new Array(); | |
/** | |
* Class: MapPoint | |
* | |
* @param string id | |
* @param string src | |
* @param string title | |
* @param array original_size | |
* @param array original_position | |
* | |
*/ | |
var MapPoint = function( id, src, title, original_size, original_position ){ | |
this.id = id; | |
this.src = src; | |
this.title = title; | |
// Replace with jQuery Object | |
// Equivalent to $( '#' + this.id ) | |
this.$object = null; | |
this.sizes = { | |
original: original_size, | |
current: [] | |
}; | |
this.positions = { | |
original: original_position, | |
current: [] | |
} | |
}; | |
MapPoint.prototype = {}; | |
/** | |
* Insert | |
* | |
* Add the map point element to the DOM | |
* Create an IMG element and append it to the map body | |
* Assign this.$object | |
*/ | |
MapPoint.prototype.insert = function(){ | |
var self = this; | |
$mapBody.append( | |
$( '<img />' ) | |
.attr( 'class', 'wicked_city_map-point' ) | |
.attr( 'id', self.id ) | |
.attr( 'src', self.src ) | |
.attr( 'alt', self.title ) | |
.attr( 'title', self.title ) | |
.css( { | |
'left' : self.positions.original[0] + 'px', | |
'top' : self.positions.original[1] + 'px' | |
} ) | |
); | |
self.$object = $( '#' + self.id ); | |
}; | |
/** | |
* Position | |
* | |
* Update the Map Point size and position based on | |
* a ratio of how the overall size of the map has changed | |
*/ | |
MapPoint.prototype.position = function( ratio ){ | |
var self = this; | |
self.sizes.current[0] = ratio * self.sizes.original[0]; | |
self.sizes.current[1] = ratio * self.sizes.original[1]; | |
self.positions.current[0] = ratio * self.positions.original[0]; | |
self.positions.current[1] = ratio * self.positions.original[1]; | |
self.$object.css( { | |
'width': self.sizes.current[0] + 'px', | |
'left': self.positions.current[0] + 'px', | |
'top': self.positions.current[1] + 'px', | |
} ); | |
}; | |
/** | |
* Events On | |
* | |
* Bind click events to the map point | |
*/ | |
MapPoint.prototype.events_on = function(){ | |
var self = this; | |
self.$object | |
.on( 'mouseenter', function(){ | |
$( this ).addClass( 'hover' ); | |
} ) | |
.on( 'mouseleave', function(){ | |
$( this ).removeClass( 'hover' ); | |
} ) | |
.on( 'click', function(){ | |
self.open(); | |
} ); | |
}; | |
/** | |
* Events Off | |
* | |
* Unbind click events from the map point | |
*/ | |
MapPoint.prototype.events_off = function(){ | |
var self = this; | |
self.$object | |
.off( 'mouseenter' ) | |
.off( 'mouseleave' ) | |
.off( 'click' ); | |
}; | |
/** | |
* Open the Map Overlay | |
* | |
* Replace the overlay content with the content | |
* of the post associated with this map point. | |
*/ | |
MapPoint.prototype.open = function(){ | |
var self = this, | |
html = $( '[data-wc-venue-id="' + self.id + '"]' ).html(); | |
$( '.wicked_city_map-content' ).html( html ) | |
$( '.wicked_city_map-overlay' ).show(); | |
}; | |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
/** | |
* Initialize | |
* | |
* Ensure the necessary DOM elements are present. | |
* Load the map background, and add map points on callback. | |
* Register the module for use of on_resize events | |
*/ | |
function init() { | |
$mapBody = $( '.wicked_city_map-internal' ); | |
if ( 0 === $mapBody.length ) { | |
return app; | |
} | |
$mapArticles = $( '.wicked_city_articles-venue' ); | |
if ( 0 === $mapArticles.length ){ | |
return app; | |
} | |
_load_map_background( function( background_loaded ){ | |
if ( false === background_loaded ) { | |
$mapBody.addClass( 'load_error' ); | |
return; | |
} | |
_create_venue_objects(); | |
_insert_venue_objects(); | |
_position_venue_objects(); | |
if( _get_width() >= mapBreakWidth ){ | |
_bind_venue_events(); | |
} | |
$mapBody.addClass( 'revealed' ); | |
} ); | |
app.site.register_module( 'wicked_city_map' ); | |
return app; | |
} | |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
/** | |
* Load Map Background | |
* | |
* Use an Image class to load the map background. | |
* Onload insert into DOM and return positive callback. | |
* Onerror return negative callback. | |
* | |
* @param function callback | |
*/ | |
function _load_map_background( callback ){ | |
var img = new Image(), | |
src = $mapBody.data( 'wc-map-src' ); | |
img.onload = function(){ | |
$mapBody | |
.append( | |
$( '<img />' ) | |
.attr( 'class', 'wicked_city_map-background' ) | |
.attr( 'id', self.id ) | |
.attr( 'src', src ) | |
) | |
.removeClass( 'loading' ); | |
return callback( true ); | |
}; | |
img.onerror = function(){ | |
return callback( false ); | |
}; | |
img.src = src; | |
} | |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
/** | |
* String to Array utility | |
* | |
* @see | |
* @param string str | |
* @return array | |
*/ | |
function string_to_array( str ) { | |
return ( new Function( 'return [' + str + '];' )() ); | |
} | |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
/** | |
* Create Venue Objects | |
* | |
* Create an instance of the Map Point class | |
* for each MapArticle elements currently in the DOM. | |
* Push to mapPoints array | |
*/ | |
function _create_venue_objects() { | |
if ( null === $mapArticles ){ | |
return; | |
} | |
$mapArticles.each( function( index ) { | |
var $this = $( this ), | |
id = $this.data( 'wc-venue-id' ), | |
src = $this.data( 'wc-venue-src' ), | |
title = $this.data( 'wc-venue-title' ), | |
size = string_to_array( $this.data( 'wc-venue-size' ) ), | |
pos = string_to_array( $this.data( 'wc-venue-position' ) ), | |
point = new MapPoint( id, src, title, size, pos ); | |
mapPoints.push( point ); | |
} ); | |
} | |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
/** | |
* Insert Venue Objects | |
* | |
* For each object in the mapPoint array, call the insert() function | |
*/ | |
function _insert_venue_objects(){ | |
for ( i in mapPoints ) { var mapObject = mapPoints[i]; | |
mapObject.insert(); | |
} | |
} | |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
/** | |
* Bind Venue Events | |
* | |
* For each object in the mapPoint array, call the events_on() function. | |
* Bind click events to hide the content and overlay. | |
*/ | |
function _bind_venue_events(){ | |
for ( i in mapPoints ) { var mapObject = mapPoints[i]; | |
mapObject.events_on(); | |
} | |
$( '.wicked_city_map-background, .wicked_city_map-close' ).on( 'click', function(){ | |
$( '.wicked_city_map-content' ).html( '' ); | |
$( '.wicked_city_map-overlay' ).hide(); | |
} ); | |
} | |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
/** | |
* Bind Venue Objects | |
* | |
* For each object in the mapPoint array, call the events_off() function. | |
* Unbind click events that hide the content and overlay. | |
*/ | |
function _unbind_venue_events(){ | |
for ( i in mapPoints ) { var mapObject = mapPoints[i]; | |
mapObject.events_off(); | |
} | |
$( '.wicked_city_map-background, .wicked_city_map-close' ).off( 'click' ); | |
$( '.wicked_city_map-content' ).html( '' ); | |
$( '.wicked_city_map-overlay' ).hide(); | |
} | |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
/** | |
* Get Width | |
* Ensure a function that uses the width value has a value available | |
* @param int | undefined width | |
*/ | |
function _get_width( width ){ | |
if ( 'undefined' === typeof width ){ | |
width = $mapBody.width(); | |
} | |
return width; | |
} | |
/** | |
* Handle Event Attachment | |
* Based on the change in the map width, either bind or unbind click events. | |
* | |
* @param int | undefined width | |
*/ | |
function _handle_event_attachment( width ){ | |
width = _get_width( width ); | |
if ( mapWidth >= mapBreakWidth && width < mapBreakWidth ){ | |
_unbind_venue_events(); | |
} | |
else if ( mapWidth < mapBreakWidth && width >= mapBreakWidth ){ | |
_bind_venue_events(); | |
} | |
} | |
/** | |
* Position Venue Objects | |
* | |
* For each object in the mapPoints array, call the position() function | |
* @param float | undefined ratio | |
*/ | |
function _position_venue_objects( ratio ){ | |
if ( 'undefined' === typeof ratio ){ | |
ratio = _get_resize_ratio(); | |
} | |
for ( i in mapPoints ) { var mapObject = mapPoints[i]; | |
mapObject.position( ratio ); | |
} | |
} | |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
/** | |
* Get Resize Ratio | |
* Ensure a function that uses the resize ratio has a value to use | |
* | |
* @param int | undefined width | |
*/ | |
function _get_resize_ratio( width ){ | |
width = _get_width( width ); | |
return width / mapFullWidth; | |
} | |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
/** | |
* On Resize | |
* Called from main app | |
* | |
* Determine new width ratio of change | |
* Return if no change to map width | |
* Reposition elements and turn click events on or off as necessary. | |
*/ | |
function on_resize() { | |
var width = $mapBody.width(), | |
ratio = _get_resize_ratio( width ); | |
// Prevent resize of map is the same size | |
// Will not always change if the window does | |
if ( mapWidth === width ) { | |
return; | |
} | |
_handle_event_attachment( width ); | |
mapWidth = width; | |
_position_venue_objects( ratio ); | |
} | |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
/* return public-facing methods and/or vars */ | |
return { | |
init : init, | |
on_resize : on_resize | |
}; | |
}($)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment