/** * * Crunchbutton * * @author: Devin Smith (http://devin.la) * @date: 2012-06-20 * */ var App = { cartHighlightEnabled: false, currentPage: null, slogans: ['Order the best food %s with a click'], tagline: 'We\'ve chosen the best food from the best restaurants %s. We save your order, delivery and payment info, so reordering is as easy as the click of a button. Click on a restaurant below to get started.', service: '/api/', cached: {}, cart: {}, community: null, page: {}, config: null, forceHome: false, order: { cardChanged: false, pay_type: 'card', delivery_type: 'delivery', tip: '15' }, _init: false, _pageInit: false }; App.loadRestaurant = function(id) { App.cache('Restaurant',id,function() { if (!this.open()) { var hours = ''; for (var x in this._hours) { hours += x + ': '; for (var xx in this._hours[x]) { hours += this._hours[x][xx][0] + ' - ' + this._hours[x][xx][1] + (xx == 0 ? ', ' : ''); } hours += "\n"; } alert("This restaurant is currently closed. It will be open during the following hours:\n\n" + hours); App.busy.unBusy(); } else { var loc = '/' + App.community.permalink + '/' + this.permalink; History.pushState({}, 'Crunchbutton - ' + this.name, loc); } }); }; App.loadCommunity = function(id) { if (App.loadedPage == id) { App.community = App.cached['Community'][id]; App.loadedPage = null; /* return; */ } App.cache('Community',id, function() { App.community = this; if (!App.community.id_community) { App.cache('Community','yale', function() { App.community = this; App.loadPage(); }); $('.main-content').show(); $('.main-content').html('just a sec...'); return; } else { App.loadPage(); } }); }; App.loadHome = function() { App.currentPage = 'home'; History.pushState({}, 'Crunchbutton', '/'); App.loc.lat = 0; App.loc.lon = 0; if ($('.enter-location').length) { $('.location-address').val(''); $('.error-location').fadeOut(100, function() { $('.enter-location, .button-letseat-form').fadeIn(); }); } }; App.page.home = function() { document.title = 'Crunchbutton'; $('.nav-back').removeClass('nav-back-show'); $('.content').addClass('short-meal-list'); var top = ''; for (var x in App.topCommunities) { top += '
' + '
' + '
' + '
' + '

' + App.topCommunities[x].name + '

' + '

Top Restaurant: ' + App.topCommunities[x].restaurant + '

' + '
' + '
'; } $('.main-content').html('
' + '
' + '

Order the best food with a click

' + '

We\'ve chosen the best food from the best restaurants. We save your order, delivery and payment info, so reordering is as easy as the click of a button.

' + '
' + '
' + '

Order the best food with a tap

' + '

We\'ve chosen the best food from the best restaurants. We save your order, delivery and payment info, so reordering is as easy as a tap of a button.

' + '
' + '
' + '
' + '
' + '' + '' + '' + /* '' + */ '' + '
= 768 ? 'autofocus="autofocus"' : '') + '>' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '' + ''); //$('.location-address').val($.cookie('entered_address')); if (navigator.userAgent.toLowerCase().indexOf('safari') > -1 && navigator.userAgent.toLowerCase().indexOf('mobile') == -1 && navigator.userAgent.toLowerCase().indexOf('chrome') == -1) { // safari desktop $('.location-detect').css({ 'margin-top': '2px', 'height': '50px' }); } else if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) { // firefox desktop $('.location-detect').css({ 'margin-top': '0px', 'height': '52px' }); } }; App.page.community = function(id) { App.lastCommunity = id; App.currentPage = 'community'; App.cache('Community', id, function() { App.community = this; App.track('Community page loaded', {community: App.community.name}); document.title = App.community.name + ' Food Delivery | Order Food from ' + (App.community.name_alt ? App.community.name_alt : 'Local') + ' Restaurants | Crunchbutton'; var slogan = App.slogans[Math.floor(Math.random()*App.slogans.length)]; var sloganReplace = App.community.prep + ' ' + App.community.name; var tagline = App.tagline.replace('%s', sloganReplace); slogan = slogan.replace('%s', sloganReplace); $('.main-content').html( '

