Skip to content

Instantly share code, notes, and snippets.

@painteddigital
Created February 19, 2016 17:47
Show Gist options
  • Save painteddigital/9801cbcf75d7322c3bc4 to your computer and use it in GitHub Desktop.
Save painteddigital/9801cbcf75d7322c3bc4 to your computer and use it in GitHub Desktop.
/*
TODOS:
- Add listener for user changing DOM DTP
- Add local variable to store in
- QA DTP logic
- Test sort options for sending to search
- Add Optimizely logging when JSON loads fail
*/
var link = document.createElement("link");
link.href = "https://dl.dropboxusercontent.com/u/4902148/Sites/opentable/assets/styles/explore-tab.css";
link.type = "text/css";
link.rel = "stylesheet";
document.getElementsByTagName("head")[0].appendChild(link);
// Add Lodash
// (function() {
// var url = ["cdnjs.cloudflare.com/ajax/libs/lodash.js/4.3.0/lodash.min.js"];
// for(var i=0; i < url.length; i++){
// var v = document.createElement('script'); v.type = 'text/javascript'; v.async = true;
// v.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + url[i];
// var s = document.head; s.parentNode.appendChild(v);
// }
// })();
// GLOBALS
window.OT.Navigation = [];
window.OT.Navigation.metro = "8";
window.OT.Navigation.region = "77";
window.OT.Navigation.currentLocation = null;
var searchRootURL = "";
var dinersChoiceRootURL = "";
var landmarkRootURL = "";
var debug = true;
var personalizer = false;
var maxItemsToShow = 8;
$(window).ready(function(){
var dropdown = '<div id="explore-menu" class="menu-target menu">'+
'<div class="menu-container ot-menu-content-wrapper">'+
'<div class="explore-group">'+
'<div class="explore-group-header">'+
'<span class="icon-utensils"></span>'+
'<h4>Search by cuisine</h4>'+
'<span>In <span class="explore-location"></span></span>'+
'</div>'+
'<ul id="cuisines" class="explore-menu-list"></ul>'+
'</div>'+
'<div class="explore-group">'+
'<div class="explore-group-header">'+
'<span class="icon-trophy"></span>'+
'<h4>Top restaurants</h4>'+
'<span>In <span class="explore-location"></span></span>'+
'</div>'+
'<ul id="top" class="explore-menu-list"></ul>'+
'</div>'+
'<div class="explore-group">'+
'<div class="explore-group-header">'+
'<span class="icon-landmark-large"></span>'+
'<h4>Restaurants near landmarks</h4>'+
'<span>Near <span class="explore-location"></span></span>'+
'</div>'+
'<ul id="landmarks" class="explore-menu-list"></ul>'+
'</div>'+
'</div>'+
'</div>';
$("#explore-menu-link").after(dropdown);
OT.Common.Menus.bindMenu("#explore-menu-link");
$("#explore-menu-label").on("click", "a#explore-menu-link", function(){
window.trackOptimizelyEvent("header_exploremenulink_click");
});
// doesn't work right now
if(debug){
window.addEventListener("click", function(e) {
var href = e.target.getAttribute("href");
if(!href)
href = e.target.parentElement.getAttribute("href");
if(href) {
location.href = href + "&exploreTab=1";
e.preventDefault();
}
});
}
$.ajax({
dataType: "json",
url: "https://dl.dropboxusercontent.com/u/4902148/Sites/opentable/assets/js/explore-data-map.json",
context: document.body
}).done(function(data) {
// debugLog("loaded external js");
// debugLog(data);
// INIT GLOBALS
initCurrentLocation(data['locations']);
searchRootURL = data['links'][0].search;
dinersChoiceRootURL = data['links'][0].dinerschoice;
landmarkRootURL = data['links'][0].landmarks;
// successfully retrieved location, init UI
if(getCurrentLocation()){
updateCurrentLocationLabels();
if(personalizer){
getCuisines(data['cuisines']);
} else {
appendCuisines(data['cuisines']);
}
appendDinersChoice(data['dinersChoicePages']);
getPOI(data['landmarks']);
}
})
});
/*
CONTROLLER FUNCTIONS
*/
function getCuisines(failsafeData){
var cuisineCount = 18;
$.ajax({
dataType: "json",
url: "https://dl.dropboxusercontent.com/u/4902148/sites/opentable/assets/js/nyc-cuisines.json",
context: document.body,
}).done(function(data) {
var topCuisines = [];
var region = getRegion();
if(region == ""){
// Sort by `user` in ascending order and by `age` in descending order.
// removes the regional distinction
var reducedData = _.reduceRight(data, function(flattened, other) {
return flattened.concat(other);
}, []);
// order by restaurant count
var orderedCuisines = _.sortBy(reducedData, function(obj){ return -obj.count; });
// grab the first [n] in the list
topCuisines = orderedCuisines.slice(0, cuisineCount);
// _.each(topCuisines, function(cuisine) {
// debugLog(cuisine.name, cuisine.count);
// });
} else {
topCuisines = data[region].slice(0, cuisineCount);
// _.each(topCuisines, function(cuisine) {
// debugLog(cuisine.cuisine_name, cuisine.cuisine_count);
// });
}
convertCuisineFormatting(topCuisines);
}).fail(function(jqXHR, textStatus, errorThrown){
debugLog("error getting cuisine JSON, loading static cuisines");
appendCuisines(failsafeData);
});
}
function getPOI(failsafeData){
var POICount = 18;
$.ajax({
dataType: "json",
url: "https://dl.dropboxusercontent.com/u/4902148/sites/opentable/assets/js/nyc-poi.json",
context: document.body,
}).done(function(data) {
window.OT.Navigation.poiData = data;
var region = getRegion();
var landmarks = [];
if(region == ""){
landmarks = data;
} else {
// Sort first by popularity, grabbing only the first 15 that match the region, then sort those Alphabetically
landmarks = _.filter(data, function(obj){
return obj.Macro == getRegion();
});
}
landmarks = _.sortBy(landmarks, function(obj){ return -obj.Popularity; }).slice(0, POICount);
landmarks = _.sortBy(landmarks, function(obj){ return obj.Name; });
convertPOIFormatting(landmarks);
}).fail(function(jqXHR, textStatus, errorThrown){
debugLog("error getting POI JSON, loading static POI");
appendLandmarks(failsafeData);
});
}
function convertCuisineFormatting(receivedData){
var reformattedList = []
var region = getRegion();
var currentLocation = getCurrentLocation();
_.each(receivedData, function(cuisine) {
var reformattedCuisine = {
"title":cuisine.name,
"restaurantCount":cuisine.count,
"regionId":region,
"urlParams":"personalizer=true&cuisineids="+cuisine.id,
"cuisineId":cuisine.id
}
reformattedList.push(reformattedCuisine);
});
currentLocation.cuisines = reformattedList;
appendCuisines();
}
function convertPOIFormatting(receivedData){
var reformattedList = []
var currentLocation = getCurrentLocation();
_.each(receivedData, function(point) {
var reformattedPoint = {
"title":point.Name,
"id":point.ID,
"regionId":point.Macro,
"metroId":point.Metro,
"popularity":point.Popularity
}
reformattedList.push(reformattedPoint);
});
currentLocation.landmarks = reformattedList;
appendLandmarks();
}
// GETTERS
function getDTP(){
// More OT-Friendly way: OT.Common.Cookies.get("OT_dtp_values")
// Example data = {covers: "2", datetime: "2016-02-11 19:00"}
var dtp = "";
var dtpCookieValues = OT.Common.Cookies.get("OT_dtp_values");
if(dtpCookieValues != "undefined"){
dtp = "&"+encodeURIComponent(document.cookie.split("OT_dtp_values=")[1].split(";")[0]);
}
var dtpDOMString = "";
// if DOM elements are present, override cookie since it can get out dated
if($("select[name=Select_1]").val() != "" && $("input#submit_datepicker").val() != "" && $("select[name=Select_0]").val() != ""){
dtp += "&covers="+$("select[name=Select_1]").val();
dtp += "&dateTime="+$("input#submit_datepicker").val();
dtp += encodeURIComponent(" "+$("select[name=Select_0]").val());
}
return dtp;
}
function getRegion(){
return window.OT.Navigation.region;
}
function getMetro(){
return window.OT.Navigation.metro;
}
function getCurrentLocation(){
return window.OT.Navigation.currentLocation;
}
// SETTERS
function setRegion(newRegion){
window.OT.Navigation.region = newRegion;
}
function setMetro(newMetro){
window.OT.Navigation.metro = newMetro;
}
function setCurrentLocation(newLocationObject){
window.OT.Navigation.currentLocation = newLocationObject;
}
function initCurrentLocation(allLocationData){
// Save location data locally
window.OT.Navigation.locationData = allLocationData;
// Attempt to get location from Cookie
var split = document.cookie.split("lvCKE=lvmreg=")[1]
var ids = split.split("%2C");
setMetro(ids[0]);
setRegion(ids[1].split("&")[0]);
//debugLog(getMetro(),getRegion());
// First attempt to match to cookie instead of UI for stability
// if cookie returns "0" region, set to nothing to match url param expectations
if(getRegion() == "0"){ setRegion(""); }
// get JSON for current metro/region
setCurrentLocation(_.find(allLocationData, function(obj){
return obj.searchParams[0].metroId == getMetro() && obj.searchParams[0].regionId == getRegion();
}));
// Check that cookie data matches location header string
// If that fails, then fallback to setting location based on
if($(".location-picker-region").text().indexOf(getCurrentLocation().title) > -1){
debugLog("cookie location matches UI");
} else {
debugLog("cookie location doesn't match UI");
var locationMatch = _.find(allLocationData, function(obj){
return obj.title == $(".location-picker-region").text();
});
if(typeof locationMatch != "undefined"){
setCurrentLocation(locationMatch);
} else {
debugLog("cant find a region from UI, using NYC metro data");
setCurrentLocation(_.find(allLocationData, function(obj){
return obj.title == "New York / Tri-State Area";
}));
}
}
}
/*
VIEW FUNCTIONS
*/
function updateCurrentLocationLabels(){
$("#location").text(getCurrentLocation().title);
$(".explore-location").text(getCurrentLocation().title);
}
function appendCuisines(cuisines){
var currentLocation = getCurrentLocation();
if(typeof currentLocation.cuisines != "undefined"){
debugLog("loading retrieved cuisine JSON");
_.each(currentLocation.cuisines, function(cuisineObject, key){
appendCuisineDOMElem(cuisineObject);
});
} else {
_.each(currentLocation.cuisineIds, function(cuisineId, key){
debugLog("proceeding with error-safe cuisines");
var cuisineObject = _.find(cuisines, function(obj){
return obj['id'] == cuisineId;
});
appendCuisineDOMElem(cuisineObject)
});
}
}
function appendCuisineDOMElem(cuisineObject){
var dtpParams = getDTP();
var currentLocation = getCurrentLocation();
$("#cuisines").append("<li><a href=\""+searchRootURL+"&metroId="+currentLocation.searchParams[0].metroId+"&regionIds="+currentLocation.searchParams[0].regionId+dtpParams+"&"+cuisineObject.urlParams+"\">"+cuisineObject.title+"</a></li>");
$("#cuisines").on("click", "a", function(){
window.trackOptimizelyEvent("header_cuisine_click");
});
hideLongColumns($("#cuisines"));
}
function appendDinersChoice(dinersChoicePages){
var currentLocation = getCurrentLocation();
_.each(currentLocation.dinersChoiceIds, function(dinersChoiceId, key){
var dinersChoiceObject = _.find(dinersChoicePages, function(obj){
return obj['id'] == dinersChoiceId;
});
var urlParams = (currentLocation.dinersChoiceParams.indexOf("?") > -1) ? "&"+dinersChoiceObject.urlParams : "?"+dinersChoiceObject.urlParams
$("#top").append("<li><a href=\""+dinersChoiceRootURL+currentLocation.dinersChoiceParams+urlParams+"\">"+dinersChoiceObject.title+"</a></li>");
});
$("#top").on("click", "a", function(){
window.trackOptimizelyEvent("header_dinerschoice_click");
});
hideLongColumns($("#top"));
}
function appendLandmarks(failsafeLandmarks){
var currentLocation = getCurrentLocation();
// if we didn't pass in failsafe data, then we got real JSON.
// this check expacts that JSON to be found under currentlocation.landmarks
if(typeof currentLocation.landmarks != "undefined"){
debugLog("loading retrieved POI JSON", currentLocation.landmarks);
_.each(currentLocation.landmarks, function(landmarkObject, key){
$("#landmarks").append("<li><a href=\""+landmarkRootURL+landmarkObject.id+"\">"+landmarkObject.title+"</a></li>");
});
} else {
debugLog("loading failsafe POIs");
_.each(currentLocation.landmarkIds, function(landmarkId, key){
var landmarkObject = _.find(failsafeLandmarks, function(obj){
return obj['id'] == landmarkId;
});
$("#landmarks").append("<li><a href=\""+landmarkRootURL+landmarkObject.urlParams+"\">"+landmarkObject.title+"</a></li>");
});
}
$("#landmarks").on("click", "a", function(){
window.trackOptimizelyEvent("header_landmark_click");
});
hideLongColumns($("#landmarks"));
}
function hideLongColumns($listElement){
var singleItemHeight = $listElement.children("li").height();
if($listElement.height() > singleItemHeight*maxItemsToShow && $listElement.children().length > maxItemsToShow){
$listElement.addClass("short");
$listElement.parent().append("<a href=\"#\" class=\"view-more secondary with-arrow text-arrow-down-small\">Show More</a>");
$listElement.parent().on("click", ".view-more", showLongColumn);
}
}
function showLongColumn(e){
$(this).siblings(".explore-menu-list").toggleClass("short long", 400, "easeOutQuint");
// debugLog($(e.currentTarget).parent());
var text = $(this).text();
$(this).toggleClass("text-arrow-down-small text-arrow-up-small").text(text == "Show More" ? "Show Fewer" : "Show More");
window.trackOptimizelyEvent("header_showmore_click");
e.stopPropagation();
return false;
}
/*
UTILITIES
*/
function debugLog(a,b,c){
if(debug){
if(typeof c != "undefined"){
console.log(a, b, c);
} else if(typeof b != "undefined"){
console.log(a, b);
} else {
console.log(a)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment