/**
*
* Crunchbutton
*
* @author: Devin Smith (http://devin.la)
* @date: 2012-06-20
*
*/
var App = {
tagline: '',
service: '/api/',
logService: 'http://log.crunchbutton.com/api/',
server: '/',
imgServer: '/',
cached: {},
community: null,
config: null,
_init: false,
_pageInit: false,
_identified: false,
touchX: null,
touchY: null,
touchOffset: null,
localStorage: false,
isPhoneGap: document.location.protocol == 'file:',
useNativeAlert: false,
useNativeConfirm: true,
ajaxTimeout: 5000,
splashHidden: false,
parallax: {
bg: null,
x: 0,
y: 0,
enabled: true
},
restaurantsPaging: {
enabled: true,
desktop: 9,
mobile: 6
}
};
// enable localstorage on phonegap
App.localStorage = App.isPhoneGap;
App.setLoggedIn = function(loggedIn) {
if ($('.is-ui2').get(0) && !loggedIn && App.isPhoneGap) {
setTimeout(function(){
App.go('/splash');
},10);
}
};
App.NGinit = function() {
$('body').attr('ng-controller', 'AppController');
angular.bootstrap(document,['NGApp']);
if (App.config.env == 'live') {
$('.footer').addClass('footer-hide');
}
};
var NGApp = angular.module('NGApp', []);
NGApp.config(function($compileProvider){
$compileProvider.urlSanitizationWhitelist(/.*/);
});
// This config will intercept all the ajax requests and take care of the errors
NGApp.config(function ( $httpProvider) {
var interceptor = function ( $q, $injector ) {
function success( response ) {
return response;
}
function error( response ) {
var status = response.status;
// Is offline
if( !window.navigator.onLine ){
var showError = false;
var url = response.config.url;
if ( url ) {
// Check if the url was an api url
if( url.indexOf( App.service ) >= 0 ){
var api = url.split( App.service );
if( api.length > 0 ){
// Get the api endpoint
api = api[1];
var showErrorFor = [ 'order', 'restaurant', 'user' ];
for( var i = 0; i < showErrorFor.length; i++ ){
if( api.indexOf( showErrorFor[i] ) >= 0 ){
showError = true;
break;
}
}
}
}
} else {
showError = true;
}
if( showError && !$( '.connection-error' ).is( ':visible' ) ){
App.connectionError();
if (App.busy.isBusy()) {
App.busy.unBusy();
}
}
}
return $q.reject( response );
}
return function ( promise ) {
return promise.then( success, error );
}
};
$httpProvider.responseInterceptors.push(interceptor);
});
NGApp.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider, RestaurantsService) {
$routeProvider
.when('/location', {
action: 'location',
controller: 'LocationCtrl',
templateUrl: 'assets/view/location.html'
})
.when('/splash', {
action: 'splash',
controller: 'SplashCtrl',
templateUrl: 'assets/view/splash.html'
})
.when('/download', {
action: 'download',
templateUrl: 'assets/view/download.html'
})
.when('/food-delivery', {
action: 'restaurants',
controller: 'RestaurantsCtrl',
templateUrl: 'assets/view/restaurants.html'
})
.when('/food-delivery/:id', {
action: 'restaurant',
controller: 'RestaurantCtrl',
templateUrl: 'assets/view/restaurant.html'
})
.when('/legal', {
action: 'legal',
controller: 'LegalCtrl',
templateUrl: 'assets/view/legal.html'
})
.when('/help', {
action: 'help',
controller: 'HelpCtrl',
templateUrl: 'assets/view/help.html'
})
.when('/about', {
action: 'about',
controller: 'AboutCtrl',
templateUrl: 'assets/view/about.html'
})
.when('/jobs', {
action: 'jobs',
controller: 'JobsCtrl',
templateUrl: 'assets/view/jobs.html'
})
.when('/owners', {
action: 'owners',
controller: 'OwnersCtrl',
templateUrl: 'assets/view/owners.html'
})
.when('/orders', {
action: 'orders',
controller: 'OrdersCtrl',
templateUrl: 'assets/view/orders.html'
})
.when('/order/:id', {
action: 'order',
controller: 'OrderCtrl',
templateUrl: 'assets/view/order.html'
})
.when('/cities', {
action: 'cities',
controller: 'CitiesCtrl',
templateUrl: 'assets/view/cities.html'
})
.when('/giftcard', {
action: 'giftcard',
controller: 'GiftcardCtrl',
templateUrl: 'assets/view/home.html'
})
.when('/giftcard/:id', {
action: 'giftcard',
controller: 'GiftcardCtrl',
templateUrl: 'assets/view/home.html'
})
.when('/gift', {
action: 'giftcard',
controller: 'GiftcardCtrl',
templateUrl: 'assets/view/home.html'
})
.when('/gift/:id', {
action: 'giftcard',
controller: 'GiftcardCtrl',
templateUrl: 'assets/view/home.html'
})
.when('/reset', {
action: 'reset',
controller: 'AccountResetCtrl',
templateUrl: 'assets/view/home.html'
})
.when('/reset/:id', {
action: 'reset',
controller: 'AccountResetCtrl',
templateUrl: 'assets/view/home.html'
})
.when('/invite/:id', {
action: 'invite',
controller: 'InviteCtrl',
templateUrl: 'assets/view/home.html'
})
.when('/', {
action: 'home',
controller: 'HomeCtrl',
templateUrl: 'assets/view/home.html'
})
.otherwise({
action: 'home',
controller: 'DefaultCtrl',
templateUrl: 'assets/view/home.html'
})
;
// only use html5 enabled location stuff if its not in a phonegap container
$locationProvider.html5Mode(!App.isPhoneGap);
}]);
// global route change items
NGApp.controller('AppController', function ($scope, $route, $routeParams, $rootScope, $location, $window, AccountService, MainNavigationService, AccountSignOut, CartService, ReferralService) {
// define external pointers
App.rootScope = $rootScope;
App.location = $location;
// define global services
$rootScope.account = AccountService;
$rootScope.navigation = MainNavigationService;
$rootScope.signout = AccountSignOut;
$rootScope.test = App.test;
$rootScope.cartScroll = function(permalink) {
//$('.snap-content-inner').scrollTop() + $('.cart-items').offset().top
var top = 183 - $('.navs').height() - 10;
var scroll = function() {
$('html, body, .snap-content-inner').animate({
scrollTop: top
}, 100, $.easing.easeInOutQuart ? 'easeInOutQuart' : null);
};
if ($rootScope.navigation.page != 'restaurant') {
$rootScope.scrollTop = top;
App.go('/food-delivery/' + permalink);
} else {
scroll();
}
};
$rootScope.scrollHalf = function(permalink) {
$('html, body, .snap-content-inner').animate({
scrollTop: 530 - $('.navs').height() - 10
}, 100, $.easing.easeInOutQuart ? 'easeInOutQuart' : null);
};
$rootScope.cancelDownload = function() {
$.totalStorage('_viewmobile', true);
App.go('/location');
};
$rootScope.$on('userAuth', function(e, data) {
$rootScope.$safeApply(function($scope) {
// @todo: remove double data
if (data) {
$rootScope.account.user = data;
App.config.user = data;
}
// If the user logged out clean the cart!
if( !App.config.user.id_user ){
CartService.clean();
}
// reload the actual controller
console.log('userAuth!');
if( !AccountService.forceDontReloadAfterAuth ){
$rootScope.reload();
}
AccountService.forceDontReloadAfterAuth = false;
});
});
$rootScope.focus = function( selector ){
setTimeout(function(){
angular.element( selector ).focus();
}, 100);
}
/* @info: this is how you watch an object rather than a property so i remeber
$rootScope.$watch('account.user', function() {
// indicates that the user object has changed
}, true);
*/
$rootScope.reload = function() {
$route.reload();
};
$rootScope.link = function(link) {
App.go.apply(arguments);
};
$rootScope.back = function() {
App.snap.close();
var backwards = false;
switch($route.current.action) {
case 'order':
backwards = '/orders';
break;
case 'restaurant':
backwards = '/food-delivery';
break;
case 'restaurants':
backwards = '/location';
break;
}
if (backwards) {
App.go(backwards);
} else {
history.back();
}
};
$rootScope.closePopup = function() {
try {
$.magnificPopup.close();
} catch (e) {}
};
$rootScope.$safeApply = function(fn) {
var phase = this.$root.$$phase;
if (phase == '$apply' || phase == '$digest') {
if (fn && (typeof(fn) === 'function')) {
this.$eval(fn);
}
} else {
this.$apply(fn);
}
};
// @todo: we might need this in the future for when we update to angular 1.2 with animations
/*
// determine if we are going backwards
$rootScope.$on('$locationChangeSuccess', function() {
$rootScope.actualLocation = $location.path();
});
$rootScope.$watch(function() {
return $location.path();
}, function (newLocation, oldLocation) {
if ($rootScope.actualLocation === newLocation) {
// this is backwards
}
});
*/
$scope.$on('$routeChangeSuccess', function ($currentRoute, $previousRoute) {
// Store the actual page
MainNavigationService.page = $route.current.action;
$('body').removeClass(function (index, css) {
return (css.match (/\bpage-\S+/g) || []).join(' ');
}).addClass('page-' + MainNavigationService.page);
$('.nav-top').addClass('at-top');
App.parallax.bg = null;
App.scrollTop($rootScope.scrollTop);
$rootScope.scrollTop = 0;
if (App.isPhoneGap && !App.splashHidden && navigator.splashscreen) {
App.splashHidden = true;
setTimeout(function() {
navigator.splashscreen.hide();
},1);
}
});
// Make the window's size available to all scope
$rootScope.windowWidth = $window.outerWidth;
$rootScope.windowHeight = $window.outerHeight;
// Window resize event
angular.element( $window ).bind( 'resize',function(){
$rootScope.windowWidth = $window.outerWidth;
$rootScope.windowHeight = $window.outerHeight;
$rootScope.$apply( 'windowWidth' );
$rootScope.$apply( 'windowHeight' );
});
AccountService.checkUser();
ReferralService.check();
});
App.alert = function( txt, title, useNativeAlert ) {
setTimeout(function() {
if (useNativeAlert && App.isPhoneGap) {
navigator.notification.alert(txt, null, title || 'Crunchbutton');
} else if ( useNativeAlert ) {
alert( txt );
} else {
App.rootScope.$broadcast('notificationAlert', title || 'Woops!', txt);
}
});
};
App.confirm = function(txt, title, fn, buttons) {
if (App.useNativeConfirm && App.isPhoneGap) {
return navigator.notification.confirm(txt, fn, title || 'Crunchbutton', buttons || 'Ok,Cancel' );
} else {
return confirm(txt);
}
};
App.connectionError = function() {
App.rootScope.$broadcast('notificationAlert', 'Connection Error', 'Sorry! We could not reach the server right now. Try again when your internet is back!');
};
App.go = function(url) {
// @todo: do some tests to figure out if we need this or not
// App.location.path(!App.isPhoneGap ? url : 'index.html#' + url);
App.location.path(url || '/');
App.rootScope.$safeApply();
};
App.toggleMenu = function() {
if (App.snap.state().state == 'left') {
App.snap.close();
} else {
App.snap.open('left');
}
};
/**
* scroll to the top of the page
*/
App.scrollTop = function(top) {
setTimeout(function() {
console.log(top);
$('html, body, .snap-content-inner').animate({scrollTop: top || 0}, 10, $.easing.easeInOutQuart ? 'easeInOutQuart' : null);
},3);
};
/**
* Sends a tracking item to google, or to google ads if its an order
*/
App.track = function() {
if (App.config.env != 'live') {
return;
}
if (arguments[0] == 'Ordered') {
$('img.conversion').remove();
var i = $('').appendTo($('body'));
}
};
/**
* controls the busy state of the app
* @sky-loader
*/
App.busy = {
_busy: false,
_timer: null,
_maxExec: 25000,
stage: function() {
$('#Stage').height('100%').width('100%');
return AdobeEdge.getComposition('EDGE-977700350').getStage();
},
isBusy: function() {
return $('.app-busy').length ? true : false;
return App.busy._busy;
},
makeBusy: function() {
if (App.busy._timer) {
clearTimeout(App.busy._timer);
}
App.busy._timer = setTimeout(function() {
App.alert('The app timed out processing your order. We can not determine if the order was placed or not. Please check your previous orders. Sorry!');
App.busy.unBusy();
}, App.busy._maxExec);
return $('body').append($('