' + slogan + '

' + tagline + '

' + '
' ); var rs = this.restaurants(); if (rs.length == 4) { $('.content').addClass('short-meal-list'); } else { $('.content').removeClass('short-meal-list'); } $('.content').removeClass('smaller-width'); for (var x in rs) { var restaurant = $('
'); var restaurantContent = $('
'); restaurantContent .append('
') .append('

' + rs[x]['name'] + '

') .append('

Top Order: ' + (rs[x].top() ? (rs[x].top().top_name || rs[x].top().name) : '') + '

'); if (rs[x].open()) { if (rs[x].delivery != '1') { restaurantContent.append('
Take out only
'); } else if (!rs[x].delivery_fee) { // restaurantContent.append('
Free Delivery
'); } } else { restaurantContent.append('
Opens in a few hours
'); } restaurant .append('
') .append(restaurantContent); $('.meal-items').append(restaurant); } }); }; App.page.restaurant = function(id) { App.currentPage = 'restaurant'; App.cartHighlightEnabled = false; $('.content').addClass('smaller-width'); $('.content').removeClass('short-meal-list'); App.cache('Restaurant', id, function() { if (App.restaurant && App.restaurant.permalink != id) { App.cart.resetOrder(); } App.restaurant = this; App.track('Restaurant page loaded', {restaurant: App.restaurant.name}); document.title = App.restaurant.name + ' | ' + App.community.name + ' Food Delivery | Order from ' + (App.community.name_alt ? App.community.name_alt : 'Local') + ' Restaurants | Crunchbutton'; $('.main-content').html( '
' + '

' + App.restaurant.name + '

' + (App.restaurant.image ? '
' : '') + '
' + '
' + '
Your Order
Please add $' + parseFloat(App.restaurant.delivery_min - App.cart.total()).toFixed(2) + ' more to your order to meet the delivery minimum of $' + parseFloat(App.restaurant.delivery_min).toFixed(2) + '.
' + '
' + '
' + '
' ); var categories = App.restaurant.categories(), dishes, list; $('.restaurant-items').append('

Add to your order

