/** * * 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.loadHome = function() { History.pushState({}, 'Crunchbutton', '/'); // App.page.restaurant('alpha-delta-pizza'); }; 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.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
Add $' + parseFloat(App.restaurant.delivery_min - App.cart.total()).toFixed(2) + ' from menu to meet delivery minimum.
' + '
' + '
' + '
' ); var categories = App.restaurant.categories(), dishes, list; var id_dish = 1; var dish = $('
  • ' + App.restaurant.top().name + '($' + App.restaurant.top().price + ')
  • '); $('.restaurant-items').append('

    Add to your order

    ', dish); list = $(''); $('.restaurant-items').append('
    Add another
    ', list ); 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' && App.restaurant.delivery == '1') { dp.append('

    ' + (App.config.user.address ? App.config.user.address.replace("\n",'
    ') : 'no address provided') + '
    '); } else { dp.append('
    takeout
    '); } dp.append('
    Change delivery or payment details
    '); 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.permalink == 'gw' || App.community.permalink == 'providence') ? '
    Include ZIP code
    ' : ''; if (restaurant.delivery == '1') { var deliveryInfo = '' + '
    ' + 'delivery or takeout' + '
    '; } else { var deliveryInfo = ''; } $('.delivery-info-container').append( '
    ' + deliveryInfo + '
    ' + '' + '
    ' + '' + '
    ' + '' + '
    ' + 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' || restaurant.delivery != '1') { 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 (!App.config.user.id_user) { App.config.user.address = App.loc.enteredLoc; App.loc.enteredLoc = ''; } }; App.loc = { enteredLoc: null } App.page.order = function(id) { App.currentPage = '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 = 'You Just Ordered Awesome Food!'; } else { message = 'You Just Ordered Awesome Food!'; } $('.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

    '); $('.order-info').append('We\'ve saved your order for easy 1 click ordering next time!

    '); }); }); }; 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 (!path[path.length-1]) { delete path[path.length-1]; } 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 (!App.community) { App.cache('Community','yale', function() { App.community = this; App.loadPage(); }); 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.restaurant('alpha-delta-pizza'); 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[0] == 'Ordered') { $('img.conversion').remove(); var i = $('').appendTo($('body')); } 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('
    Customize
    '); } 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(App.restaurant.deliveryDiff()); } 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; } if (!totalItems) { $('.default-order-check').hide(); } else { $('.default-order-check').show(); } 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 = $('