Last active
February 16, 2017 14:16
-
-
Save tistre/9092438 to your computer and use it in GitHub Desktop.
Google Maps demo for Tim’s simple JavaScript component test, see https://www.strehle.de/tim/weblog/archives/2014/02/19/1694
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
/* Namespace */ | |
var DCX = DCX || { }; | |
DCX.Ui = DCX.Ui || { }; | |
DCX.Ui.Model = DCX.Ui.Model || { }; | |
DCX.Ui.View = DCX.Ui.View || { }; | |
DCX.Ui.Controller = DCX.Ui.Controller || { }; | |
DCX.Ui.Service = DCX.Ui.Service || { }; | |
/* Demo page component */ | |
DCX.Ui.DemoPage = function(config) | |
{ | |
var _private = { }; | |
_private.config = config; | |
_private.$element = $(document); | |
_private.$model = $(_private.config.model).first(); | |
// Update page title when the address changes | |
_private.$model.on('data_changed.dcx_ui_model', function(e) | |
{ | |
if (e.data_key === 'address') | |
{ | |
document.title = e.data_value; | |
} | |
}); | |
}; | |
/* Contact info model */ | |
DCX.Ui.Model.ContactInfo = function(config) | |
{ | |
var _private = { }; | |
_private.config = config; | |
_private.data = { }; | |
_private.$element = $(_private.config.selector).first(); | |
// Update model data when components send new data | |
_private.$element.on('data_changed.dcx_ui_model', function(e) | |
{ | |
_private.data[ e.data_key ] = e.data_value; | |
}); | |
}; | |
/* Contact info controller */ | |
DCX.Ui.Controller.ContactInfo = function(config) | |
{ | |
var _private = { }; | |
_private.config = config; | |
_private.$element = $(_private.config.selector).first(); | |
_private.$model = $(_private.config.model).first(); | |
_private.$address_input = $(_private.config.address_input).first(); | |
_private.$map = $(_private.config.map).first(); | |
_private.$geocoder_service = $(_private.config.geocoder_service).first(); | |
// When the address changes in the model, update the input field value and map | |
_private.$model.on('data_changed.dcx_ui_model', function(e) | |
{ | |
if (e.data_key === 'address') | |
{ | |
if (e.data_origin !== 'address_input') | |
{ | |
_private.$address_input.trigger($.Event | |
( | |
'set_value.dcx_ui_textinput', | |
{ data_value: e.data_value } | |
)); | |
} | |
if (e.data_origin !== 'map') | |
{ | |
var result = DCX.Ui.getEventResult | |
( | |
_private.$geocoder_service, | |
'geocode.google_maps_geocoder', | |
{ address: e.data_value } | |
); | |
$.when(result).done(function() | |
{ | |
_private.$map.trigger($.Event | |
( | |
'pan_to.google_maps_map', | |
{ | |
location: result.gcr[ 0 ].geometry.location | |
} | |
)); | |
}); | |
} | |
} | |
}); | |
// When the user enters an address in the input field, change the model | |
_private.$address_input.on('value_changed.dcx_ui_textinput', function(e) | |
{ | |
_private.$model.trigger($.Event | |
( | |
'data_changed.dcx_ui_model', | |
{ | |
data_key: 'address', | |
data_value: e.data_value, | |
data_origin: 'address_input' | |
} | |
)); | |
}); | |
// When the map center changes, do a geocoder address lookup | |
// and publish its result as a model event | |
_private.$map.on('center_changed.google_maps_map', function(e) | |
{ | |
var result = DCX.Ui.getEventResult | |
( | |
_private.$geocoder_service, | |
'reverse_geocode.google_maps_geocoder', | |
{ location: e.center_location } | |
); | |
$.when(result).done(function() | |
{ | |
_private.$model.trigger($.Event | |
( | |
'data_changed.dcx_ui_model', | |
{ | |
data_key: 'address', | |
data_value: result.gcr[ 0 ].formatted_address, | |
data_origin: 'map' | |
} | |
)); | |
}); | |
}); | |
}; | |
/* Address text input component */ | |
DCX.Ui.View.AddressInput = function(config) | |
{ | |
var _private = { }; | |
_private.config = config; | |
_private.$element = $(_private.config.selector).first(); | |
_private.$button = $(_private.config.button).first(); | |
// Update the input value when requested | |
_private.$element.on('set_value.dcx_ui_textinput', function(e) | |
{ | |
if (_private.$element.val() === e.data_value) | |
{ | |
return; | |
} | |
_private.$element.val(e.data_value); | |
_private.$button.attr('disabled', 'disabled'); | |
}); | |
// When the user starts to type in the address input field, enable the "Jump to" button | |
_private.$element.on('keyup', function(e) | |
{ | |
_private.$button.removeAttr('disabled'); | |
}); | |
// When the user clicks the "Jump to" button, trigger a "value_changed" event | |
_private.$button.on('click', function(e) | |
{ | |
_private.$element.trigger($.Event | |
( | |
'value_changed.dcx_ui_textinput', | |
{ | |
data_value: _private.$element.val() | |
} | |
)); | |
}); | |
}; | |
/* Google Maps map component */ | |
DCX.Ui.View.GoogleMaps_Map = function(config) | |
{ | |
var _private = { }; | |
_private.config = config; | |
_private.$element = $(_private.config.selector).first(); | |
// Create Google Maps map | |
_private.map = new google.maps.Map | |
( | |
_private.$element[ 0 ], | |
_private.config.map_options | |
); | |
// Pan to coordinates if requested | |
_private.$element.on('pan_to.google_maps_map', function(e) | |
{ | |
_private.map.panTo(e.location); | |
}); | |
// Translate Google Maps events into jQuery custom events | |
google.maps.event.addListener(_private.map, 'center_changed', function() | |
{ | |
_private.$element.trigger($.Event | |
( | |
'center_changed.google_maps_map', | |
{ center_location: _private.map.getCenter() } | |
)); | |
}); | |
}; | |
/* Google Maps geocoder component */ | |
DCX.Ui.Service.GoogleMaps_Geocoder = function(config) | |
{ | |
var _private = { }; | |
_private.config = config; | |
_private.$element = $(_private.config.selector).first(); | |
// Create Google Maps geocoder | |
_private.geocoder = new google.maps.Geocoder(); | |
// Get location by address | |
_private.$element.on('geocode.google_maps_geocoder', function(e) | |
{ | |
var request = { address: e.address }; | |
var deferred = $.Deferred(); | |
_private.geocoder.geocode(request, function(results, status) | |
{ | |
if ((status === google.maps.GeocoderStatus.OK) && results[ 1 ]) | |
{ | |
// XXX is it okay to write custom data into the promise? | |
$.extend(true, deferred.promise(), { gcr: results }); | |
deferred.resolve(); | |
} | |
else | |
{ | |
deferred.reject(); | |
} | |
}); | |
return deferred.promise(); | |
}); | |
// Get address by location | |
_private.$element.on('reverse_geocode.google_maps_geocoder', function(e) | |
{ | |
var request = { location: e.location }; | |
var deferred = $.Deferred(); | |
_private.geocoder.geocode(request, function(results, status) | |
{ | |
if ((status === google.maps.GeocoderStatus.OK) && results[ 1 ]) | |
{ | |
// XXX is it okay to write custom data into the promise? | |
$.extend(true, deferred.promise(), { gcr: results }); | |
deferred.resolve(); | |
} | |
else | |
{ | |
deferred.reject(); | |
} | |
}); | |
return deferred.promise(); | |
}); | |
}; | |
/* Generic framework */ | |
DCX.Ui.component_selectors = [ ]; | |
DCX.Ui.createComponent = function(config) | |
{ | |
config = config || { }; | |
config.factory_function.call({ }, config); | |
if ($.inArray(config.selector, DCX.Ui.component_selectors) < 0) | |
{ | |
DCX.Ui.component_selectors.push(config.selector); | |
} | |
}; | |
DCX.Ui.createComponents = function(configs) | |
{ | |
if (! $.isArray(configs)) | |
{ | |
return; | |
} | |
$.each(configs, function(i, config) | |
{ | |
DCX.Ui.createComponent(config); | |
}); | |
$.each(DCX.Ui.component_selectors, function(i, selector) | |
{ | |
$(selector).first().trigger('initialize.dcx_ui_component'); | |
}); | |
}; | |
DCX.Ui.getEventResult = function($element, event_type, event_properties) | |
{ | |
var all_results = DCX.Ui.getAllEventResults($element, event_type, event_properties); | |
return all_results[ 0 ]; | |
}; | |
DCX.Ui.getAllEventResults = function($element, event_type, event_properties) | |
{ | |
var e = $.Event(event_type, event_properties); | |
$element.trigger(e); | |
if (e.result === undefined) | |
{ | |
return [ { } ]; | |
} | |
if (! $.isArray(e.result)) | |
{ | |
e.result = [ e.result ]; | |
} | |
return e.result; | |
}; | |
/* Generic framework - "loader" that initializes components */ | |
$(document).ready(function() | |
{ | |
DCX.Ui.createComponents(DCX.Ui.initialComponentConfig); | |
}); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment