Skip to content

Instantly share code, notes, and snippets.

@douglas-johnson
Last active June 2, 2016 18:51
Show Gist options
  • Save douglas-johnson/147065639b220b24fafc42950b043bc9 to your computer and use it in GitHub Desktop.
Save douglas-johnson/147065639b220b24fafc42950b043bc9 to your computer and use it in GitHub Desktop.
Javascript module for creating map points and maintaining their location resize.
(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