') for (var x in categories) { dishes = categories[x].dishes(); list = $(''); $('.restaurant-items').append('
' + categories[x].name + (categories[x].loc == '1' ? (' at ' + App.community.name) : '') + '
', list ); for (var xx in dishes) { var dish = $('
  • ' + dishes[xx].name + '($' + dishes[xx].price + ')
  • '); list.append(dish); } } $('.cart-items').append('
    '); if (App.cart.hasItems()) { App.cart.reloadOrder(); } else if (App.config.user && App.config.user.presets && App.config.user.presets[App.restaurant.id_restaurant]) { try { App.cart.loadOrder(App.config.user.presets[App.restaurant.id_restaurant]); } catch (e) { App.cart.loadOrder(App.restaurant.preset()); } } else { App.cart.loadOrder(App.restaurant.preset()); } if (App.config.user.id_user) { App.drawPay(this); $('.payment-form').hide(); var dp = $('
    ') .append('
    ' + (App.config.user.phone ? App.phone.format(App.config.user.phone) : 'no phone # provied') + '
    '); var paying = $('
    $0.00
    '); if (App.config.user.pay_type == 'card') { paying.append(' incl tax and 15% tip, by card'); } else { paying.append(' incl tax using cash'); } dp.append(paying); if (App.config.user.delivery_type == 'delivery') { dp.append('

    ' + (App.config.user.address ? App.config.user.address.replace("\n",'
    ') : 'no address provided') + '
    '); } else { dp.append('
    takeout
    '); } dp.append('
    '); $('.main-content').append(dp); $('.delivery-tip-amount').html(App.order.tip ? App.order.tip + '%' : 'no'); } else { App.drawPay(this); } setTimeout(function() { var total = App.cart.updateTotal(); },200); App.cartHighlightEnabled = false; }); }; App.drawPay = function(restaurant) { var total = App.cart.total(); $('.main-content').append( '
    ' + '

    Your Info

    ' + '
    (enter this once, and we\'ll save it for next time)
    ' + '
    ' + '
    ' + '
    Your total is $' + total + ' (incl tax)
    ' + '
    ' + '
    ' ); var fieldError = App.community.id_community == 'gw' ? '
    Include ZIP code
    ' : ''; $('.delivery-info-container').append( '
    ' + '' + '
    ' + 'delivery or takeout' + '
    ' + '' + '
    ' + '' + '
    ' + '' + '
    ' + fieldError + '
    ' + '' + '
    ' + '
    ' ); $('.payment-info-container').append( '
    ' + '' + '
    ' + 'card or cash' + '
    ' + '

    Your credit card information is
    super secure and encrypted.

    ' + '
    ' + 'visa' + 'master card' + 'american express' + 'discover card' + '
    ' + '
    ' + '' + '
    ' + '' + '
    ' + '' + '
    ' + '
    ' + '
    ' + '
    ' + '' + '
    ' + '
    ' + '
    ' ); var tips = [0,5,10,15,20,25]; for (var x in tips) { $('[name="pay-tip"]').append(''); } for (var x=1; x<=12; x++) { $('[name="pay-card-month"]').append(''); } var date = new Date().getFullYear(); for (var x=date; x<=date+20; x++) { $('[name="pay-card-year"]').append(''); } if (App.order['pay_type'] == 'cash') { App.trigger.cash(); } else { App.trigger.credit(); } if (App.order['delivery_type'] == 'takeout') { App.trigger.takeout(); } else { App.trigger.delivery(); } $('[name="pay-tip"]').val(App.order.tip); $('[name="pay-name"]').val(App.config.user.name); $('[name="pay-phone"]').val(App.phone.format(App.config.user.phone)); $('[name="pay-address"]').val(App.config.user.address || App.loc.enteredLoc); $('[name="pay-card-number"]').val(App.config.user.card); $('[name="pay-card-month"]').val(App.config.user.card_exp_month); $('[name="pay-card-year"]').val(App.config.user.card_exp_year); if (App.config.user && App.config.user.presets && App.config.user.presets[App.restaurant.id_restaurant]) { try { console.log(App.config.user.presets[App.restaurant.id_restaurant]); $('[name="notes"]').val(App.config.user.presets[App.restaurant.id_restaurant].notes); } catch (e) {} } if (!restaurant.delivery) { $('.delivery-only-text').hide(); } if (!App.config.user.id_user) { App.config.user.address = App.loc.enteredLoc; App.loc.enteredLoc = ''; } }; App.page.order = function(id) { App.currentPage = 'order'; console.log('order'); App.cache('Order', id, function() { if (!this.uuid) { History.replaceState({},'Crunchbutton','/'); } document.title = 'Crunchbutton - Your Order'; App.order = this; var message, order = this; if (App.justCompleted) { App.justCompleted = false; message = 'Thanks, ' + this.name + '!'; } else { message = 'Your order'; } $('.content').addClass('smaller-width'); $('.main-content').css('width','auto'); $('.main-content').html( '
    ' + '
    ' ); $('.order-info').html( ''+ message +'' + '

    ' ); if (this.delivery_type == 'delivery') { $('.order-info').append('Your delivery address:
    ' + this.address + '

    '); } else { $('.order-info').append('Takeout order

    '); } $('.order-info').append('Your phone #:
    ' + this.phone + '

    '); $('.order-info').append('Your order:' + order._message + '

    '); if (order.notes) { $('.order-info').append('' + order.notes + '

    '); } if (this.pay_type == 'card') { $('.order-info').append('Your total:
    $' + parseFloat(this.final_price).toFixed(2) + '

    '); } else { $('.order-info').append('Your approximate total:
    $' + parseFloat(this.final_price).toFixed(2) + '

    '); } App.cache('Restaurant',order.id_restaurant, function() { $('.order-info').append('For updates on your order, please call
    ' + this.name + ': ' + this.phone + '

    '); $('.order-info').append('To reach Crunchbutton, send a text to (646) 783-1444
    or call (800) 242-1444

    '); }); }); }; App.page.legal = function() { App.currentPage = 'legal'; $.getJSON('/api/legal',function(json) { $('.main-content').html(json.data); App.refreshLayout(); }); }; App.page.help = function() { App.currentPage = 'help'; $.getJSON('/api/help',function(json) { $('.main-content').html(json.data); App.refreshLayout(); }); }; App.page.orders = function() { $.getJSON('/api/user/orders',function(json) { $('.main-content').html( '
    ' + '
    order history
    ' + '
      ' + '
      ' ); var count = 0, restaurants = {}; var orders = ''; for (var x in json) { restaurants[json[x].id_restaurant] = true; } var triggerComplete = function() { count++; var y = 0; for (var i in restaurants) { y++; } if (count != y) { return; } for (var x in json) { var date = json[x].date.replace(/^[0-9]+-([0-9]+)-([0-9]+) ([0-9]+:[0-9]+):[0-9]+$/i,'$1/$2 $3'); var order = '
    • ' + App.cached['Restaurant'][json[x].id_restaurant].name + '' + date + '
    • '; orders += order; } $('.resturant-dishes').append(orders); }; for (var x in restaurants) { App.cache('Restaurant',x,function() { triggerComplete(); }); } App.refreshLayout(); }); }; App.loadPage = function() { var url = History.getState().url.replace(/http(s)?:\/\/.*?\/(.*)/,'$2').replace('//','/'), path = url.split('/'); if (!App.config) { return; } // hide whatever we have if (App._pageInit) { $('.main-content').css('visibility','0'); } else { App._pageInit = true; } // force to a specific community if (!url) { App.loc.process(); return; } switch (true) { case /^legal/i.test(url): App.page.legal(); break; case /^help/i.test(url): App.page.help(); break; case /^orders/i.test(url): App.page.orders(); break; case /^order/i.test(url): App.page.order(); break; default: if (!App.community) { // force load of community reguardless of landing (this contains everything we need) App.loadCommunity(path[0]); return; } break; } if (App.community) { var communityRegex = new RegExp('^\/' + App.community.permalink + '$', 'i'); var restaurantRegex = new RegExp('^\/(restaurant)|(' + App.community.permalink + ')/', 'i'); } switch (true) { case /^order\//i.test(url): App.page.order(path[1]); break; case /^legal/i.test(url): App.page.legal(); break; case /^help/i.test(url): App.page.help(); break; case /^orders/i.test(url): App.page.orders(); break; case restaurantRegex.test(url): App.page.restaurant(path[1]); break; case communityRegex.test(url): default: $('.nav-back').removeClass('nav-back-show'); $('.footer').removeClass('footer-hide'); App.page.community(App.community.permalink); setTimeout(scrollTo, 80, 0, 1); return; break; } if (App.config.env == 'live') { $('.footer').addClass('footer-hide'); } $('.nav-back').addClass('nav-back-show'); App.refreshLayout(); $('.main-content').css('visibility','1'); setTimeout(scrollTo, 80, 0, 1); }; App.refreshLayout = function() { setTimeout(function() { scrollTo(0, 1); return; // a really stupid fix for ios and fixed position with fadein var el = $('.cart-summary'); if (el.length) { if (App.cartTimer) { clearTimeout(App.cartTimer); } else { var top = el.css('top'); el.css('position','relative'); el.css('top',0); } App.cartTimer = setTimeout(function() { el.css('top','43px'); el.css('position','fixed'); App.cartTimer = null; }, 1); } }, 80); }; App.track = function() { if (App.config.env != 'live') { return; } if (arguments[1]) { mixpanel.track(arguments[0],arguments[1]); } else { mixpanel.track(arguments[0]); } }; App.cart = { uuidInc: 0, items: {}, uuid: function() { var id = 'c-' + App.cart.uuidInc; App.cart.uuidInc++; return id; }, add: function(item) { var id = App.cart.uuid(), opt = App.cached['Dish'][item].options(), options = []; if (arguments[1]) { options = arguments[1].options; } else { for (var x in opt) { if (opt[x]['default'] == 1) { options[options.length] = opt[x].id_option; } } } App.cart.items[id] = { id: item, options: options }; var el = $('
      '); el.append('
      '); el.append('
      ' + App.cache('Dish',item).name + ' ' + (App.cache('Dish',item).description != null ? App.cache('Dish',item).description : '') + '
      '); if (App.cached['Dish'][item].options().length) { el.append(''); } el.hide(); $('.cart-items-content').append(el); //el.fadeIn(); el.show(); App.cart.updateTotal(); App.track('Dish added'); }, clone: function(item) { var cartid = item.attr('data-cart_id'), cart = App.cart.items[cartid], newoptions = []; for (var x in cart.options) { newoptions[newoptions.length] = cart.options[x]; } App.cart.add(cart.id, { options: newoptions }); App.track('Dish cloned'); }, remove: function(item) { var cart = item.attr('data-cart_id'); App.track('Dish removed'); delete App.cart.items[cart]; item.remove(); $('.cart-item-customize[data-id_cart_item="' + cart + '"]').remove(); App.cart.updateTotal(); }, updateTotal: function() { var totalText = '$' + App.cart.total(), tipText = '', feesText = '', totalItems = 0, hasFees = ((App.restaurant.delivery_fee && App.order.delivery_type == 'delivery') || App.restaurant.fee_customer) ? true : false; for (var x in App.cart.items) { totalItems++; } if (App.restaurant.meetDeliveryMin() && App.order.delivery_type == 'delivery') { $('.delivery-minimum-error').show(); $('.delivery-min-diff').html(parseFloat(App.restaurant.delivery_min - App.cart.total()).toFixed(2)); } else { $('.delivery-minimum-error').hide(); } $('.cart-summary-item-count span').html(totalItems); $('.cart-total').html(totalText); if (App.order['pay_type'] == 'card') { tipText = hasFees ? ', tip and fees' : ' and tip'; feesText = hasFees ? ', fees' : ''; $('.cash-order-aprox').html(''); } else { tipText = hasFees ? ' and fees' : ''; feesText = hasFees ? ' and fees' : ''; $('.cash-order-aprox').html('approximate'); } if (App.cartHighlightEnabled && $('.cart-summary').css('display') != 'none') { $('.cart-summary').removeClass('cart-summary-detail'); $('.cart-summary').effect('highlight', {}, 500, function() { $('.cart-summary').addClass('cart-summary-detail'); }); } $('.includes-tip').html(tipText); $('.includes-fees').html(feesText); if ($('.cart-total').html() == totalText) { //return; } var totalItems = {}, name, text = ''; $('.cart-summary-items').html(''); for (var x in App.cart.items) { name = App.cached['Dish'][App.cart.items[x].id].name; if (totalItems[name]) { totalItems[name]++; } else { totalItems[name] = 1; } } for (x in totalItems) { text += x; if (totalItems[x] > 1) { text += ' (' + totalItems[x] + ')'; } text += ',  '; } $('.cart-summary-items').html(text.substr(0,text.length-13)); $('.cart-item-customize-price').each(function() { var dish = $(this).closest('.cart-item-customize').attr('data-id_cart_item'), option = $(this).closest('.cart-item-customize-item').attr('data-id_option'), cartitem = App.cart.items[dish], opt = App.cached['Option'][option], price = opt.optionPrice(cartitem.options); $(this).html(App.cart.customizeItemPrice(price)); }); }, customizeItemPrice: function(price) { return price != '0.00' ? ' ($' + price + ')' : ''; }, customize: function(item) { var cart = item.attr('data-cart_id'), old = $('.cart-item-customize[data-id_cart_item="' + cart + '"]'); if (old.length) { old.remove(); } else { var el = $('
      ').insertAfter(item), cartitem = App.cart.items[cart], obj = App.cached['Dish'][cartitem.id], opt = obj.options(); for (var x in opt) { if (opt[x].id_option_parent) { continue; } if (opt[x].type == 'check') { var price = opt[x].optionPrice(cartitem.options); var check = $(''); if ($.inArray(opt[x].id_option, cartitem.options) !== -1) { check.attr('checked','checked'); } var option = $('
      ') .append(check) .append(''); el.append(option); } else if (opt[x].type == 'select') { var select = $('