Skip to content

Instantly share code, notes, and snippets.

@niekvandepas
Last active August 29, 2015 14:22
Show Gist options
  • Save niekvandepas/a69ee05e38f4e867b31a to your computer and use it in GitHub Desktop.
Save niekvandepas/a69ee05e38f4e867b31a to your computer and use it in GitHub Desktop.
McDonalds storefinder
(function() {
alert('testing')
window.mcdStoreLocator = {};
// Simple JavaScript Templating
// John Resig - http://ejohn.org/ - MIT Licensed
(function(){
var cache = {};
mcdStoreLocator.createMicroTemplate = function createMicroTemplate(label, element) {
if (cache[label]) return cache[label];
var str = element.textContent;
var returnFunc = new Function("obj",
"var p=[],print=function(){p.push.apply(p,arguments);};" +
// Introduce the data as local variables using with(){}
"with(obj){p.push('" +
// Convert the template into pure JavaScript
str
.replace(/[\r\t\n]/g, " ")
.split("<%").join("\t")
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%>/g, "',$1,'")
.split("\t").join("');")
.split("%>").join("p.push('")
.split("\r").join("\\'")
+ "');}return p.join('');");
cache[label] = returnFunc;
return cache[label];
};
})();
mcdStoreLocator.StoreLocator = function() {
this.templates = {};
this.locationData = [];
this.currentFilters = [];
this.activeMarkers = [];
this.youAreHereMarker = null;
this.isSmallWidth = false;
this.isLoading = false;
this.supportGeolocation = false;
this.mapMarkerIcons = {
youAreHere: {
url: mcdStoreLocatorSettings.assetPath + "/img/marker-you@2x.png",
scaledSize: new google.maps.Size(82 / 2, 92 / 2),
origin: new google.maps.Point(0,0),
anchor: new google.maps.Point(39 / 2, 82 / 2)
},
location: {
url: mcdStoreLocatorSettings.assetPath + "/img/marker-location@2x.png",
scaledSize: new google.maps.Size(60 / 2, 86 / 2),
origin: new google.maps.Point(0,0),
anchor: new google.maps.Point(30 / 2, 82 / 2)
},
}
this.divResults = document.querySelector(".storelocator__results");
this.divResultsList = document.querySelector(".storelocator__results-list");
this.divViews = document.querySelector(".storelocator__views");
this.divSingleViewContainer = document.querySelector(".storelocator__single-view-container");
this.divNoResults = $(".storelocator__no-results");
this.divAcceptLocation = $(".storelocator__accept-location");
this.filterButtons = $(".storelocator__filter");
this.iconResetFilters = $(".storelocator__filter[data-filter=none]").find(".storelocator__filtericon");
this.divFiltersListContainer = $(".storelocator__filters-list-container");
this.ulFiltersList = $(".storelocator__filters-list");
this.btnFilterArrowUp = $(".storelocator__filters-arrow--up");
this.btnFilterArrowDown = $(".storelocator__filters-arrow--down");
this.searchField = $(".storelocator__input-location");
this.btnCurrentPosition = $(".storelocator__btn-current-position");
this.searchForm = $(".storelocator__search-form");
this.btnBack = document.querySelector(".storelocator__content-title--back-button");
this.init();
}
mcdStoreLocator.StoreLocator.prototype.init = function() {
this.onResize();
this.initMap();
this.initTemplates();
this.initEvents();
this.initStartValues();
if (this.searchField.val() == "") {
this.autoLocateAndGetCloseRestaurants();
}else{
this.searchForm.trigger("submit");
}
}
mcdStoreLocator.StoreLocator.prototype.initMap = function() {
this.map = new google.maps.Map(document.querySelector(".storelocator__map"), {
zoom: 7,
center: new google.maps.LatLng(52.03366734651407, 5.429455423242189),
mapTypeId: google.maps.MapTypeId.ROADMAP,
draggable: !this.isSmallWidth,
streetViewControl: false,
disableDefaultUI: true,
zoomControl: true,
zoomControlOptions: {
position: google.maps.ControlPosition.TOP_RIGHT,
style: google.maps.ZoomControlStyle.SMALL
},
panControl: !this.isSmallWidth,
panControlOptions: {
position: google.maps.ControlPosition.TOP_RIGHT
}
});
this.geocoder = new google.maps.Geocoder();
}
mcdStoreLocator.StoreLocator.prototype.initTemplates = function() {
var _this = this;
$("script[store-locator-micro-template]").each(function(i, el) {
var templateName = $(el).attr("store-locator-micro-template");
_this.templates[templateName] = mcdStoreLocator.createMicroTemplate(templateName, el);
});
}
mcdStoreLocator.StoreLocator.prototype.initEvents = function() {
var _this = this;
this.btnBack.addEventListener("click", function() {
_this.toggleSingleView(false, null, true);
});
this.searchForm.bind("submit", function(event) {
event.preventDefault();
_this.searchForLocation(_this.searchField.val(), function(data) {
var location = data[0].geometry.location;
_this.getLocations(location.lat(), location.lng(), 10);
});
});
this.searchField.bind("click", function(event) {
_this.searchField.select();
});
this.btnFilterArrowUp.bind("click", function(event) {
_this.divFiltersListContainer.animate({
scrollTop: 0
});
_this.btnFilterArrowUp.hide();
_this.btnFilterArrowDown.show();
});
this.btnFilterArrowDown.bind("click", function(event) {
_this.divFiltersListContainer.animate({
scrollTop: _this.ulFiltersList.height() - _this.divFiltersListContainer.height()
});
_this.btnFilterArrowUp.show();
_this.btnFilterArrowDown.hide();
});
this.btnCurrentPosition.bind("click", function(event) {
if (_this.supportGeolocation) _this.autoLocateAndGetCloseRestaurants();
});
this.filterButtons.each(function(i, el) {
var tar = $(el);
var iconTarget = tar.find(".storelocator__filtericon");
var filter = tar.attr("data-filter");
// Reset filter-button
if (filter == "none") {
tar.bind("click", function() {
_this.resetFilters();
});
}else{
// All filters
tar.bind("click", function() {
iconTarget.toggleClass("active");
if (iconTarget.is(".active")) {
_this.toggleFilter(filter, true);
}else{
_this.toggleFilter(filter, false);
}
_this.applyFilters(_this.currentFilters);
})
}
});
$(window).bind("resize", function() {
_this.onResize();
});
}
mcdStoreLocator.StoreLocator.prototype.initStartValues = function() {
if (mcdStoreLocatorSettings.filters) {
var filters = mcdStoreLocatorSettings.filters.split(",");
for (var i = 0; i < filters.length; i++) {
$(".storelocator__filter[data-filter="+filters[i]+"]").click();
}
}
}
mcdStoreLocator.StoreLocator.prototype.onResize = function() {
var _this = this;
if (window.innerWidth < 768) {
this.isSmallWidth = true;
}else{
this.isSmallWidth = false;
}
}
mcdStoreLocator.StoreLocator.prototype.toggleLoading = function(flag) {
var _this = this;
this.isLoading = flag;
if (flag) {
$(_this.divResults).toggleClass("loading", true);
_this.searchField.attr("disabled", true);
}else{
$(_this.divResults).toggleClass("loading", false);
_this.searchField.attr("disabled", false);
}
}
mcdStoreLocator.StoreLocator.prototype.autoLocateAndGetCloseRestaurants = function() {
var _this = this;
_this.resetResults();
_this.searchField.val("Even wachten a.u.b.");
//_this.toggleLoading(true);
if (navigator.geolocation) {
_this.divAcceptLocation.show();
_this.supportGeolocation = true;
navigator.geolocation.getCurrentPosition(function(position) {
_this.divAcceptLocation.hide();
var latlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
_this.setCenterAndZoom(latlng, 12);
_this.searchForLocation(latlng, function(data) {
var location = data[0].geometry.location;
if (!_this.youAreHereMarker) {
_this.youAreHereMarker = new google.maps.Marker({
position: new google.maps.LatLng(location.lat(), location.lng()),
animation: google.maps.Animation.DROP,
icon: _this.mapMarkerIcons.youAreHere,
map: _this.map
});
}
_this.getLocations(location.lat(), location.lng(), 10);
});
}, function(error) {
_this.divAcceptLocation.hide();
_this.supportGeolocation = false;
console.log(error);
_this.searchField.val("");
_this.toggleLoading(false);
_this.btnCurrentPosition.addClass("not-available");
});
}else{
_this.supportGeolocation = false;
_this.searchField.val("");
_this.toggleLoading(false);
_this.btnCurrentPosition.addClass("not-available");
}
}
mcdStoreLocator.StoreLocator.prototype.callAPI = function(action, data, callback) {
data.action = action;
data.storelocator_v2 = true;
$.ajax({
url: window.location.href,
type: "post",
dataType: "json",
data: data,
success: alert('testing at line 282'),
error: function() {
throw("Error in api");
}
});
}
mcdStoreLocator.StoreLocator.prototype.resetResults = function() {
var _this = this;
_this.locationData = [];
_this.divResultsList.innerHTML = "";
this.divNoResults.hide();
this.clearMarkers();
this.toggleSingleView(false);
}
mcdStoreLocator.StoreLocator.prototype.clearMarkers = function() {
for (var i = 0; i < this.activeMarkers.length; i++) {
var marker = this.activeMarkers[i];
marker.setMap(null);
marker = null;
}
this.activeMarkers = [];
}
mcdStoreLocator.StoreLocator.prototype.getLocations = function(lat, lon, distance) {
var _this = this;
_this.resetResults();
_this.toggleLoading(true);
_this.callAPI("getLocations", {
lat: lat,
lon: lon,
distance: distance
}, function(data) {
_this.locationData = data;
_this.processLocationData();
_this.toggleLoading(false);
_this.setCenterAndZoom(new google.maps.LatLng(lat, lon), 12);
_this.applyFilters(_this.currentFilters);
});
}
mcdStoreLocator.StoreLocator.prototype.processLocationData = function() {
var _this = this;
for (var i = 0; i < _this.locationData.length; i++) {
var location = _this.locationData[i];
location.openStatus = _this.calculateOpenStatus(location.openTimes);
if (location.openTimesMcDrive) location.mcDriveOpenStatus = _this.calculateOpenStatus(location.openTimesMcDrive);
// add open status to features for filtering
if (location.openStatus.isOpen || (location.mcDriveOpenStatus && location.mcDriveOpenStatus.isOpen)) location.features.push("open");
}
}
mcdStoreLocator.StoreLocator.prototype.toggleSingleView = function(flag, location, scrollFlag) {
var _this = this;
if (flag) {
$(_this.divViews).css({
transform: "translate(-100%, 0)",
webkitTransform: "translate(-100%, 0)"
});
location.currentLocation = _this.searchField.val();
var newSingleLocationViewElement = _this.templates.singleLocationView(location);
_this.divSingleViewContainer.innerHTML = newSingleLocationViewElement;
if (_this.isSmallWidth) {
_this.rememberScrollPosition = document.body.scrollTop;
$(_this.divViews).css({
height: _this.divSingleViewContainer.offsetHeight + 50
});
$("html, body").animate({
scrollTop: $(".storelocator__map").offset().top
}, {
duration: 500
})
}
}else{
$(_this.divViews).css({
transform: "translate(0, 0)",
webkitTransform: "translate(0, 0)"
});
if (_this.isSmallWidth) {
$(_this.divViews).css({
height: _this.divResultsList.offsetHeight ? _this.divResultsList.offsetHeight + 35 : 400
});
if (scrollFlag) {
$("html, body").animate({
scrollTop: _this.rememberScrollPosition
}, {
duration: 1000
});
}
}
}
}
mcdStoreLocator.StoreLocator.prototype.populateLocationList = function(data) {
var _this = this;
_this.divResultsList.innerHTML = "";
for (var i = 0; i < data.length; i++) {
var location = data[i];
_this.addListItem(location);
}
if (data.length < 1) {
this.divNoResults.show();
}else{
this.divNoResults.hide();
}
if (_this.isSmallWidth) {
$(_this.divViews).css({
height: _this.divResultsList.offsetHeight ? _this.divResultsList.offsetHeight + 35 : 400
});
}
}
mcdStoreLocator.StoreLocator.prototype.resetFilters = function() {
this.filterButtons.find(".storelocator__filtericon").toggleClass("active", false);
this.currentFilters = [];
this.applyFilters(this.currentFilters);
}
mcdStoreLocator.StoreLocator.prototype.toggleFilter = function(filter, flag) {
var filterIndex = this.currentFilters.indexOf(filter);
if (flag) {
if (filterIndex == -1) this.currentFilters.push(filter);
}else{
if (filterIndex !== -1) this.currentFilters.splice(filterIndex, 1);
}
if (this.currentFilters.length > 0) {
this.iconResetFilters.toggleClass("active", true);
}else{
this.iconResetFilters.toggleClass("active", false);
}
}
mcdStoreLocator.StoreLocator.prototype.applyFilters = function(filters) {
if (this.isLoading) return false;
var filtered = this.getFilteredLocationsFromCurrentLocationData(filters);
this.toggleSingleView(false);
this.clearMarkers();
this.populateLocationList(filtered);
}
mcdStoreLocator.StoreLocator.prototype.getFilteredLocationsFromCurrentLocationData = function(filters) {
_this = this;
var filteredData = [];
function applyFiltersForLocation(location, filters) {
for (var i = 0; i < filters.length; i++) {
var feature = filters[i];
if (location.features.indexOf(feature) == -1) return false;
}
return true;
}
for (var i = 0; i < _this.locationData.length; i++) {
var location = _this.locationData[i];
if (applyFiltersForLocation(location, filters)) filteredData.push(location);
}
return filteredData;
}
mcdStoreLocator.StoreLocator.prototype.calculateOpenStatus = function(openTimes, forceCurrentString) {
var now = new Date();
var currentWeekday = (now.getDay() == 0 ? 6 : now.getDay() - 1); // transformed so 0 is monday
var previousWeekday = currentWeekday == 0 ? 6 : currentWeekday - 1; // previous weekday, if monday then sunday
var currentTimeString = forceCurrentString || (now.getHours().toString().length < 2 ? "0" + now.getHours() : now.getHours()) + ":" + (now.getMinutes().toString().length < 2 ? "0" + now.getMinutes() : now.getMinutes());
var yesterdayOpeningHours = openTimes[previousWeekday];
var todayOpeningHours = openTimes[currentWeekday];
// Check if is still open from last day
if (todayOpeningHours.open > yesterdayOpeningHours.close && yesterdayOpeningHours.close > currentTimeString) {
return {
activeDay: previousWeekday,
isOpen: true
}
}
// Check if open today
var todayCloseHour = todayOpeningHours.close;
if (todayCloseHour < todayOpeningHours.open) {
var closeArray = todayCloseHour.split(":");
todayCloseHour = (24 + closeArray[0]) + ":" + (closeArray[1].toString().length < 2 ? "0" + closeArray[1] : closeArray[1]);
}
if (todayOpeningHours.open <= currentTimeString && todayCloseHour >= currentTimeString) {
return {
activeDay: currentWeekday,
isOpen: true
}
}
return {
activeDay: currentWeekday,
isOpen: false
}
}
mcdStoreLocator.StoreLocator.prototype.searchForLocation = function(locationInput, callback) {
var _this = this;
function gotLocation(data, status) {
if (status == google.maps.GeocoderStatus.OK) {
_this.setCenterAndZoom(new google.maps.LatLng(data[0].geometry.location.lat(), data[0].geometry.location.lng()), 12);
_this.searchField.val(data[0].formatted_address);
callback(data);
}
}
if (typeof locationInput == "string") {
this.geocoder.geocode({
address: locationInput,
country: "NL",
region: "NL"
}, gotLocation);
}else{
this.geocoder.geocode({
latLng: locationInput,
country: "NL",
region: "NL"
}, gotLocation);
}
}
mcdStoreLocator.StoreLocator.prototype.setCenterAndZoom = function(center, zoom) {
this.map.setCenter(center);
if (zoom != undefined) this.map.setZoom(zoom);
var ww = window.innerWidth;
if (ww > 768){
this.map.panBy(-180, 0);
}
}
mcdStoreLocator.StoreLocator.prototype.addListItem = function(location) {
var _this = this;
var locationElement = $(this.templates.locationListItem(location).trim());
var locationMarker = new google.maps.Marker({
position: new google.maps.LatLng(location.lat, location.lon),
map: _this.map,
icon: _this.mapMarkerIcons.location
//animation: google.maps.Animation.DROP
});
google.maps.event.addListener(locationMarker, "click", function() {
_this.toggleSingleView(true, location);
_this.setCenterAndZoom(new google.maps.LatLng(location.lat, location.lon), 15);
});
_this.activeMarkers.push(locationMarker);
locationElement.bind("click", function(event) {
_this.toggleSingleView(true, location);
_this.setCenterAndZoom(new google.maps.LatLng(location.lat, location.lon), 15);
});
_this.divResultsList.appendChild(locationElement[0]);
}
window.addEventListener("load", function() {
mcdStoreLocator.main = new mcdStoreLocator.StoreLocator();
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment