/******/
 (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId])
/******/ 			return installedModules[moduleId].exports;
/******/
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			exports: {},
/******/ 			id: moduleId,
/******/ 			loaded: false
/******/ 		};
/******/
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ 		// Flag the module as loaded
/******/ 		module.loaded = true;
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/
/******/
/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;
/******/
/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;
/******/
/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";
/******/
/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	__webpack_require__(1);
	
	var _generosityBankCountryDirective = __webpack_require__(2);
	
	var _generosityBankCountryDirective2 = _interopRequireDefault(_generosityBankCountryDirective);
	
	var _generosityBeneficiaryNameDirective = __webpack_require__(4);
	
	var _generosityBeneficiaryNameDirective2 = _interopRequireDefault(_generosityBeneficiaryNameDirective);
	
	var _generosityNonprofitNameDirective = __webpack_require__(6);
	
	var _generosityNonprofitNameDirective2 = _interopRequireDefault(_generosityNonprofitNameDirective);
	
	var _generosityStripeBankFormDirective = __webpack_require__(8);
	
	var _generosityStripeBankFormDirective2 = _interopRequireDefault(_generosityStripeBankFormDirective);
	
	var _generosityStripeCountryDirective = __webpack_require__(11);
	
	var _generosityStripeCountryDirective2 = _interopRequireDefault(_generosityStripeCountryDirective);
	
	var _lifeFundsBankInfoDirective = __webpack_require__(13);
	
	var _lifeFundsBankInfoDirective2 = _interopRequireDefault(_lifeFundsBankInfoDirective);
	
	var _lifeFundsBreakdownDirective = __webpack_require__(15);
	
	var _lifeFundsBreakdownDirective2 = _interopRequireDefault(_lifeFundsBreakdownDirective);
	
	var _lifeFundsDirective = __webpack_require__(18);
	
	var _lifeFundsDirective2 = _interopRequireDefault(_lifeFundsDirective);
	
	var _lifeFundsUnderReviewDirective = __webpack_require__(20);
	
	var _lifeFundsUnderReviewDirective2 = _interopRequireDefault(_lifeFundsUnderReviewDirective);
	
	var _lifeReceiveFundsDirective = __webpack_require__(22);
	
	var _lifeReceiveFundsDirective2 = _interopRequireDefault(_lifeReceiveFundsDirective);
	
	var _pcAutomatedFacebookUpdatesDirective = __webpack_require__(24);
	
	var _pcAutomatedFacebookUpdatesDirective2 = _interopRequireDefault(_pcAutomatedFacebookUpdatesDirective);
	
	var _pcDashboardCampaignCardDirective = __webpack_require__(27);
	
	var _pcDashboardCampaignCardDirective2 = _interopRequireDefault(_pcDashboardCampaignCardDirective);
	
	var _pcDashboardDirective = __webpack_require__(29);
	
	var _pcDashboardDirective2 = _interopRequireDefault(_pcDashboardDirective);
	
	var _pcDashboardDonationsDirective = __webpack_require__(31);
	
	var _pcDashboardDonationsDirective2 = _interopRequireDefault(_pcDashboardDonationsDirective);
	
	var _pcDashboardEndFundraiserDirective = __webpack_require__(33);
	
	var _pcDashboardEndFundraiserDirective2 = _interopRequireDefault(_pcDashboardEndFundraiserDirective);
	
	var _pcDashboardFundraiserLinkDirective = __webpack_require__(37);
	
	var _pcDashboardFundraiserLinkDirective2 = _interopRequireDefault(_pcDashboardFundraiserLinkDirective);
	
	var _pcDashboardMobileFundraiserLinkDirective = __webpack_require__(39);
	
	var _pcDashboardMobileFundraiserLinkDirective2 = _interopRequireDefault(_pcDashboardMobileFundraiserLinkDirective);
	
	var _pcDashboardPostUpdateDirective = __webpack_require__(42);
	
	var _pcDashboardPostUpdateDirective2 = _interopRequireDefault(_pcDashboardPostUpdateDirective);
	
	var _pcDashboardService = __webpack_require__(44);
	
	var _pcDashboardService2 = _interopRequireDefault(_pcDashboardService);
	
	var _pcManagementBarDirective = __webpack_require__(45);
	
	var _pcManagementBarDirective2 = _interopRequireDefault(_pcManagementBarDirective);
	
	var _pcRecentDonationsDirective = __webpack_require__(46);
	
	var _pcRecentDonationsDirective2 = _interopRequireDefault(_pcRecentDonationsDirective);
	
	var _pcTodoItemsDirective = __webpack_require__(48);
	
	var _pcTodoItemsDirective2 = _interopRequireDefault(_pcTodoItemsDirective);
	
	var _pcVisitStatsDirective = __webpack_require__(51);
	
	var _pcVisitStatsDirective2 = _interopRequireDefault(_pcVisitStatsDirective);
	
	var _percentChangeFilter = __webpack_require__(53);
	
	var _percentChangeFilter2 = _interopRequireDefault(_percentChangeFilter);
	
	var _todoItemStatusIconDirective = __webpack_require__(54);
	
	var _todoItemStatusIconDirective2 = _interopRequireDefault(_todoItemStatusIconDirective);
	
	var _weekOfFilter = __webpack_require__(56);
	
	var _weekOfFilter2 = _interopRequireDefault(_weekOfFilter);
	
	var _campaignCommentsService = __webpack_require__(57);
	
	var _campaignCommentsService2 = _interopRequireDefault(_campaignCommentsService);
	
	var _campaignUpdatesService = __webpack_require__(58);
	
	var _campaignUpdatesService2 = _interopRequireDefault(_campaignUpdatesService);
	
	var _campaignHeaderRecommendationsDirective = __webpack_require__(59);
	
	var _campaignHeaderRecommendationsDirective2 = _interopRequireDefault(_campaignHeaderRecommendationsDirective);
	
	var _campaignHeaderRecommendationsService = __webpack_require__(61);
	
	var _campaignHeaderRecommendationsService2 = _interopRequireDefault(_campaignHeaderRecommendationsService);
	
	var _pusherWrapperService = __webpack_require__(62);
	
	var _pusherWrapperService2 = _interopRequireDefault(_pusherWrapperService);
	
	var _campaignPusherService = __webpack_require__(65);
	
	var _campaignPusherService2 = _interopRequireDefault(_campaignPusherService);
	
	var _campaignShareModalDirective = __webpack_require__(66);
	
	var _campaignShareModalDirective2 = _interopRequireDefault(_campaignShareModalDirective);
	
	var _contributeButtonGaTrackingDirective = __webpack_require__(68);
	
	var _contributeButtonGaTrackingDirective2 = _interopRequireDefault(_contributeButtonGaTrackingDirective);
	
	var _desktopApprovalButtonDirective = __webpack_require__(69);
	
	var _desktopApprovalButtonDirective2 = _interopRequireDefault(_desktopApprovalButtonDirective);
	
	var _desktopCampaignPageDirective = __webpack_require__(71);
	
	var _desktopCampaignPageDirective2 = _interopRequireDefault(_desktopCampaignPageDirective);
	
	var _desktopCommentDirective = __webpack_require__(72);
	
	var _desktopCommentDirective2 = _interopRequireDefault(_desktopCommentDirective);
	
	var _desktopCommentsDirective = __webpack_require__(75);
	
	var _desktopCommentsDirective2 = _interopRequireDefault(_desktopCommentsDirective);
	
	var _desktopCommentContributionDetailsDirective = __webpack_require__(77);
	
	var _desktopCommentContributionDetailsDirective2 = _interopRequireDefault(_desktopCommentContributionDetailsDirective);
	
	var _desktopFacebookShareDirective = __webpack_require__(79);
	
	var _desktopFacebookShareDirective2 = _interopRequireDefault(_desktopFacebookShareDirective);
	
	var _desktopFundersDirective = __webpack_require__(81);
	
	var _desktopFundersDirective2 = _interopRequireDefault(_desktopFundersDirective);
	
	var _desktopGalleryDirective = __webpack_require__(83);
	
	var _desktopGalleryDirective2 = _interopRequireDefault(_desktopGalleryDirective);
	
	var _desktopNavBarDirective = __webpack_require__(85);
	
	var _desktopNavBarDirective2 = _interopRequireDefault(_desktopNavBarDirective);
	
	var _desktopProjectFunderCountDirective = __webpack_require__(87);
	
	var _desktopProjectFunderCountDirective2 = _interopRequireDefault(_desktopProjectFunderCountDirective);
	
	var _desktopUpdatesDirective = __webpack_require__(88);
	
	var _desktopUpdatesDirective2 = _interopRequireDefault(_desktopUpdatesDirective);
	
	var _desktopUpdatePreviewDirective = __webpack_require__(90);
	
	var _desktopUpdatePreviewDirective2 = _interopRequireDefault(_desktopUpdatePreviewDirective);
	
	var _earlyContributeDirective = __webpack_require__(93);
	
	var _earlyContributeDirective2 = _interopRequireDefault(_earlyContributeDirective);
	
	var _storyTabCacheProvider = __webpack_require__(95);
	
	var _storyTabCacheProvider2 = _interopRequireDefault(_storyTabCacheProvider);
	
	var _addYourDonationDirective = __webpack_require__(96);
	
	var _addYourDonationDirective2 = _interopRequireDefault(_addYourDonationDirective);
	
	var _generosityDonationsDirective = __webpack_require__(98);
	
	var _generosityDonationsDirective2 = _interopRequireDefault(_generosityDonationsDirective);
	
	var _generosityFundraiserMainDirective = __webpack_require__(100);
	
	var _generosityFundraiserMainDirective2 = _interopRequireDefault(_generosityFundraiserMainDirective);
	
	var _generosityFundraiserService = __webpack_require__(102);
	
	var _generosityFundraiserService2 = _interopRequireDefault(_generosityFundraiserService);
	
	var _generosityStoryTruncationService = __webpack_require__(103);
	
	var _generosityStoryTruncationService2 = _interopRequireDefault(_generosityStoryTruncationService);
	
	var _generosityPerksDirective = __webpack_require__(104);
	
	var _generosityPerksDirective2 = _interopRequireDefault(_generosityPerksDirective);
	
	var _generosityPostUpdateDirective = __webpack_require__(106);
	
	var _generosityPostUpdateDirective2 = _interopRequireDefault(_generosityPostUpdateDirective);
	
	var _generosityStoryDirective = __webpack_require__(108);
	
	var _generosityStoryDirective2 = _interopRequireDefault(_generosityStoryDirective);
	
	var _generosityUpdatesDirective = __webpack_require__(110);
	
	var _generosityUpdatesDirective2 = _interopRequireDefault(_generosityUpdatesDirective);
	
	var _generosityUpdatePreviewDirective = __webpack_require__(113);
	
	var _generosityUpdatePreviewDirective2 = _interopRequireDefault(_generosityUpdatePreviewDirective);
	
	var _campaignLoginDirective = __webpack_require__(116);
	
	var _campaignLoginDirective2 = _interopRequireDefault(_campaignLoginDirective);
	
	var _campaignMainDirective = __webpack_require__(118);
	
	var _campaignMainDirective2 = _interopRequireDefault(_campaignMainDirective);
	
	var _campaignStoryDirective = __webpack_require__(120);
	
	var _campaignStoryDirective2 = _interopRequireDefault(_campaignStoryDirective);
	
	var _collapsableDirective = __webpack_require__(122);
	
	var _collapsableDirective2 = _interopRequireDefault(_collapsableDirective);
	
	var _emailImporterDirective = __webpack_require__(124);
	
	var _emailImporterDirective2 = _interopRequireDefault(_emailImporterDirective);
	
	var _emailImporterService = __webpack_require__(127);
	
	var _emailImporterService2 = _interopRequireDefault(_emailImporterService);
	
	var _shareWizardDirective = __webpack_require__(128);
	
	var _shareWizardDirective2 = _interopRequireDefault(_shareWizardDirective);
	
	var _backToTopDirective = __webpack_require__(130);
	
	var _backToTopDirective2 = _interopRequireDefault(_backToTopDirective);
	
	var _campaignOwnerService = __webpack_require__(131);
	
	var _campaignOwnerService2 = _interopRequireDefault(_campaignOwnerService);
	
	var _fbAutopostService = __webpack_require__(132);
	
	var _fbAutopostService2 = _interopRequireDefault(_fbAutopostService);
	
	var _generosityFbShareDirective = __webpack_require__(133);
	
	var _generosityFbShareDirective2 = _interopRequireDefault(_generosityFbShareDirective);
	
	var _pcCampaignService = __webpack_require__(135);
	
	var _pcCampaignService2 = _interopRequireDefault(_pcCampaignService);
	
	var _pcContactDirective = __webpack_require__(136);
	
	var _pcContactDirective2 = _interopRequireDefault(_pcContactDirective);
	
	var _pcFbShareDirective = __webpack_require__(140);
	
	var _pcFbShareDirective2 = _interopRequireDefault(_pcFbShareDirective);
	
	var _publishButtonDirective = __webpack_require__(142);
	
	var _publishButtonDirective2 = _interopRequireDefault(_publishButtonDirective);
	
	var _todoItemsService = __webpack_require__(145);
	
	var _todoItemsService2 = _interopRequireDefault(_todoItemsService);
	
	var _generosityDashboardFundsDisbursementDirective = __webpack_require__(146);
	
	var _generosityDashboardFundsDisbursementDirective2 = _interopRequireDefault(_generosityDashboardFundsDisbursementDirective);
	
	var _generosityFundsDisbursementService = __webpack_require__(149);
	
	var _generosityFundsDisbursementService2 = _interopRequireDefault(_generosityFundsDisbursementService);
	
	var _camelCaserService = __webpack_require__(150);
	
	var _camelCaserService2 = _interopRequireDefault(_camelCaserService);
	
	var _refundDisplayFactory = __webpack_require__(151);
	
	var _refundDisplayFactory2 = _interopRequireDefault(_refundDisplayFactory);
	
	var _contributionsApiService = __webpack_require__(152);
	
	var _contributionsApiService2 = _interopRequireDefault(_contributionsApiService);
	
	var _orderStateDirective = __webpack_require__(153);
	
	var _orderStateDirective2 = _interopRequireDefault(_orderStateDirective);
	
	var _paymentMethodDirective = __webpack_require__(155);
	
	var _paymentMethodDirective2 = _interopRequireDefault(_paymentMethodDirective);
	
	var _lineItemsDirective = __webpack_require__(157);
	
	var _lineItemsDirective2 = _interopRequireDefault(_lineItemsDirective);
	
	var _discovery = __webpack_require__(159);
	
	var _discovery2 = _interopRequireDefault(_discovery);
	
	var _updatePreview = __webpack_require__(172);
	
	var _updatePreview2 = _interopRequireDefault(_updatePreview);
	
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
	
	__webpack_require__(175);
	
	/* for comment order details modal on desktop campaign page */
	
	(0, _discovery2.default)(angular);
	(0, _updatePreview2.default)(angular);
	
	angular.module('campaignPage.lifeDashboard', ['templates', 'header', 'footer', 'campaignPage.utils', 'campaignPage.share', 'bankInfo.main', 'ui.router', 'utils', 'bankInfo.payment', 'indiegogo.commandCenter.payoutRecords', 'LocalStorageModule', 'angularMoment', 'ngTouch']).factory('pcDashboard', _pcDashboardService2.default).factory('generosityFundsDisbursement', _generosityFundsDisbursementService2.default).factory('camelCaser', _camelCaserService2.default).filter('percentChange', _percentChangeFilter2.default).filter('weekOf', _weekOfFilter2.default).directive('generosityBankCountry', _generosityBankCountryDirective2.default).directive('generosityBeneficiaryName', _generosityBeneficiaryNameDirective2.default).directive('generosityNonprofitName', _generosityNonprofitNameDirective2.default).directive('generosityStripeBankForm', _generosityStripeBankFormDirective2.default).directive('generosityStripeCountry', _generosityStripeCountryDirective2.default).directive('lifeFundsBankInfo', _lifeFundsBankInfoDirective2.default).directive('lifeFundsBreakdown', _lifeFundsBreakdownDirective2.default).directive('lifeFunds', _lifeFundsDirective2.default).directive('lifeFundsUnderReview', _lifeFundsUnderReviewDirective2.default).directive('lifeReceiveFunds', _lifeReceiveFundsDirective2.default).directive('pcAutomatedFacebookUpdates', _pcAutomatedFacebookUpdatesDirective2.default).directive('pcDashboardCampaignCard', _pcDashboardCampaignCardDirective2.default).directive('pcDashboard', _pcDashboardDirective2.default).directive('pcDashboardDonations', _pcDashboardDonationsDirective2.default).directive('pcDashboardEndFundraiser', _pcDashboardEndFundraiserDirective2.default).directive('pcDashboardFundraiserLink', _pcDashboardFundraiserLinkDirective2.default).directive('pcDashboardMobileFundraiserLink', _pcDashboardMobileFundraiserLinkDirective2.default).directive('pcDashboardPostUpdate', _pcDashboardPostUpdateDirective2.default).directive('pcManagementBar', _pcManagementBarDirective2.default).directive('pcRecentDonations', _pcRecentDonationsDirective2.default).directive('pcTodoItems', _pcTodoItemsDirective2.default).directive('pcVisitStats', _pcVisitStatsDirective2.default).directive('generosityDashboardFundsDisbursement', _generosityDashboardFundsDisbursementDirective2.default).directive('todoItemStatusIcon', _todoItemStatusIconDirective2.default).config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
	  $urlRouterProvider.otherwise('/manage');
	
	  $stateProvider.state('manage', {
	    url: '/manage',
	    template: __webpack_require__(176)
	  });
	
	  $stateProvider.state('funds', {
	    url: '/funds',
	    template: '<div ui-view></div>',
	    redirectTo: 'funds.main'
	  });
	
	  $stateProvider.state('funds.main', {
	    url: '',
	    template: __webpack_require__(177)
	  });
	
	  $stateProvider.state('funds.bank', {
	    url: '/bank',
	    template: __webpack_require__(178),
	    controller: ['$scope', 'gon', function ($scope, gon) {
	      $scope.stripePayoutActive = gon.fundraiser.stripe_payout_active;
	    }]
	  });
	
	  $stateProvider.state('donations', {
	    url: '/donations',
	    template: __webpack_require__(179)
	  });
	}]).run(['$rootScope', '$state', function ($rootScope, $state) {
	  $rootScope.$on('$stateChangeStart', function (evt, to, params) {
	    if (to.redirectTo) {
	      evt.preventDefault();
	      $state.go(to.redirectTo, params);
	    }
	  });
	}]).run(['$window', function ($window) {
	  $window.skipExceptions = true;
	}]);
	
	angular.module('campaignPage.mobile', ['campaignPage.responsive', 'ui.router', 'header', 'footer', 'utils', 'perks', 'campaignPage.utils', 'campaignPage.preorder']).directive('campaignLogin', _campaignLoginDirective2.default).directive('campaignMain', _campaignMainDirective2.default).directive('campaignStory', _campaignStoryDirective2.default).directive('collapsable', _collapsableDirective2.default).config(['$stateProvider', '$urlRouterProvider', '$provide', function ($stateProvider, $urlRouterProvider, $provide) {
	  $urlRouterProvider.otherwise('/');
	
	  $stateProvider.state('main', {
	    url: '/',
	    template: __webpack_require__(180)
	  });
	
	  $stateProvider.state('story', {
	    url: '/story',
	    template: __webpack_require__(181)
	  });
	
	  $stateProvider.state('trust_passport', {
	    url: '/trust_passport',
	    template: '<campaign-trust-passport-mobile></campaign-trust-passport-mobile>'
	  });
	
	  $stateProvider.state('contact', {
	    url: '/contact',
	    template: '<campaign-contact-mobile></campaign-contact-mobile>'
	  });
	
	  $stateProvider.state('perks', {
	    url: '/perks/:perkId',
	    template: __webpack_require__(180)
	  });
	
	  $provide.decorator('$uiViewScroll', ["$delegate", "$window", "browser", function ($delegate, $window, browser) {
	    return function (uiViewElement) {
	      if (browser.isIphone()) {
	        var iPhoneSmartAppBannerPadding = -100;
	        $window.scrollTo(0, iPhoneSmartAppBannerPadding);
	      } else {
	        $window.scrollTo(0, 0);
	      }
	    };
	  }]);
	}]).run(['campaign', '$http', 'gon', 'ga', function (campaign, $http, gon, ga) {
	  if (gon && gon.campaign) {
	    campaign.setCampaignJson(gon.campaign);
	  }
	
	  if (gon && gon.campaignPrivateJson) {
	    _.merge(campaign, gon.campaignPrivateJson);
	  }
	
	  if (gon && gon.tracking_info && gon.tracking_info.google_analytics_id) {
	    // TODO EVENTS: id=euge9 fixtype=infra subsystem=campaign-page . Move GA campaign create elsewhere
	    ga('create', gon.tracking_info.google_analytics_id, 'auto', { 'name': 'campaign' });
	    // TODO EVENTS: id=zieb5 fixtype=pageview subsystem=campaign-page . review
	    ga('campaign.send', 'pageview');
	  }
	
	  if (gon.pageview_data) {
	    // TODO EVENTS: id=ruap3 fixtype=pageview name-new=TBD subsystem=campaign-page . review pageview overwrite
	    ga('send', 'pageview', gon.pageview_data.analytics_friendly_url);
	  }
	
	  var csrfToken = $('meta[name=csrf-token]').attr('content');
	  $http.defaults.headers.common['X-CSRF-Token'] = csrfToken;
	}]);
	
	angular.module('campaignPage.generosity', ['campaignPage.utils', 'campaignPage.share', 'header', 'footer', 'utils', 'indiegogo.components.updatePreview']).factory('generosityFundraiser', _generosityFundraiserService2.default).factory('generosityStoryTruncation', _generosityStoryTruncationService2.default).directive('addYourDonation', _addYourDonationDirective2.default).directive('generosityDonations', _generosityDonationsDirective2.default).directive('generosityFundraiserMain', _generosityFundraiserMainDirective2.default).directive('generosityPerks', _generosityPerksDirective2.default).directive('generosityPostUpdate', _generosityPostUpdateDirective2.default).directive('generosityStory', _generosityStoryDirective2.default).directive('generosityUpdates', _generosityUpdatesDirective2.default).directive('generosityUpdatePreview', _generosityUpdatePreviewDirective2.default).run(['$window', function ($window) {
	  $window.skipExceptions = true;
	}]);
	
	angular.module('campaignPage.shareWizard', ['campaignPage.share']).config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
	
	  $urlRouterProvider.otherwise('/');
	
	  $stateProvider.state('facebook', {
	    url: '/',
	    template: __webpack_require__(182),
	    controller: ["$scope", function controller($scope) {
	      $scope.captureEvent('share_wizard_fb');
	    }]
	  });
	
	  $stateProvider.state('facebook-2', {
	    url: '/facebook',
	    template: __webpack_require__(183),
	    controller: ["$scope", function controller($scope) {
	      $scope.captureEvent('share_wizard_fb_2');
	    }]
	  });
	
	  $stateProvider.state('twitter', {
	    url: '/twitter',
	    template: __webpack_require__(184),
	    controller: ["$scope", function controller($scope) {
	      $scope.captureEvent('share_wizard_tw');
	    }]
	  });
	
	  $stateProvider.state('email', {
	    url: '/email',
	    template: __webpack_require__(185),
	    controller: ["$scope", function controller($scope) {
	      $scope.captureEvent('share_wizard_email');
	    }]
	  });
	}]).run(['$window', function ($window) {
	  $window.skipExceptions = true;
	}]);
	
	angular.module('campaignPage.share', ['templates', 'header', 'footer', 'utils', 'campaignPage.utils', 'ui.router']).factory('emailImporter', _emailImporterService2.default).directive('emailImporter', _emailImporterDirective2.default).directive('shareWizard', _shareWizardDirective2.default).run(['$window', function ($window) {
	  $window.skipExceptions = true;
	}]);
	
	angular.module('campaignPage.utils', ['utils']).factory('campaignOwner', _campaignOwnerService2.default).factory('fbAutopost', _fbAutopostService2.default).factory('pcCampaign', _pcCampaignService2.default).factory('todoItems', _todoItemsService2.default).directive('backToTop', _backToTopDirective2.default).directive('generosityFbShare', _generosityFbShareDirective2.default).directive('pcContact', _pcContactDirective2.default).directive('pcFbShare', _pcFbShareDirective2.default).directive('publishButton', _publishButtonDirective2.default).run(['$window', function ($window) {
	  $window.skipExceptions = true;
	}]);
	
	angular.module('campaignPage.preorder', ['templates', 'utils', 'perks']).run(['$window', function ($window) {
	  $window.skipExceptions = true;
	}]);
	
	angular.module('campaignPage.desktop', ['campaignPage.responsive', 'templates', 'utils', 'campaignPage.utils', 'ngAnimate', 'perks', 'ui.router', 'campaignPage.share', 'pusher-angular', 'discovery', 'ngCookies', 'campaignPage.preorder', 'indiegogo.components.updatePreview']).factory('campaignComments', _campaignCommentsService2.default).factory('campaignUpdates', _campaignUpdatesService2.default).factory('campaignHeaderRecommendations', _campaignHeaderRecommendationsService2.default).factory('pusherWrapper', _pusherWrapperService2.default).factory('campaignPusher', _campaignPusherService2.default).factory('contributionsApi', _contributionsApiService2.default).factory('RefundDisplayFactory', _refundDisplayFactory2.default).provider('storyTabCache', _storyTabCacheProvider2.default).directive('campaignHeaderRecommendations', _campaignHeaderRecommendationsDirective2.default).directive('campaignShareModal', _campaignShareModalDirective2.default).directive('contributeButtonGaTracking', _contributeButtonGaTrackingDirective2.default).directive('desktopApprovalButton', _desktopApprovalButtonDirective2.default).directive('desktopCampaignPage', _desktopCampaignPageDirective2.default).directive('desktopComment', _desktopCommentDirective2.default).directive('desktopComments', _desktopCommentsDirective2.default).directive('desktopCommentContributionDetails', _desktopCommentContributionDetailsDirective2.default).directive('orderState', _orderStateDirective2.default).directive('paymentMethod', _paymentMethodDirective2.default).directive('lineItems', _lineItemsDirective2.default).directive('desktopFacebookShare', _desktopFacebookShareDirective2.default).directive('desktopFunders', _desktopFundersDirective2.default).directive('desktopGallery', _desktopGalleryDirective2.default).directive('desktopNavBar', _desktopNavBarDirective2.default).directive('desktopProjectFunderCount', _desktopProjectFunderCountDirective2.default).directive('desktopUpdates', _desktopUpdatesDirective2.default).directive('desktopUpdatePreview', _desktopUpdatePreviewDirective2.default).directive('earlyContribute', _earlyContributeDirective2.default).config(['storyTabCacheProvider', '$stateProvider', '$urlRouterProvider', function (storyTabCacheProvider, $stateProvider, $urlRouterProvider) {
	  storyTabCacheProvider.cacheHtml(angular.element('[ui-view]'));
	
	  $urlRouterProvider.when('/activity', '/updates');
	  $urlRouterProvider.when('/pledges', '/funders');
	  $urlRouterProvider.otherwise('/');
	
	  var storyTemplateProvider = function storyTemplateProvider(storyTabCache) {
	    return storyTabCache.cachedHtml();
	  };
	  storyTemplateProvider.$inject = ['storyTabCache'];
	
	  $stateProvider.state('story', {
	    url: '/story',
	    templateProvider: storyTemplateProvider
	  });
	
	  $stateProvider.state('updates', {
	    url: '/updates',
	    template: "<desktop-updates></desktop-updates>",
	    controller: ["$scope", function controller($scope) {}]
	  });
	
	  $stateProvider.state('comments', {
	    url: '/comments',
	    template: "<desktop-comments></desktop-comments>",
	    controller: ["$scope", function controller($scope) {}]
	  });
	
	  $stateProvider.state('funders', {
	    url: '/funders',
	    template: "<desktop-funders></desktop-funders>",
	    controller: ["$scope", function controller($scope) {}]
	  });
	
	  $stateProvider.state('gallery', {
	    url: '/gallery',
	    template: "<desktop-gallery></desktop-gallery>",
	    controller: ["$scope", function controller($scope) {}]
	  });
	
	  $stateProvider.state('perks', {
	    url: '/perks/:perkId',
	    templateProvider: storyTemplateProvider,
	    controller: ["$scope", function controller($scope) {}]
	  });
	}]).run(['campaignPusher', 'gon', 'ga', '$cookies', 'contributionsApi', function (campaignPusher, gon, ga, $cookies, contributionsApi) {
	  if (gon && gon.tracking_info && gon.tracking_info.google_analytics_id) {
	    // TODO EVENTS: id=aix0o fixtype=ga-create subsystem=campaign-page . revisit the campaigner tracker creation
	    ga('create', gon.tracking_info.google_analytics_id, 'auto', { 'name': 'campaign' });
	    if (typeof $cookies.get('utm_campaign') !== 'undefined' && $cookies.get('utm_campaign').indexOf('iggmediasource') < 0) {
	      ga('campaign.set', {
	        campaignName: $cookies.get('utm_campaign'),
	        campaignSource: $cookies.get('utm_source'),
	        campaignMedium: $cookies.get('utm_medium'),
	        campaignKeyword: $cookies.get('utm_term'),
	        campaignContent: $cookies.get('utm_content')
	      });
	    }
	    // TODO EVENTS: id=eew2x subsystem=campaigner-analytics fixtype=pageview name-new=TBD . review pageview
	    ga('campaign.send', 'pageview');
	  }
	  angular.element("[ui-view]").show();
	  if (gon) {
	    if (gon.pusher) {
	      campaignPusher.start();
	    }
	    if (gon.urls && gon.urls.contributionsApi) {
	      contributionsApi.setUrls(gon.urls.contributionsApi);
	    }
	  }
	  // TODO EVENTS: id=ies1j category=Trust action=Teaser subsystem=campaign-page fixtype=bare-ga name-new=TBD . review
	  ga('send', 'event', 'Trust', 'Teaser');
	}]).run(['$window', function ($window) {
	  $window.skipExceptions = true;
	}]);

/***/ },
/* 1 */
/***/ function(module, exports) {

	/**
	 * @license AngularJS v1.4.6
	 * (c) 2010-2015 Google, Inc. http://angularjs.org
	 * License: MIT
	 */
	(function(window, angular, undefined) {'use strict';
	
	/**
	 * @ngdoc module
	 * @name ngCookies
	 * @description
	 *
	 * # ngCookies
	 *
	 * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.
	 *
	 *
	 * <div doc-module-components="ngCookies"></div>
	 *
	 * See {@link ngCookies.$cookies `$cookies`} for usage.
	 */
	
	
	angular.module('ngCookies', ['ng']).
	  /**
	   * @ngdoc provider
	   * @name $cookiesProvider
	   * @description
	   * Use `$cookiesProvider` to change the default behavior of the {@link ngCookies.$cookies $cookies} service.
	   * */
	   provider('$cookies', [function $CookiesProvider() {
	    /**
	     * @ngdoc property
	     * @name $cookiesProvider#defaults
	     * @description
	     *
	     * Object containing default options to pass when setting cookies.
	     *
	     * The object may have following properties:
	     *
	     * - **path** - `{string}` - The cookie will be available only for this path and its
	     *   sub-paths. By default, this would be the URL that appears in your base tag.
	     * - **domain** - `{string}` - The cookie will be available only for this domain and
	     *   its sub-domains. For obvious security reasons the user agent will not accept the
	     *   cookie if the current domain is not a sub domain or equals to the requested domain.
	     * - **expires** - `{string|Date}` - String of the form "Wdy, DD Mon YYYY HH:MM:SS GMT"
	     *   or a Date object indicating the exact date/time this cookie will expire.
	     * - **secure** - `{boolean}` - The cookie will be available only in secured connection.
	     *
	     * Note: by default the address that appears in your `<base>` tag will be used as path.
	     * This is important so that cookies will be visible for all routes in case html5mode is enabled
	     *
	     **/
	    var defaults = this.defaults = {};
	
	    function calcOptions(options) {
	      return options ? angular.extend({}, defaults, options) : defaults;
	    }
	
	    /**
	     * @ngdoc service
	     * @name $cookies
	     *
	     * @description
	     * Provides read/write access to browser's cookies.
	     *
	     * <div class="alert alert-info">
	     * Up until Angular 1.3, `$cookies` exposed properties that represented the
	     * current browser cookie values. In version 1.4, this behavior has changed, and
	     * `$cookies` now provides a standard api of getters, setters etc.
	     * </div>
	     *
	     * Requires the {@link ngCookies `ngCookies`} module to be installed.
	     *
	     * @example
	     *
	     * ```js
	     * angular.module('cookiesExample', ['ngCookies'])
	     *   .controller('ExampleController', ['$cookies', function($cookies) {
	     *     // Retrieving a cookie
	     *     var favoriteCookie = $cookies.get('myFavorite');
	     *     // Setting a cookie
	     *     $cookies.put('myFavorite', 'oatmeal');
	     *   }]);
	     * ```
	     */
	    this.$get = ['$$cookieReader', '$$cookieWriter', function($$cookieReader, $$cookieWriter) {
	      return {
	        /**
	         * @ngdoc method
	         * @name $cookies#get
	         *
	         * @description
	         * Returns the value of given cookie key
	         *
	         * @param {string} key Id to use for lookup.
	         * @returns {string} Raw cookie value.
	         */
	        get: function(key) {
	          return $$cookieReader()[key];
	        },
	
	        /**
	         * @ngdoc method
	         * @name $cookies#getObject
	         *
	         * @description
	         * Returns the deserialized value of given cookie key
	         *
	         * @param {string} key Id to use for lookup.
	         * @returns {Object} Deserialized cookie value.
	         */
	        getObject: function(key) {
	          var value = this.get(key);
	          return value ? angular.fromJson(value) : value;
	        },
	
	        /**
	         * @ngdoc method
	         * @name $cookies#getAll
	         *
	         * @description
	         * Returns a key value object with all the cookies
	         *
	         * @returns {Object} All cookies
	         */
	        getAll: function() {
	          return $$cookieReader();
	        },
	
	        /**
	         * @ngdoc method
	         * @name $cookies#put
	         *
	         * @description
	         * Sets a value for given cookie key
	         *
	         * @param {string} key Id for the `value`.
	         * @param {string} value Raw value to be stored.
	         * @param {Object=} options Options object.
	         *    See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
	         */
	        put: function(key, value, options) {
	          $$cookieWriter(key, value, calcOptions(options));
	        },
	
	        /**
	         * @ngdoc method
	         * @name $cookies#putObject
	         *
	         * @description
	         * Serializes and sets a value for given cookie key
	         *
	         * @param {string} key Id for the `value`.
	         * @param {Object} value Value to be stored.
	         * @param {Object=} options Options object.
	         *    See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
	         */
	        putObject: function(key, value, options) {
	          this.put(key, angular.toJson(value), options);
	        },
	
	        /**
	         * @ngdoc method
	         * @name $cookies#remove
	         *
	         * @description
	         * Remove given cookie
	         *
	         * @param {string} key Id of the key-value pair to delete.
	         * @param {Object=} options Options object.
	         *    See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
	         */
	        remove: function(key, options) {
	          $$cookieWriter(key, undefined, calcOptions(options));
	        }
	      };
	    }];
	  }]);
	
	angular.module('ngCookies').
	/**
	 * @ngdoc service
	 * @name $cookieStore
	 * @deprecated
	 * @requires $cookies
	 *
	 * @description
	 * Provides a key-value (string-object) storage, that is backed by session cookies.
	 * Objects put or retrieved from this storage are automatically serialized or
	 * deserialized by angular's toJson/fromJson.
	 *
	 * Requires the {@link ngCookies `ngCookies`} module to be installed.
	 *
	 * <div class="alert alert-danger">
	 * **Note:** The $cookieStore service is **deprecated**.
	 * Please use the {@link ngCookies.$cookies `$cookies`} service instead.
	 * </div>
	 *
	 * @example
	 *
	 * ```js
	 * angular.module('cookieStoreExample', ['ngCookies'])
	 *   .controller('ExampleController', ['$cookieStore', function($cookieStore) {
	 *     // Put cookie
	 *     $cookieStore.put('myFavorite','oatmeal');
	 *     // Get cookie
	 *     var favoriteCookie = $cookieStore.get('myFavorite');
	 *     // Removing a cookie
	 *     $cookieStore.remove('myFavorite');
	 *   }]);
	 * ```
	 */
	 factory('$cookieStore', ['$cookies', function($cookies) {
	
	    return {
	      /**
	       * @ngdoc method
	       * @name $cookieStore#get
	       *
	       * @description
	       * Returns the value of given cookie key
	       *
	       * @param {string} key Id to use for lookup.
	       * @returns {Object} Deserialized cookie value, undefined if the cookie does not exist.
	       */
	      get: function(key) {
	        return $cookies.getObject(key);
	      },
	
	      /**
	       * @ngdoc method
	       * @name $cookieStore#put
	       *
	       * @description
	       * Sets a value for given cookie key
	       *
	       * @param {string} key Id for the `value`.
	       * @param {Object} value Value to be stored.
	       */
	      put: function(key, value) {
	        $cookies.putObject(key, value);
	      },
	
	      /**
	       * @ngdoc method
	       * @name $cookieStore#remove
	       *
	       * @description
	       * Remove given cookie
	       *
	       * @param {string} key Id of the key-value pair to delete.
	       */
	      remove: function(key) {
	        $cookies.remove(key);
	      }
	    };
	
	  }]);
	
	/**
	 * @name $$cookieWriter
	 * @requires $document
	 *
	 * @description
	 * This is a private service for writing cookies
	 *
	 * @param {string} name Cookie name
	 * @param {string=} value Cookie value (if undefined, cookie will be deleted)
	 * @param {Object=} options Object with options that need to be stored for the cookie.
	 */
	function $$CookieWriter($document, $log, $browser) {
	  var cookiePath = $browser.baseHref();
	  var rawDocument = $document[0];
	
	  function buildCookieString(name, value, options) {
	    var path, expires;
	    options = options || {};
	    expires = options.expires;
	    path = angular.isDefined(options.path) ? options.path : cookiePath;
	    if (angular.isUndefined(value)) {
	      expires = 'Thu, 01 Jan 1970 00:00:00 GMT';
	      value = '';
	    }
	    if (angular.isString(expires)) {
	      expires = new Date(expires);
	    }
	
	    var str = encodeURIComponent(name) + '=' + encodeURIComponent(value);
	    str += path ? ';path=' + path : '';
	    str += options.domain ? ';domain=' + options.domain : '';
	    str += expires ? ';expires=' + expires.toUTCString() : '';
	    str += options.secure ? ';secure' : '';
	
	    // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
	    // - 300 cookies
	    // - 20 cookies per unique domain
	    // - 4096 bytes per cookie
	    var cookieLength = str.length + 1;
	    if (cookieLength > 4096) {
	      $log.warn("Cookie '" + name +
	        "' possibly not set or overflowed because it was too large (" +
	        cookieLength + " > 4096 bytes)!");
	    }
	
	    return str;
	  }
	
	  return function(name, value, options) {
	    rawDocument.cookie = buildCookieString(name, value, options);
	  };
	}
	
	$$CookieWriter.$inject = ['$document', '$log', '$browser'];
	
	angular.module('ngCookies').provider('$$cookieWriter', function $$CookieWriterProvider() {
	  this.$get = $$CookieWriter;
	});
	
	
	})(window, window.angular);


/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	generosityBankCountryDirective.$inject = ["countriesService", "i18n"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = generosityBankCountryDirective;
	/*@ngInject*/
	
	function generosityBankCountryDirective(countriesService, i18n) {
	  return {
	    restrict: 'E',
	    scope: {
	      beneficiaryIdentity: '=',
	      canEdit: '='
	    },
	    template: __webpack_require__(3),
	    link: function link(scope, element, attrs) {
	      scope.i18n = i18n;
	      scope.countryOptions = countriesService.all();
	    }
	  };
	}

/***/ },
/* 3 */
/***/ function(module, exports) {

	module.exports = "<div class=\"i-field-row stripeBankCountryCode\">\n  <div class=\"i-block-label\">\n    <label>{{::i18n.t('generosity.dashboard.funds.bank_account_country')}}</label>\n    <span igg-popover>{{::i18n.t('generosity.dashboard.funds.bank_account_country_tooltip')}}</span>\n  </div>\n  <div class=\"i-address-country inline-elements\">\n    <ui-select ng-model=\"beneficiaryIdentity.bankCountryCode\" theme=\"select2\" ng-disabled=\"!canEdit\">\n      <ui-select-match placeholder=\"{{::i18n.t('country')}}\">\n        {{$select.selected.text}}\n      </ui-select-match>\n      <ui-select-choices repeat=\"country.country_code_alpha_2 as country in countryOptions | filter: $select.search\">\n        {{selectItem.text}}\n      </ui-select-choices>\n    </ui-select>\n  </div>\n</div>\n";

/***/ },
/* 4 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	generosityBeneficiaryNameDirective.$inject = ["i18n"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = generosityBeneficiaryNameDirective;
	/*@ngInject*/
	
	function generosityBeneficiaryNameDirective(i18n) {
	  return {
	    restrict: 'E',
	    scope: {
	      beneficiaryIdentity: '=',
	      canEdit: '=',
	      isNonprofit: '='
	    },
	    template: __webpack_require__(5),
	    link: function link(scope) {
	      scope.firstNameLabel = scope.isNonprofit ? i18n.t('generosity.dashboard.funds.legal_first_name_representative') : i18n.t('generosity.dashboard.funds.legal_first_name');
	      scope.lastNameLabel = scope.isNonprofit ? i18n.t('generosity.dashboard.funds.legal_last_name_representative') : i18n.t('generosity.dashboard.funds.legal_last_name');
	    }
	  };
	}

/***/ },
/* 5 */
/***/ function(module, exports) {

	module.exports = "<div class=\"inline-elements\">\n  <div>\n    <label for=\"stripeFirstName\" class=\"i-block-label\">{{::firstNameLabel}}</label>\n    <input id=\"stripeFirstName\" ng-model=\"beneficiaryIdentity.firstName\" class=\"i-text-field i-form-field-3\" ng-disabled=\"!canEdit\"/>\n  </div>\n  <div>\n    <label for=\"stripeLastName\" class=\"i-block-label\">{{::lastNameLabel}}</label>\n    <input id=\"stripeLastName\" ng-model=\"beneficiaryIdentity.lastName\" class=\"i-text-field i-form-field-3\" ng-disabled=\"!canEdit\"/>\n  </div>\n</div>\n";

/***/ },
/* 6 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	generosityNonprofitNameDirective.$inject = ["i18n"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = generosityNonprofitNameDirective;
	/*@ngInject*/
	
	function generosityNonprofitNameDirective(i18n) {
	  return {
	    restrict: 'E',
	    scope: {
	      beneficiaryIdentity: '=',
	      canEdit: '='
	    },
	    template: __webpack_require__(7),
	    link: function link(scope) {
	      scope.i18n = i18n;
	    }
	  };
	}

/***/ },
/* 7 */
/***/ function(module, exports) {

	module.exports = "<div class=\"inline-elements\">\n  <div>\n    <label for=\"stripeBusinessName\" class=\"i-block-label\">{{::i18n.t('generosity.dashboard.funds.nonprofit_name')}}</label>\n    <input id=\"stripeBusinessName\" ng-model=\"beneficiaryIdentity.businessName\" class=\"i-text-field i-form-field-3\" ng-disabled=\"!canEdit\"/>\n  </div>\n  <div>\n    <label for=\"stripeBusinessEin\" class=\"i-block-label\">{{::i18n.t('generosity.dashboard.funds.tax_id_business_ein')}}</label>\n    <input id=\"stripeBusinessEin\" ng-model=\"beneficiaryIdentity.businessEin\" class=\"i-text-field i-form-field-3\" ng-disabled=\"!canEdit\"/>\n  </div>\n</div>\n";

/***/ },
/* 8 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	generosityStripeBankFormDirective.$inject = ["ibbAccountService", "i18n", "gon", "$modal", "browser"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = generosityStripeBankFormDirective;
	/*@ngInject*/
	
	function generosityStripeBankFormDirective(ibbAccountService, i18n, gon, $modal, browser) {
	  return {
	    template: __webpack_require__(9),
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.errors = {};
	      scope.permissions = gon.fundraiser.permissions;
	      scope.beneficiaryIdentity = hackSnakeCase(gon.fundraiser.beneficiary_identity);
	      scope.isNonprofit = gon.fundraiser.owner_type === 'nonprofit';
	
	      ibbAccountService.setBankAccountsUrl(gon.urls.campaign_bank_accounts_url);
	      ibbAccountService.setIdentityVerificationUrl(gon.urls.campaign_identity_verification_url);
	
	      scope.loaded = false;
	      ibbAccountService.load().then(function () {
	        scope.account = ibbAccountService.account;
	        scope.options = ibbAccountService.options;
	        scope.account.bank = scope.account.bank || {};
	        scope.fieldsNeeded = ibbAccountService.fieldsNeeded;
	        scope.loaded = true;
	
	        scope.$watchGroup(['options.extended_verification', 'fieldsNeeded.length'], function () {
	          var alreadyProvidedFullSsn = scope.account.owner.ssn.ssnFullProvided;
	          var fullSsnRequested = scope.options.extended_verification && !! ~scope.fieldsNeeded.indexOf('legal_entity.personal_id_number');
	          scope.needsFullSsn = alreadyProvidedFullSsn || fullSsnRequested;
	          scope.needsIdentityDoc = !!(scope.options.extended_verification && ~scope.fieldsNeeded.indexOf('legal_entity.verification.document'));
	
	          // Lock the bank identity fields immediately after completing bank account, even if Stripe webhooks didn't update gon value yet
	          scope.permissions.can_edit_stripe_bank_identity = gon.fundraiser.permissions.can_edit_stripe_bank_identity && (_.include(scope.fieldsNeeded, 'bank_account') || scope.permissions.can_edit_stripe_identity);
	
	          scope.lockedDownForVerification = !scope.permissions.can_edit_stripe_identity && !scope.permissions.can_edit_stripe_bank_identity && !scope.permissions.can_edit_stripe_country && !scope.permissions.can_edit_stripe_bank_token && !scope.needsIdentityDoc && !scope.needsFullSsn;
	        });
	      });
	
	      scope.submitButtonText = i18n.t('generosity.dashboard.funds.submit_bank_form');
	
	      scope.validForm = function (account) {
	        return hasBankInfo(account.bank) && hasOwnerInfo(account.owner) && hasAddressInfo(account.address) && !inError(scope.errors);
	      };
	
	      scope.formFocused = function () {
	        if (scope.submitButtonText !== i18n.t('campaign_editor.buttons.saving') && !scope.lockedDownForVerification) {
	          scope.submitButtonText = i18n.t('generosity.dashboard.funds.submit_bank_form');
	          scope.disableAfterSave = false;
	        }
	      };
	
	      scope.confirmSubmit = function () {
	        $modal({ template: __webpack_require__(10), scope: scope });
	      };
	
	      scope.updateStripeAccountInfo = function () {
	        ibbAccountService.updateAccount(scope.account, scope.beneficiaryIdentity).then(onSuccessfulUpdate, onFailedUpdate);
	        scope.submitButtonText = i18n.t('campaign_editor.buttons.saving');
	        scope.disableAfterSave = true;
	        scope.errors = {};
	      };
	
	      function onSuccessfulUpdate() {
	        scope.account = ibbAccountService.account;
	        scope.submitButtonText = i18n.t('campaign_editor.buttons.saved');
	        browser.scrollToTop();
	      }
	
	      function onFailedUpdate(response) {
	        if (response && response.data && response.data.error_description && response.data.error_code === "bank_account") {
	          addErrorMessages(response.data.error_description);
	        } else {
	          addErrorMessages(i18n.t('campaign_editor.funding.failed_to_save'));
	        }
	        scope.submitButtonText = i18n.t('generosity.dashboard.funds.submit_bank_form');
	        scope.disableAfterSave = false;
	      }
	
	      function addErrorMessages(message) {
	        if (message.match(/routing/i) !== null) {
	          scope.errors.routingNumber = message;
	        } else if (message.match(/account/i) !== null) {
	          scope.errors.accountNumber = message;
	        } else {
	          scope.errors.misc = message;
	        }
	      }
	
	      function hasBankInfo(bank) {
	        if (!bank) return false;
	        var bankInfoFilledOut = !!(bank.accountNumber && bank.routingNumber);
	        var bankInfoPreviouslySaved = !!bank.savedAccountNumberLast4;
	        return bankInfoFilledOut || bankInfoPreviouslySaved;
	      }
	
	      function inError(errorsObj) {
	        return Object.keys(errorsObj).filter(function (key) {
	          return key !== 'misc';
	        }).map(function (key) {
	          return errorsObj[key];
	        }).reduce(function (isInError, errorString) {
	          return errorString.length > 0 || isInError;
	        }, false);
	      }
	
	      function hasOwnerInfo(owner) {
	        var last4SsnOkay = !scope.needsFullSsn && (owner.ssn.last4 || owner.ssn.ssnLast4Provided);
	        var fullSsnOkay = scope.needsFullSsn && (owner.ssn.full || owner.ssn.ssnFullProvided);
	        var ssnValid = last4SsnOkay || fullSsnOkay;
	
	        var dobValid = scope.beneficiaryIdentity.dob.day && scope.beneficiaryIdentity.dob.month && scope.beneficiaryIdentity.dob.year;
	        var nameValid = scope.beneficiaryIdentity.firstName && scope.beneficiaryIdentity.lastName;
	        var beneficiaryIdentityValid = dobValid && nameValid;
	
	        return beneficiaryIdentityValid && ssnValid;
	      }
	
	      function hasAddressInfo(address) {
	        if (!address) return false;
	        return !!(address.city && address.streetAddress1 && address.regionCode && address.postalCode);
	      }
	
	      function hackSnakeCase(beneficiaryIdentityJson) {
	        return {
	          bankCountryCode: beneficiaryIdentityJson.bank_country_code,
	          businessEin: beneficiaryIdentityJson.business_ein,
	          businessName: beneficiaryIdentityJson.business_name,
	          dob: {
	            day: beneficiaryIdentityJson.dob.day,
	            month: beneficiaryIdentityJson.dob.month,
	            year: beneficiaryIdentityJson.dob.year
	          },
	          firstName: beneficiaryIdentityJson.first_name,
	          lastName: beneficiaryIdentityJson.last_name,
	          stripeComplete: beneficiaryIdentityJson.stripe_complete
	        };
	      }
	    }
	  };
	}

/***/ },
/* 9 */
/***/ function(module, exports) {

	module.exports = "<div class=\"stripeBankForm-aboveForm\">\n  <div class=\"stripeBankForm-title\">{{::i18n.t('generosity.dashboard.funds.bank_account_information')}}</div>\n  <a class=\"stripeBankForm-back\" ui-sref=\"funds\">{{::i18n.t('generosity.dashboard.funds.back_to_funds')}}</a>\n</div>\n\n<div class=\"pc-dashboard-section stripeBankForm\" ng-if=\"loaded\">\n  <div class=\"pc-dashboard-section-header stripeBankForm-header\">\n    <span class=\"pc-dashboard-section-title\">{{::i18n.t('generosity.dashboard.funds.funds_recipient')}}</span>\n    <span class=\"i-annotation-pill i-pill-happy\" ng-if=\"!fieldsNeeded.length && account.owner.verification_status === 'verified'\">{{::i18n.t('campaign_editor.funding.identity_verified')}}</span>\n    <span class=\"i-annotation-pill i-pill-pending\" ng-if=\"fieldsNeeded.length===0 && account.owner.verification_status !== 'verified'\">{{::i18n.t('campaign_editor.funding.awaiting_verification')}}</span>\n  </div>\n  <div class=\"pc-dashboard-section-body stripeBankForm-body\" ng-click=\"formFocused()\">\n    <div class=\"stripeBankForm-boilerplate\">{{::i18n.t('generosity.dashboard.funds.stripe_bank_form_boilerplate')}}</div>\n    <generosity-nonprofit-name ng-if=\"isNonprofit\" class=\"i-field-row\" beneficiary-identity=\"beneficiaryIdentity\" can-edit=\"permissions.can_edit_stripe_identity\"></generosity-nonprofit-name>\n    <generosity-beneficiary-name class=\"i-field-row\" beneficiary-identity=\"beneficiaryIdentity\" can-edit=\"permissions.can_edit_stripe_identity\" is-nonprofit=\"isNonprofit\"></generosity-beneficiary-name>\n    <ibb-dob class=\"i-field-row\" beneficiary-identity=\"beneficiaryIdentity\" can-edit=\"permissions.can_edit_stripe_identity\"></ibb-dob>\n    <ibb-ssn class=\"i-field-row\" ssn=\"account.owner.ssn\" full-ssn-needed=\"needsFullSsn\" errors=\"errors\" can-edit=\"permissions.can_edit_stripe_bank_identity\"></ibb-ssn>\n    <generosity-stripe-country class=\"i-field-row\" beneficiary-identity=\"beneficiaryIdentity\" can-edit=\"permissions.can_edit_stripe_country\"></generosity-stripe-country>\n    <ibb-address class=\"i-field-row\" address=\"account.address\" can-edit=\"permissions.can_edit_stripe_bank_identity\"></ibb-address>\n    <generosity-bank-country class=\"i-field-row\" beneficiary-identity=\"beneficiaryIdentity\" can-edit=\"permissions.can_edit_stripe_country\"></generosity-bank-country>\n    <ibb-bank-account class=\"i-field-row\" bank=\"account.bank\" can-edit=\"permissions.can_edit_stripe_bank_token\" errors=\"errors\"></ibb-bank-account>\n    <ibb-file-uploader class=\"i-field-row\" ng-if=\"needsIdentityDoc\"></ibb-file-uploader>\n  </div>\n</div>\n\n<div class=\"i-button-row\" ng-if=\"loaded\">\n  <button class=\"primary-cta stripeBankForm-cta\" ng-click=\"confirmSubmit()\"\n          ng-disabled=\"!validForm(account) || lockedDownForVerification || disableAfterSave\">{{submitButtonText}}</button>\n  <div id=\"generic-error\" class=\"error-message i-block-label\" ng-if=\"errors.misc\">{{errors.misc}}</div>\n</div>\n";

/***/ },
/* 10 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal\">\n  <div class=\"modal-dialog lifeModal-dialog\">\n    <div class=\"modal-content lifeModal-content lifeModal-content--shady\">\n      <a class=\"lifeModal-close\" ng-click=\"$hide()\">\n        <svg-icon icon=\"icon-icon-close\"></svg-icon>\n      </a>\n      <div class=\"lifeModal-container\">\n        <div class=\"lifeModal-headerText\">{{::i18n.t('generosity.dashboard.confirm_stripe_modal.title')}}</div>\n        <div class=\"lifeModal-bodyText\">{{::i18n.t('generosity.dashboard.confirm_stripe_modal.explanation')}}</div>\n\n        <div class=\"lifeModal-buttons hidden-xs\">\n          <a href=\"\" class=\"lifeModal-button lifeModal-button--cancel\" ng-click=\"$hide()\">{{::i18n.t('cancel')}}</a>\n          <a href=\"\" class=\"primary-cta lifeModal-button\" ng-click=\"$hide(); updateStripeAccountInfo()\">{{::i18n.t('submit')}}</a>\n        </div>\n\n        <div class=\"lifeModal-buttons visible-xs\">\n          <a href=\"\" class=\"primary-cta lifeModal-button\" ng-click=\"$hide(); updateStripeAccountInfo()\">{{::i18n.t('submit')}}</a>\n          <a href=\"\" class=\"lifeModal-button lifeModal-button--cancel\" ng-click=\"$hide()\">{{::i18n.t('cancel')}}</a>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 11 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	generosityStripeCountryDirective.$inject = ["countriesService", "i18n"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = generosityStripeCountryDirective;
	/*@ngInject*/
	
	function generosityStripeCountryDirective(countriesService, i18n) {
	  return {
	    restrict: 'E',
	    scope: {
	      beneficiaryIdentity: '=',
	      canEdit: '='
	    },
	    template: __webpack_require__(12),
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.countryOptions = countriesService.all();
	    }
	  };
	}

/***/ },
/* 12 */
/***/ function(module, exports) {

	module.exports = "<div class=\"i-field-row stripeBankCountryCode\">\n  <label class=\"i-block-label\">{{::i18n.t('generosity.dashboard.funds.legal_residence')}}</label>\n  <div class=\"i-address-country inline-elements\">\n    <ui-select ng-model=\"beneficiaryIdentity.bankCountryCode\" theme=\"select2\" ng-disabled=\"!canEdit\">\n      <ui-select-match placeholder=\"{{::i18n.t('country')}}\">\n        {{$select.selected.text}}\n      </ui-select-match>\n      <ui-select-choices repeat=\"country.country_code_alpha_2 as country in countryOptions | filter: $select.search\">\n        {{selectItem.text}}\n      </ui-select-choices>\n    </ui-select>\n  </div>\n</div>\n";

/***/ },
/* 13 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	lifeFundsBankInfoDirective.$inject = ["i18n", "gon", "pcDashboard", "bankInfoService", "browser"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = lifeFundsBankInfoDirective;
	/*@ngInject*/
	
	function lifeFundsBankInfoDirective(i18n, gon, pcDashboard, bankInfoService, browser) {
	  return {
	    scope: {},
	    template: __webpack_require__(14),
	    link: function link(scope) {
	      pcDashboard.getBankInfo().then(function () {
	        scope.bankInfo = pcDashboard.bankInfo;
	        bankInfoService.setCampaign(scope.bankInfo.bankCampaign);
	      });
	      scope.i18n = i18n;
	      scope.closeFlash = function () {
	        scope.successfulSave = false;
	      };
	      scope.save = function () {
	        scope.showSpinner = true;
	        bankInfoService.save().then(function () {
	          scope.showSpinner = false;
	          scope.errors = [];
	          scope.successfulSave = true;
	          pcDashboard.bankInfo.filledOut = true;
	          bankInfoService.cleanBankForm(scope.bankForm);
	          browser.scrollToTop();
	        }, function (response) {
	          scope.showSpinner = false;
	          scope.successfulSave = false;
	          scope.errors = bankInfoService.handleBankFormErrors(scope.bankForm, response.data);
	          browser.scrollToTop();
	        });
	      };
	    }
	  };
	}

/***/ },
/* 14 */
/***/ function(module, exports) {

	module.exports = "<a class=\"bankFundsWellsFargo-back\" ui-sref=\"funds\"><span>{{::i18n.t('generosity.dashboard.funds.back_to_funds')}}</span></a>\n<div class=\"bankFormWellsFargo\" ng-form name=\"bankForm\">\n  <div ng-if=\"bankInfo.loaded\">\n    <div class=\"messageNotification messageNotification--error\" ng-if=\"errors.length > 0\">\n      <ul>\n        <li ng-repeat=\"error in errors\">{{::error}}</li>\n      </ul>\n    </div>\n    <div class=\"messageNotification messageNotification--success\" ng-if=\"successfulSave\"><span>{{::i18n.t('generosity.dashboard.funds.bank_account_information_successfully_saved')}}</span></div>\n\n    <div class=\"bankFormWellsFargo-title\">\n      <span class=\"text\">{{::i18n.t('bank_account_information')}}</span>\n    </div>\n    <section class=\"bankFormWellsFargo-main\">\n      <p class=\"bankFormWellsFargo-explanation\">\n        <span class=\"hidden-inline-xs\">{{::i18n.t('generosity.dashboard.funds.bank_account_explanation_1')}}</span>\n        <span>{{::i18n.t('generosity.dashboard.funds.bank_account_explanation_2')}}</span>\n      </p>\n      <div ng-if=\"bankInfo.bankCampaign.currency_iso_code === 'CAD'\" bank-info-cad>CAD</div>\n      <div ng-if=\"bankInfo.bankCampaign.currency_iso_code === 'GBP'\" bank-info-gbp>GBP</div>\n      <div\n        ng-if=\"bankInfo.bankCampaign.currency_iso_code !== 'CAD' && bankInfo.bankCampaign.currency_iso_code !== 'GBP'\"\n        bank-info-usd>USD\n      </div>\n    </section>\n\n    <section class=\"i-button-row\">\n      <button class=\"pc-cta bankFormWellsFargo-btn\" ng-click=\"save()\">\n        <span ng-if=\"showSpinner\" class=\"fa fa-spinner fa-spin\"></span>\n        <span ng-if=\"!showSpinner\">{{::i18n.t('save')}}</span>\n      </button>\n    </section>\n  </div>\n</div>\n";

/***/ },
/* 15 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	lifeFUndsBreakdownDirective.$inject = ["i18n", "gon", "pcDashboard", "currencies", "iggCurrencyFilter", "$modal"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = lifeFUndsBreakdownDirective;
	/*@ngInject*/
	
	function lifeFUndsBreakdownDirective(i18n, gon, pcDashboard, currencies, iggCurrencyFilter, $modal) {
	  return {
	    scope: {},
	    restrict: 'A',
	    template: __webpack_require__(16),
	
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.fundsData = pcDashboard.fundsData;
	      scope.showExplanation = function () {
	        $modal({
	          scope: scope,
	          template: __webpack_require__(17)
	        });
	      };
	
	      var creditCardFund = _.findWhere(scope.fundsData.funds, { contribution_method_raw: "credit_card" });
	      var paypalFund = _.findWhere(scope.fundsData.funds, { contribution_method_raw: "paypal" });
	      var totalFund = _.findWhere(scope.fundsData.funds, { contribution_method_raw: "total" }) || creditCardFund;
	      var adjustmentFund = _.findWhere(scope.fundsData.funds, { contribution_method_raw: "adjustment" });
	
	      if (creditCardFund) {
	        var isoNum = currencies.forIsoCode(creditCardFund.currency_iso_code).iso_num;
	        var includeCents = function includeCents(amount) {
	          return iggCurrencyFilter(amount, isoNum, 'noIso,cents');
	        };
	
	        var feeDesc = creditCardFund.transaction_fee_percent * 100 + '%';
	        if (parseFloat(creditCardFund.transaction_fee_fixed) > 0) {
	          var fixedFee = includeCents(creditCardFund.transaction_fee_fixed);
	          var fixedCost = i18n.t('generosity.dashboard.funds.fixed_cost_phrase', { fixed_cost: fixedFee });
	          feeDesc = feeDesc + ' + ' + fixedCost;
	        }
	        scope.transactionFeeLabel = i18n.t('generosity.dashboard.funds.transaction_fee_label', { fee_desc: feeDesc });
	        scope.transactionFees = '- ' + includeCents(creditCardFund.transaction_fees_raw);
	        scope.transactionFeeTooltip = i18n.t('generosity.dashboard.funds.transaction_fee_tooltip', { fee_desc: feeDesc });
	        scope.fundsRaised = [];
	
	        var optionalFees = [];
	        if (parseFloat(totalFund.delivery_fees_raw) > 0) {
	          optionalFees.push({
	            label: i18n.t('generosity.dashboard.funds.bank_delivery_fees'),
	            value: '- ' + includeCents(totalFund.delivery_fees_raw),
	            tooltip: i18n.t('generosity.dashboard.funds.bank_delivery_tooltip')
	          });
	        }
	        if (parseFloat(totalFund.platform_fees_raw) > 0) {
	          optionalFees.push({
	            label: i18n.t('generosity.dashboard.funds.platform_fees'),
	            value: '- ' + includeCents(totalFund.platform_fees_raw)
	          });
	        }
	        if (paypalFund) {
	          optionalFees.push({
	            label: i18n.t('generosity.dashboard.funds.paypal_fees'),
	            value: i18n.t('command_center.estimated_3_to_5_percent')
	          });
	
	          scope.fundsRaised = [{ label: 'PayPal', value: includeCents(paypalFund.total_raised) }, { label: 'Debit/Credit Card', value: includeCents(creditCardFund.total_raised) }];
	        }
	
	        var totalRaised = totalFund.total_raised;
	        if (adjustmentFund) {
	          totalRaised -= adjustmentFund.total_raised;
	          optionalFees.push({
	            label: i18n.t('campaigner_dashboard.adjustment'),
	            value: includeCents(adjustmentFund.total_raised)
	          });
	        }
	
	        scope.fundsRaisedToDate = includeCents(totalRaised);
	        scope.optionalFees = optionalFees;
	
	        var totalTakeawayAmount = parseFloat(totalFund.total_raised_not_yet_disbursed_raw) + parseFloat(totalFund.total_raised_disbursed_raw);
	        scope.totalTakeaway = includeCents(totalTakeawayAmount);
	        if (paypalFund) {
	          scope.totalTakeaway = scope.totalTakeaway + ' (' + i18n.t('campaigner_dashboard.minus_paypal_fees') + ')';
	        }
	      }
	    }
	  };
	}

/***/ },
/* 16 */
/***/ function(module, exports) {

	module.exports = "<div class=\"pc-dashboard-section\">\n  <div class=\"pc-dashboard-section-header\">\n    <a href=\"\" ng-click=\"showExplanation()\" class=\"pc-dashboard-section-header-rtLink visible-md visible-lg\">{{::i18n.t('generosity.dashboard.funds.when_receive_funds')}}</a>\n    <div class=\"pc-dashboard-section-title\">{{::i18n.t('generosity.dashboard.funds.funds_breakdown')}}</div>\n  </div>\n  <ul class=\"pc-dashboard-section-body lifeFunds-body\">\n    <li class=\"lifeFunds-item\" ng-class=\"{'lifeFunds-item--hasSubItems': fundsRaised.length > 0}\">\n      <div class=\"label\">{{::i18n.t('generosity.dashboard.funds.funds_raised_to_date')}}</div>\n      <div class=\"value\">{{fundsRaisedToDate}}</div>\n    </li>\n    <li class=\"lifeFunds-item lifeFunds-item--subItem hidden-xs\" ng-repeat=\"fundRaised in fundsRaised\">\n      <div class=\"label\">{{::fundRaised.label}}</div>\n      <div class=\"value\">({{::fundRaised.value}})</div>\n    </li>\n    <li class=\"lifeFunds-item\">\n      <div class=\"label\"><span>{{transactionFeeLabel}}</span> <span igg-popover placement=\"bottom\">{{transactionFeeTooltip}}</span></div>\n      <div class=\"value\">{{transactionFees}}</div>\n    </li>\n    <li class=\"lifeFunds-item\" ng-repeat=\"fee in optionalFees\">\n      <div class=\"label\"><span>{{::fee.label}}</span> <span igg-popover placement=\"bottom\" ng-if=\"fee.tooltip\">{{fee.tooltip}}</span></div>\n      <div class=\"value\">{{::fee.value}}</div>\n    </li>\n    <li class=\"lifeFunds-item lifeFunds-item--total\">\n      <div class=\"label\">{{::i18n.t('generosity.dashboard.funds.total_takeaway')}}</div>\n      <div class=\"value\">{{totalTakeaway}}</div>\n    </li>\n  </ul>\n</div>\n<a href=\"\" ng-click=\"showExplanation()\" class=\"lifeFunds-underSection hidden-md hidden-lg\">{{::i18n.t('generosity.dashboard.funds.when_receive_funds')}}</a>\n";

/***/ },
/* 17 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal\">\n  <div class=\"modal-dialog lifeModal-dialog\">\n    <div class=\"modal-content lifeModal-content lifeModal-content--shady\">\n      <a class=\"lifeModal-close\" ng-click=\"$hide()\"><svg-icon icon=\"icon-icon-close\"></svg-icon></a>\n      <div class=\"lifeModal-container\">\n        <div class=\"lifeModal-headerText\">{{::i18n.t('generosity.dashboard.funds.when_receive_funds')}}</div>\n        <div class=\"lifeModal-bodyText\">{{::i18n.t('generosity.dashboard.funds.when_receive_funds_explanation')}}</div>\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 18 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	lifeFundsDirective.$inject = ["i18n", "gon", "pcDashboard"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = lifeFundsDirective;
	/*@ngInject*/
	
	function lifeFundsDirective(i18n, gon, pcDashboard) {
	  return {
	    scope: {},
	    restrict: 'A',
	    template: __webpack_require__(19),
	
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.funds = pcDashboard.fundsData;
	      scope.underReview = pcDashboard.underReview;
	      scope.stripePayoutActive = gon.fundraiser.stripe_payout_active;
	      pcDashboard.getDisbursements();
	      pcDashboard.getDonationsUnderReview({ page: 1, per_page: 5 });
	    }
	  };
	}

/***/ },
/* 19 */
/***/ function(module, exports) {

	module.exports = "<div class=\"pc-dashboard-header hidden-xs\">{{::i18n.t('funds')}}</div>\n<div ng-if=\"!funds.loaded\" class=\"pc-dashboard-layout\">\n  <div class=\"i-fa-centered i-fa-gogenta fa fa-spinner fa-4x fa-spin\"></div>\n</div>\n<div ng-if=\"funds.loaded\" class=\"pc-dashboard-layout\">\n  <div class=\"pc-dashboard-rightRailCol pc-dashboard-rightRailCol--funds\">\n    <div life-receive-funds class=\"pc-dashboard-rightRailCol-item\"></div>\n  </div>\n  <div class=\"pc-dashboard-mainCol\">\n    <div ng-if=\"!stripePayoutActive\">\n      <div life-funds-breakdown class=\"pc-dashboard-mainCol-item\"></div>\n    </div>\n    <div ng-if=\"stripePayoutActive\">\n      <div payout-records-breakdown class=\"pc-dashboard-mainCol-item\"></div>\n    </div>\n    <div generosity-dashboard-funds-disbursement class=\"pc-dashboard-mainCol-item generosityFunds\"></div>\n    <div ng-if=\"underReview.loaded && underReview.donations.length > 0\" life-funds-under-review class=\"pc-dashboard-mainCol-item\"></div>\n  </div>\n</div>\n";

/***/ },
/* 20 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	lifeFundsUnderReviewDirective.$inject = ["i18n", "pcDashboard"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = lifeFundsUnderReviewDirective;
	/*@ngInject*/
	
	function lifeFundsUnderReviewDirective(i18n, pcDashboard) {
	  return {
	    scope: {},
	    restrict: 'A',
	    template: __webpack_require__(21),
	
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.underReview = pcDashboard.underReview;
	
	      scope.showMore = function () {
	        pcDashboard.loadMoreDonationsUnderReview();
	      };
	    }
	  };
	}

/***/ },
/* 21 */
/***/ function(module, exports) {

	module.exports = "<div class=\"pc-dashboard-section\">\n  <div class=\"pc-dashboard-section-header\">\n    <div class=\"pc-dashboard-section-title\">{{::i18n.t('generosity.dashboard.funds.funds_under_review')}}</div>\n  </div>\n  <div class=\"pc-dashboard-section-body lifeFunds-body pc-donations\">\n    <div class=\"pc-donation\" ng-repeat=\"donation in underReview.donations\">\n      <div class=\"pc-donation-image\">\n        <img class=\"pc-donation-imagePhoto\" ng-src=\"{{::donation.contributor.avatar_url}}\" />\n        <div class=\"pc-donation-imageAmt\">{{::-donation.amount|iggCurrency:donation.currency.iso_num:'noIso'}}</div>\n      </div>\n      <div class=\"pc-donation-mainCol\">\n        <div class=\"pc-donation-name\">{{::donation.contributor.name}}</div>\n        <div class=\"pc-donation-info pc-donation-email\">{{::donation.contributor.email}}</div>\n        <div class=\"pc-donation-info pc-donation-time\">{{::donation.created_at | amDateFormat:'MMM D, YYYY'}}</div>\n      </div>\n    </div>\n  </div>\n  <div ng-if=\"underReview.pagination.next\" class=\"pc-dashboard-section-footer\">\n    <a href=\"\" class=\"pc-dashboard-section-showMoreDonations\" ng-click=\"showMore()\">{{::i18n.t('show_more_caps')}}</a>\n  </div>\n</div>\n";

/***/ },
/* 22 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	lifeReceiveFundsDirective.$inject = ["i18n", "gon", "pcDashboard"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = lifeReceiveFundsDirective;
	/*@ngInject*/
	
	function lifeReceiveFundsDirective(i18n, gon, pcDashboard) {
	  return {
	    scope: {},
	    restrict: 'A',
	    template: __webpack_require__(23),
	
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.hasDonated = gon.fundraiser.donations_count > 0;
	      scope.bankInfo = pcDashboard.bankInfo;
	    }
	  };
	}

/***/ },
/* 23 */
/***/ function(module, exports) {

	module.exports = "<div class=\"pc-dashboard-section\">\n  <div class=\"pc-dashboard-section-header\">\n    <div class=\"pc-dashboard-section-title\">{{::i18n.t('generosity.dashboard.funds.receive_funds')}}</div>\n  </div>\n  <div class=\"pc-dashboard-section-body lifeFunds-body\">\n    <div ng-if=\"!hasDonated\">{{::i18n.t('generosity.dashboard.funds.bank_info_not_yet_needed_prompt')}}</div>\n    <div ng-if=\"hasDonated\">{{::i18n.t('generosity.dashboard.funds.bank_info_prompt')}}</div>\n    <div ng-if=\"hasDonated && !bankInfo.filledOut\" class=\"lifeFunds-addBankAccountArea\">\n      <a class=\"small-to-primary-cta\" ui-sref=\"funds.bank\"><span>{{::i18n.t('generosity.dashboard.funds.add_bank_account')}}</span></a>\n    </div>\n    <div ng-if=\"hasDonated && bankInfo.filledOut\" class=\"lifeFunds-bankComplete\">\n      <svg-icon icon=\"icon-icon-check\"></svg-icon>\n      <span>{{::i18n.t('generosity.dashboard.funds.bank_info_complete')}}</span>\n      <a ui-sref=\"funds.bank\">\n        <svg-icon icon=\"icon-icon-create-edit\"></svg-icon>\n        <span class=\"text\">{{::i18n.t('edit')}}</span>\n      </a>\n    </div>\n\n  </div>\n</div>\n";

/***/ },
/* 24 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	pcAutomatedFacebookUpdatesDirective.$inject = ["i18n", "$modal", "gon", "fbAutopost", "gogoEvents"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = pcAutomatedFacebookUpdatesDirective;
	/*@ngInject*/
	
	function pcAutomatedFacebookUpdatesDirective(i18n, $modal, gon, fbAutopost, gogoEvents) {
	  return {
	    template: __webpack_require__(25),
	    scope: {},
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.authorizeFacebookUrl = gon.urls.facebook_authorize_url;
	      scope.canWallPost = gon.current_account.facebook_can_wall_post;
	      scope.fbAutopost = fbAutopost;
	
	      scope.frequencyOptions = _.map([1, 2, 3, 7], function (value) {
	        return {
	          value: value,
	          title: i18n.t('generosity.dashboard.automated_updates.frequency_' + value.toString() + '.title'),
	          description: i18n.t('generosity.dashboard.automated_updates.frequency_' + value.toString() + '.description')
	        };
	      });
	
	      scope.showModal = function () {
	        fbAutopost.makeSnapshot();
	        fbAutopost.snapshot.postingActive = true;
	        $modal({
	          scope: scope,
	          template: __webpack_require__(26)
	        });
	      };
	
	      scope.turnOffAutopost = function () {
	        fbAutopost.setPostingActive(false).then(function () {
	          // TODO EVENTS: id=ooth4 fixtype=captureEvent subsystem=campaign-page name=fb_autopost_dashboard_off category-new=TBD label=TBD . review
	          gogoEvents.captureEvent('fb_autopost_dashboard_off');
	        });
	      };
	
	      scope.changeFrequency = function (freq) {
	        fbAutopost.snapshot.frequency = freq.value;
	      };
	
	      scope.frequencyText = function () {
	        var frequencyOption = _.detect(scope.frequencyOptions, function (freqOption) {
	          return freqOption.value === fbAutopost.snapshot.frequency;
	        });
	        return frequencyOption ? frequencyOption.description : '';
	      };
	
	      scope.updateAutopostFrequency = function () {
	        fbAutopost.saveSnapshot().then(function () {
	          // TODO EVENTS: id=tup1k fixtype=captureEvent subsystem=campaign-page name=dynamic category-new=TBD . dynamic name is maybe sketchy
	          gogoEvents.captureEvent('fb_autopost_dashboard_changefreq_' + fbAutopost.frequency.toString());
	        });
	      };
	    }
	  };
	}

/***/ },
/* 25 */
/***/ function(module, exports) {

	module.exports = "<div class=\"pc-dashboard-section-header\">\n  <a href=\"\" ng-click=\"showModal()\" ng-if=\"fbAutopost.postingActive\" class=\"visible-md visible-lg pc-dashboard-section-header-rtLink\">{{::i18n.t('settings')}}</a>\n  <div class=\"pc-dashboard-section-title\">{{::i18n.t('generosity.dashboard.automated_updates.automate_your_messages')}}</div>\n</div>\n<div class=\"pc-dashboard-section-body pc-automatedFacebookUpdates\">\n  <div class=\"pc-automatedFacebookUpdates-title\"><svg-icon icon=\"icon-icon-facebook\"></svg-icon><span class=\"text\">{{::i18n.t('generosity.dashboard.automated_updates.automated_facebook_updates')}}:</span></div>\n  <div class=\"pc-automatedFacebookUpdates-segmentedControl\">\n    <a href=\"\" class=\"pc-automatedFacebookUpdates-segment segmentedControl-segment\" ng-class=\"{selected: fbAutopost.postingActive}\" ng-click=\"showModal()\">{{::i18n.t('button_on')}}</a><!--\n    --><a href=\"\" class=\"pc-automatedFacebookUpdates-segment segmentedControl-segment\" ng-class=\"{selected: !fbAutopost.postingActive}\" ng-click=\"turnOffAutopost()\">{{::i18n.t('button_off')}}</a>\n  </div>\n\n  <div class=\"pc-automatedFacebookUpdates-nextPostDate\" ng-if=\"fbAutopost.postingActive && fbAutopost.nextPostDate\">\n    <div class=\"pc-automatedFacebookUpdates-nextPostDate-title\">{{::i18n.t('generosity.dashboard.automated_updates.next_post_scheduled_for')}}</div>\n    <div class=\"pc-automatedFacebookUpdates-nextPostDate-value\">{{fbAutopost.nextPostDate | amDateFormat:'dddd, MMMM D, YYYY'}}</div>\n  </div>\n</div>\n<div ng-if=\"fbAutopost.postingActive\" class=\"hidden-md hidden-lg pc-dashboard-section-footer\">\n  <a href=\"\" ng-click=\"showModal()\">{{::i18n.t('settings')}}</a>\n</div>\n";

/***/ },
/* 26 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal\">\n  <div class=\"modal-dialog lifeModal-dialog lifeModal-dialog--wider\">\n    <div class=\"modal-content lifeModal-content\">\n      <a class=\"lifeModal-close\" ng-click=\"$hide()\"><svg-icon icon=\"icon-icon-close\"></svg-icon></a>\n      <div class=\"autopostSettingsModal-section\">\n        <div class=\"lifeModal-headerText\">{{::i18n.t('generosity.dashboard.automated_updates.automated_facebook_updates')}}</div>\n        <div class=\"lifeModal-bodyText\">{{::i18n.t('generosity.dashboard.automated_updates.tight_on_time_change_settings')}}</div>\n      </div>\n\n      <div class=\"autopostSettingsModal-section autopostSettingsModal-section--body\">\n        <div class=\"autopostSettingsModal-section-message\">\n          <div class=\"compose-message\">{{::i18n.t('generosity.dashboard.automated_updates.compose_automated_message')}}</div>\n          <textarea class=\"i-text-area automated-message\" ng-model=\"fbAutopost.snapshot.automatedMessage\"\n                    maxlength=\"500\"></textarea>\n        </div>\n\n        <div class=\"autopostSettingsModal-frequency-question\">{{::i18n.t('generosity.dashboard.automated_updates.frequency_question')}}</div>\n        <span igg-popover\n              class=\"hidden-xs\">{{::i18n.t('generosity.dashboard.automated_updates.auto_post_dont_worry')}}</span>\n        <ui-select class=\"visible-xs autopostSettingsModal-frequency-dropdown frequencyDropdown\"\n                   ng-model=\"fbAutopost.snapshot.frequency\" theme=\"select2\">\n          <ui-select-match>\n            <div class=\"frequencyDropdown-title\">{{$select.selected.title}}</div>\n            <div class=\"frequencyDropdown-desc\">{{$select.selected.description}}</div>\n          </ui-select-match>\n          <ui-select-choices repeat=\"option.value as option in frequencyOptions | filter: $select.search\">\n            <div class=\"frequencyDropdown-title\">{{option.title}}</div>\n            <div class=\"frequencyDropdown-desc\">{{option.description}}</div>\n          </ui-select-choices>\n        </ui-select>\n        <div class=\"hidden-xs segmentedControl\">\n          <a class=\"segmentedControl-segment segmentedControl-segment--frequency\"\n             ng-class=\"{selected: freq.value === fbAutopost.snapshot.frequency}\"\n             href=\"\" ng-click=\"changeFrequency(freq)\" ng-repeat=\"freq in frequencyOptions\">{{::freq.title}}</a>\n        </div>\n        <div class=\"hidden-xs autopostSettingsModal-frequency-explanation\">{{frequencyText()}}</div>\n      </div>\n      <div class=\"autopostSettingsModal-section lifeModal-buttons\">\n        <a class=\"hidden-inline-xs lifeModal-button lifeModal-button--cancel\" href=\"\" ng-click=\"$hide()\">{{::i18n.t('cancel')}}</a>\n        <a href=\"{{::authorizeFacebookUrl}}\" class=\"lifeModal-button pc-cta pc-cta--facebook\"\n           ng-if=\"!canWallPost\">\n          <span>{{::i18n.t('generosity.dashboard.automated_updates.enable_automated_updates')}}</span>\n        </a>\n        <button class=\"lifeModal-button pc-cta\" ng-click=\"updateAutopostFrequency(); $hide();\" ng-if=\"canWallPost\">{{::i18n.t('save_settings')}}</button>\n        <a class=\"visible-xs lifeModal-button lifeModal-button--cancel\" href=\"\" ng-click=\"$hide()\">{{::i18n.t('cancel')}}</a>\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 27 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	pcDashboardCampaignCardDirective.$inject = ["browser", "i18n", "pcCampaign", "gon", "$filter"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = pcDashboardCampaignCardDirective;
	/*@ngInject*/
	
	function pcDashboardCampaignCardDirective(browser, i18n, pcCampaign, gon, $filter) {
	  return {
	    scope: {},
	    restrict: 'A',
	    template: __webpack_require__(28),
	    link: function link(scope) {
	      scope.browser = browser;
	      scope.i18n = i18n;
	      scope.pcCampaign = pcCampaign;
	      scope.raisedOfGoal = i18n.t("generosity.fundraiser_dashboard.raised_of_goal", { goal: pcCampaign.json().goal });
	      var donorCount = pcCampaign.json().donations_count;
	      scope.donorText = i18n.t('generosity.from_x_donors', { count: donorCount, x: $filter('number')(donorCount) });
	    }
	  };
	}

/***/ },
/* 28 */
/***/ function(module, exports) {

	module.exports = "<div class=\"baseballCard pc-dashboard-campaignCard\">\n  <a href=\"{{pcCampaign.json().url}}\"><img class=\"baseballCard-image\" ng-src=\"{{pcCampaign.json().compressed_image_url}}\" /></a>\n  <div class=\"baseballCard-title\"><a href=\"{{pcCampaign.json().url}}\">{{::pcCampaign.json().title}}</a></div>\n  <div class=\"baseballCard-amount\">{{::pcCampaign.json().balance}} <span class=\"baseballCard-donors\">{{donorText}}</span></div>\n  <div class=\"baseballCard-tags\">\n    <a href=\"{{pcCampaign.json().url}}\" class=\"baseballCard-tag tag--light\">{{::pcCampaign.json().category_name}}</a>\n    <span class=\"baseballCard-tag tag--light\">{{::pcCampaign.json().city}}</span>\n  </div>\n</div>\n";

/***/ },
/* 29 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	pcDashboardDirective.$inject = ["i18n", "$state", "pcDashboard", "pcCampaign", "gon", "browser"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = pcDashboardDirective;
	/*@ngInject*/
	
	function pcDashboardDirective(i18n, $state, pcDashboard, pcCampaign, gon, browser) {
	  return {
	    scope: {},
	    restrict: 'A',
	    template: __webpack_require__(30),
	
	    link: function link(scope) {
	      scope.i18n = i18n;
	      pcCampaign.setCampaignJson(gon.fundraiser);
	
	      scope.fundraiserUrl = gon.fundraiser.url;
	      scope.isMobile = browser.isMobile();
	      scope.hasRecentDonations = gon.fundraiser.donations && gon.fundraiser.donations.length > 0;
	      scope.fundsData = pcDashboard.fundsData;
	      pcDashboard.getFunds();
	    }
	  };
	}

/***/ },
/* 30 */
/***/ function(module, exports) {

	module.exports = "<div class=\"dashboard-tabs\">\n  <div class=\"container\">\n    <div class=\"i-float-tab-links i-float-tab-links--dashboard\">\n      <a class=\"i-tab\" ui-sref=\"manage\" ui-sref-active=\"i-selected pc-selected\">\n        <span>{{::i18n.t('manage')}}</span>\n      </a>\n      <a class=\"i-tab\" ui-sref=\"donations\" ui-sref-active=\"i-selected pc-selected\">\n        <span>{{::i18n.t('generosity.donations')}}</span>\n      </a>\n      <a class=\"i-tab\" ui-sref=\"funds\" ui-sref-active=\"i-selected pc-selected\" ng-class=\"{'acceptance-loaded': fundsData.loaded}\">\n        <span>{{::i18n.t('command_center.funds')}}</span>\n      </a>\n    </div>\n  </div>\n</div>\n\n<div class=\"pc-dashboard-background\">\n  <div class=\"container pc-dashboard-content\" ui-view>\n  </div>\n</div>\n";

/***/ },
/* 31 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	pcDashboardDonationsDirective.$inject = ["i18n", "pcDashboard", "gon"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = pcDashboardDonationsDirective;
	/*@ngInject*/
	
	function pcDashboardDonationsDirective(i18n, pcDashboard, gon) {
	  return {
	    template: __webpack_require__(32),
	    link: function link(scope) {
	      var currentShownAddress;
	
	      scope.i18n = i18n;
	      scope.offset = 4;
	      scope.csvPath = gon.urls.donations_csv_endpoint;
	      scope.donationsData = {};
	      scope.showData = false;
	      scope.pledges = [];
	
	      scope.getDonations = function (params) {
	        scope.showData = false;
	        pcDashboard.getDonations(params).then(function () {
	          scope.showData = true;
	          scope.currentPage = params.page;
	          scope.pledges = pcDashboard.donationsData.pledges;
	          scope.totalPages = pcDashboard.donationsData.totalPages;
	
	          var rangeStart = scope.currentPage > scope.offset ? scope.currentPage - scope.offset : 1;
	          var rangeEnd = scope.totalPages - scope.currentPage > scope.offset ? scope.currentPage + scope.offset : scope.totalPages;
	          scope.paginatedPages = _.range(rangeStart, rangeEnd + 1);
	        });
	      };
	
	      scope.showAddress = function (pledge_id) {
	        currentShownAddress = pledge_id;
	      };
	
	      scope.showingAddress = function (pledge_id) {
	        return currentShownAddress === pledge_id;
	      };
	
	      scope.isCurrentPage = function (page) {
	        return scope.currentPage === page;
	      };
	
	      scope.getDonations({ page: 1 });
	    }
	  };
	}

/***/ },
/* 32 */
/***/ function(module, exports) {

	module.exports = "<div class=\"pc-tab-header\">\n  <span class=\"pc-updated-at\" ng-if=\"showData\">\n    {{i18n.t('command_center.last_updated_less_than_min_ago')}}\n  </span>\n  <h3 class=\"pc-tab-header-title\">\n    {{::i18n.t('generosity.donations')}}\n  </h3>\n</div>\n\n<div class=\"pc-spinner\" ng-class=\"{'hidden' : showData}\">\n  <span class=\"fa fa-spinner fa-4x fa-spin\"></span>\n</div>\n\n<div class=\"pc-donations-container\" ng-if=\"showData\">\n  <a class=\"btn btn-default pc-btn-csv small-cta\" ng-href=\"{{csvPath}}\">\n    {{::i18n.t('command_center.generate_csv')}}\n  </a>\n\n  <table class=\"table\">\n    <thead>\n    <tr>\n      <th>{{::i18n.t('command_center.amount')}}</th>\n      <th>{{::i18n.t('command_center.donation_level')}}</th>\n      <th>{{::i18n.t('name')}}</th>\n      <th>{{::i18n.t('command_center.email')}}</th>\n      <th>{{::i18n.t('command_center.shipping_address')}}</th>\n      <th>{{::i18n.t('command_center.appearance')}}</th>\n      <th>{{::i18n.t('command_center.funding_date')}}</th>\n    </tr>\n    </thead>\n    <tbody>\n    <tr ng-repeat=\"pledge in pledges\" ng-class=\"{'showingAddress':showingAddress(pledge.id)}\">\n      <td>{{pledge.amount | iggCurrency:pledge.currency.iso_num:\"noIso\"}}</td>\n      <td>\n        <span ng-if=\"pledge.perk\">{{pledge.perk.label}}</span>\n        <span ng-if=\"!pledge.perk\">-</span>\n      </td>\n      <td>{{pledge.contributor.name}}</td>\n      <td>{{pledge.contributor.email}}</td>\n      <td class=\"shippingAddress\">\n        <div ng-if=\"pledge.order\">\n          <a href=\"\" class=\"showAddressLink\" ng-click=\"showAddress(pledge.id)\" ng-if=\"!showingAddress(pledge.id)\">{{::i18n.t('command_center.show_address')}}</a>\n          <shipping-info shipping=\"pledge.order.shipping\" ng-if=\"showingAddress(pledge.id)\"></shipping-info>\n        </div>\n        <span ng-if=\"!pledge.order\">-</span>\n      </td>\n      <td>{{i18n.t(pledge.appearance)}}</td>\n      <td>{{pledge.created_at | amDateFormat:'D-MMM-YYYY'}}</td>\n    </tr>\n    </tbody>\n  </table>\n</div>\n\n<div class=\"pc-pagination\" ng-if=\"showData\">\n  <ul class=\"pc-pagination-links\">\n    <li ng-if=\"currentPage !== 1\">\n      <a href=\"\" ng-click=\"getDonations({page: 1})\">{{i18n.t('first')}}</a>\n    </li>\n\n    <li ng-if=\"currentPage !== 1\">\n      <a href=\"\" ng-click=\"getDonations({page: (currentPage - 1)})\">{{i18n.t('previous')}}</a>\n    </li>\n\n    <li ng-if=\"currentPage > offset + 1\">...</li>\n\n    <li ng-repeat=\"page in paginatedPages\">\n      <a href=\"\" id=\"page-{{page}}-link\" ng-click=\"getDonations({page: page})\"\n         ng-class=\"{'pc-selected-page' : isCurrentPage(page)}\">{{page}}</a>\n    </li>\n\n    <li ng-if=\"totalPages - offset > currentPage\">...</li>\n\n    <li ng-if=\"currentPage !== totalPages\">\n      <a href=\"\" ng-click=\"getDonations({page: (currentPage + 1)})\">{{i18n.t('next')}}</a>\n    </li>\n\n    <li ng-if=\"currentPage !== totalPages\">\n      <a href=\"\" ng-click=\"getDonations({page: totalPages})\">{{i18n.t('last')}}</a>\n    </li>\n  </ul>\n</div>\n";

/***/ },
/* 33 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	pcDashboardEndFundraiserDirective.$inject = ["i18n", "pcCampaign", "$modal", "$http", "gon", "flash", "pcDashboard"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = pcDashboardEndFundraiserDirective;
	/*@ngInject*/
	
	function pcDashboardEndFundraiserDirective(i18n, pcCampaign, $modal, $http, gon, flash, pcDashboard) {
	  var endFundraiserModal, removeDeadlineModal;
	
	  return {
	    template: __webpack_require__(34),
	    scope: {},
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.fundingStartedAt = i18n.t('generosity.dashboard.started_on_html', {
	        date: pcCampaign.json().start_date
	      });
	
	      scope.showAnswer = false;
	      scope.hasDeadline = pcCampaign.hasDeadline();
	      scope.endsOn = i18n.t('generosity.dashboard.ends_on_html', {
	        date: pcCampaign.json().end_date
	      });
	
	      scope.hasEnded = pcCampaign.json().has_ended;
	      if (scope.hasEnded) {
	        scope.endDate = i18n.t('generosity.dashboard.ended_on_html', {
	          date: pcCampaign.json().end_date
	        });
	      }
	
	      scope.endFundraiser = function () {
	        $http.post(gon.urls.end_fundraiser).then(function (response) {
	          scope.hasEnded = true;
	          scope.endDate = i18n.t('generosity.dashboard.ended_on_html', {
	            date: response.data.end_date
	          });
	          pcDashboard.pillState = response.data.pill_state;
	          pcDashboard.getDisbursements();
	          flash.addMessage('notice', i18n.t('generosity.dashboard.successfully_ended'));
	          endFundraiserModal.hide();
	        });
	      };
	
	      scope.removeDeadline = function () {
	        $http.post(gon.urls.remove_deadline).then(function () {
	          scope.hasDeadline = false;
	          pcDashboard.getDisbursements();
	          flash.addMessage('notice', i18n.t('generosity.dashboard.deadline_removed'));
	          removeDeadlineModal.hide();
	        });
	      };
	
	      scope.showEndFundraiserModal = function () {
	        endFundraiserModal = $modal({
	          template: __webpack_require__(35),
	          scope: scope
	        });
	      };
	
	      scope.showRemoveDeadlineModal = function () {
	        removeDeadlineModal = $modal({
	          template: __webpack_require__(36),
	          scope: scope
	        });
	      };
	    }
	  };
	}

/***/ },
/* 34 */
/***/ function(module, exports) {

	module.exports = "<div ng-if=\"!hasDeadline\">\n  <div ng-if=\"!hasEnded\">\n    <span ng-bind-html=\"fundingStartedAt\"></span>\n    <a href=\"\" class=\"pc-endFundraiser-link\" ng-click=\"showEndFundraiserModal()\">{{::i18n.t('generosity.dashboard.end_fundraiser')}}</a>\n  </div>\n\n  <div ng-if=\"hasEnded\" ng-bind-html=\"endDate\"></div>\n</div>\n\n<div ng-if=\"hasDeadline\">\n  <div ng-if=\"!hasEnded\">\n    <span ng-bind-html=\"endsOn\"></span>\n    <a href=\"\" class=\"pc-removeDeadline-link\" ng-click=\"showRemoveDeadlineModal()\">{{::i18n.t('generosity.dashboard.remove_deadline')}}</a>\n  </div>\n\n  <div ng-if=\"hasEnded\" ng-bind-html=\"endDate\"></div>\n</div>\n";

/***/ },
/* 35 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal\">\n  <div class=\"modal-dialog lifeModal-dialog\">\n    <div class=\"modal-content lifeModal-content lifeModal-content--shady\">\n      <a class=\"lifeModal-close\" ng-click=\"$hide()\"><svg-icon icon=\"icon-icon-close\"></svg-icon></a>\n      <div class=\"lifeModal-container\">\n        <div class=\"lifeModal-headerText\">{{::i18n.t('generosity.dashboard.end_fundraiser_modal.title')}}</div>\n        <div class=\"lifeModal-bodyText\">{{::i18n.t('generosity.dashboard.end_fundraiser_modal.explanation')}}</div>\n\n        <div class=\"lifeModal-buttons hidden-xs\">\n          <a href=\"\" class=\"lifeModal-button lifeModal-button--cancel\" ng-click=\"$hide()\">{{::i18n.t('cancel')}}</a>\n          <a href=\"\" class=\"pc-cta lifeModal-button\" ng-click=\"endFundraiser()\">{{::i18n.t('generosity.dashboard.end_fundraiser')}}</a>\n        </div>\n\n        <div class=\"lifeModal-buttons visible-xs\">\n          <a href=\"\" class=\"pc-cta lifeModal-button\" ng-click=\"endFundraiser()\">{{::i18n.t('generosity.dashboard.end_fundraiser')}}</a>\n          <a href=\"\" class=\"lifeModal-button lifeModal-button--cancel\" ng-click=\"$hide()\">{{::i18n.t('cancel')}}</a>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 36 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal\">\n  <div class=\"modal-dialog lifeModal-dialog\">\n    <div class=\"modal-content lifeModal-content lifeModal-content--shady\">\n      <a class=\"lifeModal-close\" ng-click=\"$hide()\"><svg-icon icon=\"icon-icon-close\"></svg-icon></a>\n      <div class=\"lifeModal-container\">\n        <div class=\"lifeModal-headerText\">{{::i18n.t('generosity.dashboard.remove_deadline_modal.title')}}</div>\n        <div class=\"lifeModal-bodyText\">{{::i18n.t('generosity.dashboard.remove_deadline_modal.explanation')}}</div>\n\n        <div class=\"pc-removeDeadline-funds-question\" ng-click=\"showAnswer = !showAnswer\">\n          <svg-icon icon=\"down-caret\" class=\"pc-remove-fundraiser-dropArrow\" ng-class=\"{'show-answer' : showAnswer}\"></svg-icon>\n          <span class=\"pc-removeDeadline-question-text\">{{::i18n.t('generosity.dashboard.remove_deadline_modal.funds_question')}}</span>\n        </div>\n\n        <div class=\"pc-removeDeadline-funds-answer\" ng-if=\"showAnswer\">\n          {{::i18n.t('generosity.dashboard.remove_deadline_modal.funds_answer')}}\n        </div>\n\n\n        <div class=\"lifeModal-buttons hidden-xs\">\n          <a href=\"\" class=\"lifeModal-button lifeModal-button--cancel\" ng-click=\"$hide()\">{{::i18n.t('cancel')}}</a>\n          <a href=\"\" class=\"pc-cta lifeModal-button\" ng-click=\"removeDeadline()\">{{::i18n.t('generosity.dashboard.remove_deadline')}}</a>\n        </div>\n\n        <div class=\"lifeModal-buttons visible-xs\">\n          <a href=\"\" class=\"pc-cta lifeModal-button\" ng-click=\"removeDeadline()\">{{::i18n.t('generosity.dashboard.remove_deadline')}}</a>\n          <a href=\"\" class=\"lifeModal-button lifeModal-button--cancel\" ng-click=\"$hide()\">{{::i18n.t('cancel')}}</a>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 37 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	pcDashboardFundraiserLinkDirective.$inject = ["i18n", "pcDashboard", "browser"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = pcDashboardFundraiserLinkDirective;
	/*@ngInject*/
	
	function pcDashboardFundraiserLinkDirective(i18n, pcDashboard, browser) {
	  return {
	    template: __webpack_require__(38),
	    scope: {
	      title: '@'
	    },
	    link: function link(scope, element) {
	      scope.i18n = i18n;
	      scope.projectUrl = pcDashboard.urls.fundraiser_short_link_url;
	      scope.selectUrl = function () {
	        element.find('input').select();
	      };
	    }
	  };
	}

/***/ },
/* 38 */
/***/ function(module, exports) {

	module.exports = "<div class=\"pc-dashboard-fundraiserLink-title\">{{title}}</div>\n<div class=\"pc-dashboard-fundraiserLink-content\" ng-click=\"selectUrl()\">\n  <span class=\"pc-dashboard-fundraiserLink-icon\"><svg-icon icon=\"icon-icon-link\"></svg-icon></span><!--\n  --><input type=\"text\" readonly value=\"{{projectUrl}}\"/>\n</div>\n";

/***/ },
/* 39 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	pcDashboardMobileFundraiserLinkDirective.$inject = ["i18n", "pcDashboard", "$modal", "gon"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = pcDashboardMobileFundraiserLinkDirective;
	/*@ngInject*/
	
	function pcDashboardMobileFundraiserLinkDirective(i18n, pcDashboard, $modal, gon) {
	  return {
	    template: __webpack_require__(40),
	    link: function link(scope) {
	      scope.projectUrl = pcDashboard.urls.fundraiser_short_link_url;
	      scope.openModal = function () {
	        $modal({
	          template: __webpack_require__(41),
	          scope: scope
	        });
	      };
	    }
	  };
	}

/***/ },
/* 40 */
/***/ function(module, exports) {

	module.exports = "<div class=\"pc-mobile-fundraiserLink-content pc-dashboard-section-title\">\n  <div>Share URL</div>\n  <a href=\"\" class=\"ghost-cta--light\" ng-click=\"openModal()\">Copy Fundraiser Link</a>\n</div>\n";

/***/ },
/* 41 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal\">\n  <div class=\"modal-dialog lifeModal-dialog\">\n    <div class=\"modal-content lifeModal-content lifeModal-content--shady\">\n      <a class=\"lifeModal-close\" ng-click=\"$hide()\"><svg-icon icon=\"icon-icon-close\"></svg-icon></a>\n      <div class=\"lifeModal-container\">\n        <div class=\"lifeModal-headerText\">Share Your Fundraiser</div>\n        <div class=\"pc-dashboard-fundraiserLink-content\">\n          <a ng-href=\"{{projectUrl}}\" target=\"_blank\" ng-click=\"$event.preventDefault()\">\n            <span class=\"pc-dashboard-fundraiserLink-icon\"><svg-icon icon=\"icon-icon-link\"></svg-icon></span><!--\n         --><input type=\"text\" disabled value=\"{{projectUrl}}\"/>\n          </a>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 42 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	pcDashboardPostUpdateDirective.$inject = ["pcDashboard", "i18n", "$http", "gon", "flash", "browser", "localStorageService", "stripTags"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = pcDashboardPostUpdateDirective;
	/*@ngInject*/
	
	function pcDashboardPostUpdateDirective(pcDashboard, i18n, $http, gon, flash, browser, localStorageService, stripTags) {
	  return {
	    scope: {},
	    template: __webpack_require__(43),
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.showSpinner = false;
	      scope.postToFacebook = gon.current_account.facebook_can_wall_post;
	
	      var updateBody = localStorageService.get('campaignUpdate');
	
	      if (updateBody) {
	        scope.editMode = true;
	        scope.newUpdate = {
	          bodyHtml: localStorageService.get('campaignUpdate')
	        };
	        localStorageService.remove('campaignUpdate');
	      } else {
	        scope.editMode = false;
	        scope.newUpdate = {
	          bodyHtml: ''
	        };
	      }
	
	      scope.connectToFacebook = function () {
	        if (gon.current_account.facebook_can_wall_post) {
	          return true;
	        } else {
	          localStorageService.set('campaignUpdate', scope.newUpdate.bodyHtml);
	          browser.redirectTo(gon.urls.facebook_authorize_url);
	          return false;
	        }
	      };
	
	      scope.serverError = null;
	      scope.needHelpUrl = gon.urls.help_url;
	      var MIN_UPDATE_LENGTH = 2;
	      scope.MAX_UPDATE_LENGTH = 1500;
	
	      scope.$watch('newUpdate.bodyHtml', function (newVal, oldVal) {
	        var stripped = stripTags(newVal);
	        scope.ckeditorPostDisabled = stripped.length > scope.MAX_UPDATE_LENGTH || stripped.length < MIN_UPDATE_LENGTH;
	        scope.ckeditorTooLong = stripped.length > scope.MAX_UPDATE_LENGTH;
	        scope.serverError = null;
	      });
	
	      scope.showEditor = function () {
	        scope.editMode = true;
	      };
	
	      scope.postUpdate = function () {
	        scope.showSpinner = true;
	        $http.post(gon.urls.fundraiser_new_update, {
	          body_html: scope.newUpdate.bodyHtml,
	          post_to_facebook: scope.postToFacebook
	        }).then(function onSuccess() {
	          scope.showSpinner = false;
	          scope.$broadcast('postUpdateFinished');
	          flash.addMessage('notice', 'Update posted successfully.');
	        }, function onError(response) {
	          scope.showSpinner = false;
	          scope.serverError = response.data.error;
	        });
	      };
	    }
	  };
	}

/***/ },
/* 43 */
/***/ function(module, exports) {

	module.exports = "<div class=\"pc-dashboard-section-header\">\n  <div class=\"pc-dashboard-section-title\">{{::i18n.t(\"generosity.dashboard.post_an_update\")}}</div>\n</div>\n<div class=\"postUpdate-body\">\n  <div class=\"postUpdate-placeholder i-text-field\" ng-click=\"showEditor()\" ng-if=\"!editMode\">{{::i18n.t(\"generosity.dashboard.whats_new\")}}</div>\n  <textarea ckeditor id=\"postUpdateInput\" ng-if=\"editMode\" ng-model=\"newUpdate.bodyHtml\"></textarea>\n  <div class=\"postUpdate-error\" ng-if=\"ckeditorTooLong\">{{::i18n.t(\"generosity.dashboard.updates_must_be_less_than\")}}</div>\n  <div class=\"postUpdate-error\" ng-if=\"serverError\">{{serverError}}</div>\n\n  <div class=\"postUpdate-xpost\">\n    <span>{{::i18n.t(\"generosity.dashboard.also_post_to\")}}</span>\n    <label ng-click=\"connectToFacebook()\" class=\"postUpdate-xpost-facebook\">\n      <input type=\"checkbox\"\n             name=\"postToFacebook\"\n             id=\"postToFacebook\"\n             ng-model=\"postToFacebook\">\n      {{::i18n.t(\"facebook\")}}\n    </label>\n  </div>\n\n  <div class=\"postUpdate-bottomRow\">\n    <button class=\"i-cta-1 postUpdate-cta\" ng-click=\"postUpdate()\" ng-disabled=\"ckeditorPostDisabled\">\n      <span ng-if=\"showSpinner\" class=\"fa fa-spinner fa-spin\"></span>\n      <span ng-if=\"!showSpinner\">{{::i18n.t('generosity.dashboard.post_an_update')}}</span>\n    </button>\n    <div class=\"postUpdate-descriptionCol\">\n      <span class=\"postUpdate-descriptionCol-text visible-md visible-lg\">{{::i18n.t(\"generosity.dashboard.regular_updates\")}}</span>\n      <a class=\"postUpdate-descriptionCol-url\" ng-href=\"{{needHelpUrl}}\" target=\"_blank\">{{::i18n.t(\"generosity.dashboard.need_help\")}}</a>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 44 */
/***/ function(module, exports) {

	'use strict';
	
	pcDashboardService.$inject = ["$http", "$sce", "gon", "payoutRecords"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = pcDashboardService;
	/*@ngInject*/
	
	function pcDashboardService($http, $sce, gon, payoutRecords) {
	  var dashboard = {
	    fundsData: {
	      loaded: false
	    },
	    underReview: {
	      loaded: false
	    },
	    donationsData: {},
	    pillState: null,
	    urls: gon.urls
	  };
	
	  dashboard.getFunds = function () {
	    if (gon.fundraiser.stripe_payout_active) {
	      return payoutRecords.getPayoutRecords().then(function (response) {
	        dashboard.fundsData.loaded = true;
	        payoutRecords.funds = response.funds;
	        payoutRecords.payout_records = response.payout_records;
	      });
	    } else {
	      return $http.get(dashboard.urls.funds_endpoint).success(function (response) {
	        dashboard.fundsData.loaded = true;
	        dashboard.fundsData.date = response.date;
	        dashboard.fundsData.funds = response.funds;
	        _.each(dashboard.fundsData.funds, function (fund) {
	          fund.destination = $sce.trustAsHtml(fund.destination);
	          fund.description = $sce.trustAsHtml(fund.description);
	        });
	      });
	    }
	  };
	
	  function loadDonationsUnderReview(pagingOptions) {
	    var params = { filter_pledge_status: 'on_hold', page: pagingOptions.page, per_page: pagingOptions.per_page };
	    return $http.get(dashboard.urls.donations_endpoint, { params: params }).success(function (response) {
	      dashboard.underReview.loaded = true;
	      dashboard.underReview.pagination = response.pagination;
	    });
	  }
	
	  dashboard.getDonationsUnderReview = function (pagingOptions) {
	    return loadDonationsUnderReview(pagingOptions).then(function (response) {
	      dashboard.underReview.donations = response.data.response;
	    });
	  };
	
	  dashboard.loadMoreDonationsUnderReview = function () {
	    var pagination = dashboard.underReview.pagination;
	    return loadDonationsUnderReview({ page: pagination.next, per_page: pagination.per_page }).then(function (response) {
	      response.data.response.forEach(function (donation) {
	        dashboard.underReview.donations.push(donation);
	      });
	    });
	  };
	
	  dashboard.getDonations = function (params) {
	    var defaultParams = { page: 1, per_page: 20 };
	    params = params ? _.merge(defaultParams, params) : defaultParams;
	
	    return $http.get(dashboard.urls.donations_endpoint, { params: params }).success(function (response) {
	      dashboard.donationsData.pledges = response.response;
	      dashboard.donationsData.totalPages = response.pagination.pages;
	    });
	  };
	
	  dashboard.disbursements = { loaded: false };
	  dashboard.getDisbursements = function () {
	    $http.get(gon.urls.disbursement_history_endpoint).then(function (response) {
	      dashboard.disbursements.loaded = true;
	      _.merge(dashboard.disbursements, response.data);
	    });
	  };
	
	  dashboard.bankInfo = { loaded: false,
	    filledOut: gon.fundraiser && gon.fundraiser.has_required_disbursement_attributes };
	  dashboard.getBankInfo = function () {
	    return $http.get(gon.urls.update_bank_info).then(function (response) {
	      dashboard.bankInfo.loaded = true;
	      dashboard.bankInfo.bankCampaign = response.data;
	    });
	  };
	
	  return dashboard;
	}

/***/ },
/* 45 */
/***/ function(module, exports) {

	'use strict';
	
	pcManagementBarDirective.$inject = ["i18n", "pcDashboard"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = pcManagementBarDirective;
	/*@ngInject*/
	
	function pcManagementBarDirective(i18n, pcDashboard) {
	  return {
	    scope: {},
	    link: function link(scope, element) {
	      var pill = element.find('.i-annotation-pill');
	      scope.pcDashboard = pcDashboard;
	      scope.$watch('pcDashboard.pillState', function (newVal, oldVal) {
	        if (!_.isUndefined(newVal) && !_.isNull(newVal)) {
	          pill.attr('class', 'i-annotation-pill ' + newVal.pill_class);
	          pill.attr('title', newVal.body_text);
	          pill.text(newVal.pill_text);
	        }
	      });
	    }
	  };
	}

/***/ },
/* 46 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	pcRecentDonationsDirective.$inject = ["gon", "i18n", "$sce"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = pcRecentDonationsDirective;
	/*@ngInject*/
	
	function pcRecentDonationsDirective(gon, i18n, $sce) {
	  return {
	    template: __webpack_require__(47),
	    scope: {},
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.recentDonations = _.take(gon.fundraiser.donations, 5);
	      scope.donationAmountHtml = function (donationAmount) {
	        return $sce.trustAsHtml(i18n.t('generosity.fundraiser_dashboard.donated_amount', { amount: '<strong>' + donationAmount + '</strong>' }));
	      };
	    }
	  };
	}

/***/ },
/* 47 */
/***/ function(module, exports) {

	module.exports = "<div class=\"pc-dashboard-section-header\">\n  <div class=\"pc-dashboard-section-title\">{{::i18n.t('generosity.fundraiser_dashboard.recent_donations')}}</div>\n</div>\n<div class=\"pc-dashboard-section-body pc-donations\">\n  <div class=\"pc-donation\" ng-repeat=\"donation in recentDonations\">\n    <div class=\"pc-donation-image\">\n      <img class=\"pc-donation-imagePhoto\" ng-src=\"{{donation.photo_url}}\" ng-if=\"donation.photo_url\" />\n      <span class=\"pc-donation-imagePhoto missingAvatar\" ng-if=\"!donation.photo_url\"></span>\n      <div class=\"pc-donation-imageAmt\">{{donation.amount}}</div>\n    </div>\n    <div class=\"pc-donation-mainCol pc-donation-mainCol--recent\">\n      <div class=\"pc-donation-name\">{{donation.name}}</div>\n      <div class=\"pc-donation-amount\" ng-bind-html=\"donationAmountHtml(donation.amount)\"></div>\n      <div class=\"pc-donation-info pc-donation-time\">{{donation.timestamp}}</div>\n      <div class=\"pc-donation-comment\" ng-if=\"donation.comment\">{{donation.comment}}</div>\n    </div>\n  </div>\n</div>\n<div class=\"pc-dashboard-section-footer\">\n  <a href=\"\" class=\"view-donations\" ui-sref=\"donations\">{{::i18n.t('generosity.fundraiser_dashboard.view_complete_donation_list')}}</a>\n</div>\n";

/***/ },
/* 48 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	pcTodoItemsDirective.$inject = ["i18n", "pcDashboard", "fb", "gon", "todoItems", "twitter", "gogoEvents", "$modal", "fbAutopost", "$http"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = pcTodoItemsDirective;
	/*@ngInject*/
	
	function pcTodoItemsDirective(i18n, pcDashboard, fb, gon, todoItems, twitter, gogoEvents, $modal, fbAutopost, $http) {
	  var offlineFundraiserModal;
	
	  return {
	    scope: {},
	    template: __webpack_require__(49),
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.urls = pcDashboard.urls;
	      scope.todoItems = todoItems.get();
	      scope.showTips = false;
	      scope.relevantHashtagHtml = i18n.t('generosity.fundraiser_dashboard.use_a_relevant_hashtag_html', { learn_how_url: scope.urls.help_url });
	      scope.showPromotionProgramTodoItem = gon.show_promotion_program_todo_item;
	      scope.offlineFundraiserItems = ['hold_an_event', 'raise_awareness', 'share_with_press'];
	
	      scope.toggleShowTips = function () {
	        scope.showTips = !scope.showTips;
	      };
	
	      scope.clickFacebook = function () {
	        var options = gon.current_account ? { account_id: gon.current_account.account_id } : {};
	        fb.share(pcDashboard.urls.fundraiser_url, options).then(function () {
	          todoItems.markCompleted('facebook_share');
	          // TODO EVENTS: id=eeb8e fixtype=captureEvent name=complete_facebook_todo_item category-new=TBD subsystem=generosity-todo . review
	          gogoEvents.captureEvent('complete_facebook_todo_item');
	          if (gon.urls.schedule_next_post_date_url) {
	            $http.put(gon.urls.schedule_next_post_date_url).then(function (response) {
	              fbAutopost.nextPostDate = response.data.next_post_date;
	            });
	          }
	        });
	      };
	
	      scope.completeEmailItemCallback = function () {
	        todoItems.markCompleted('email_share');
	        // TODO EVENTS: id=ohah6 fixtype=captureEvent name=complete_email_todo_item category-new=TBD subsystem=generosity-todo . review
	        gogoEvents.captureEvent('complete_email_todo_item');
	      };
	
	      scope.completePromotionProgramCallback = function () {
	        todoItems.markCompleted('promotion_program');
	        // TODO EVENTS: id=sei4e  fixtype=captureEvent name=dashboard_promotional_program category-new=TBD subsystem=generosity-todo . review
	        gogoEvents.captureEvent('dashboard_promotional_program');
	      };
	
	      scope.clickOfflineFundraiser = function () {
	        todoItems.markCompleted('offline_fundraiser');
	        // TODO EVENTS: id=vae5s fixtype=captureEvent name=dashboard_offline_fundraiser category-new=TBD subsystem=generosity-todo . review
	        gogoEvents.captureEvent('dashboard_offline_fundraiser');
	        offlineFundraiserModal = $modal({
	          template: __webpack_require__(50),
	          scope: scope
	        });
	      };
	
	      twitter.onTweet(function () {
	        todoItems.markCompleted('twitter_share');
	        // TODO EVENTS: id=bun5t fixtype=captureEvent name=complete_twitter_todo_item category-new=TBD subsystem=generosity-todo . review
	        gogoEvents.captureEvent('complete_twitter_todo_item');
	      });
	    }
	  };
	}

/***/ },
/* 49 */
/***/ function(module, exports) {

	module.exports = "<div class=\"pc-dashboard-section-header pc-dashboard-todoItems-header\">\n  <a href=\"{{urls.help_url}}\" target=\"_new\" class=\"visible-md visible-lg pc-dashboard-section-header-rtLink\">{{::i18n.t('generosity.fundraiser_dashboard.how_often_should_i_post')}}</a>\n  <div class=\"pc-dashboard-section-title pc-dashboard-todoItems-header-title\">{{::i18n.t('generosity.fundraiser_dashboard.promote_your_fundraiser')}}</div>\n</div>\n\n<div class=\"pc-dashboard-section-body pc-dashboard-todoItems-body\">\n  <div class=\"pc-dashboard-todoItem pc-dashboard-fb-todoItem\">\n    <todo-item-status-icon status=\"todoItems.facebook_share\"></todo-item-status-icon>\n    <div class=\"pc-dashboard-todoItem-content\">\n      <div class=\"pc-dashboard-todoItem-lastCompleted\">{{todoItems.facebook_share.lastCompletedText}}</div>\n      <div class=\"pc-dashboard-todoItem-title\">{{::i18n.t('generosity.fundraiser_dashboard.post_on_facebook')}}</div>\n      <div class=\"pc-dashboard-todoItem-description\">{{::i18n.t('generosity.fundraiser_dashboard.fundraisers_shared_on_facebook')}}</div>\n    </div>\n    <!-- TODO EVENTS: id=ooqu1 fixtype=event-dir name=click_facebook_todo_item vars=tags subsystem=generosity-todo trigger=click dom=button category-new=TBD action-new=TBD . review -->\n    <button class=\"pc-cta pc-cta--todoItem pc-cta--facebook pc-dashboard-todoItem-cta\" ng-click=\"clickFacebook()\" event-on=\"click\" event-name=\"click_facebook_todo_item\" event-tags=\"{{eventTags()}}\">\n      <svg-icon icon=\"icon-icon-facebook\"></svg-icon>\n      <span class=\"text\">{{::i18n.t('post')}}</span>\n    </button>\n  </div>\n\n  <div class=\"pc-dashboard-todoItem pc-dashboard-twitter-todoItem\">\n    <todo-item-status-icon status=\"todoItems.twitter_share\"></todo-item-status-icon>\n    <div class=\"pc-dashboard-todoItem-content\">\n      <div class=\"pc-dashboard-todoItem-lastCompleted\">{{todoItems.twitter_share.lastCompletedText}}</div>\n      <div class=\"pc-dashboard-todoItem-title\">{{::i18n.t('generosity.fundraiser_dashboard.share_on_twitter')}}</div>\n      <div class=\"pc-dashboard-todoItem-description\" ng-bind-html=\"relevantHashtagHtml\"></div>\n    <!-- TODO EVENTS: id=ooqu2 fixtype=event-dir name=click_twitter_todo_item vars=tags subsystem=generosity-todo trigger=click dom=a category-new=TBD action-new=TBD . review -->\n      <a class=\"pc-cta pc-cta--todoItem pc-cta--twitter pc-dashboard-todoItem-cta\" ng-href=\"{{urls.twitter_share_url}}\" event-on=\"click\" event-name=\"click_twitter_todo_item\" event-tags=\"{{eventTags()}}\">\n        <svg-icon icon=\"icon-icon-twitter\"></svg-icon>\n        <span class=\"text\">{{::i18n.t('share')}}</span>\n      </a>\n    </div>\n  </div>\n\n  <div class=\"pc-dashboard-todoItem pc-dashboard-email-todoItem\">\n    <todo-item-status-icon status=\"todoItems.email_share\"></todo-item-status-icon>\n    <div class=\"pc-dashboard-todoItem-content\">\n      <div class=\"pc-dashboard-todoItem-lastCompleted\">{{todoItems.email_share.lastCompletedText}}</div>\n      <div class=\"pc-dashboard-todoItem-title\">{{::i18n.t('generosity.fundraiser_dashboard.send_personal_messages')}}</div>\n      <div class=\"pc-dashboard-todoItem-description\">{{::i18n.t('generosity.fundraiser_dashboard.ask_close_friends_and_family')}}</div>\n    </div>\n    <!-- TODO EVENTS: id=ooqu3 fixtype=event-dir name=click_mobile_email_todo_item subsystem=generosity-todo vars=tags trigger=click dom=a category-new=TBD . review -->\n    <a href=\"{{urls.email_share_url}}\" ng-click=\"completeEmailItemCallback()\" target=\"_blank\" class=\"pc-cta pc-cta--todoItem pc-cta--email pc-dashboard-todoItem-cta visible-xs\"\n       event-on=\"click\" event-name=\"click_mobile_email_todo_item\" event-tags=\"{{eventTags()}}\">\n      <svg-icon icon=\"icon-icon-mail\"></svg-icon>\n      <span class=\"text\">{{::i18n.t('email')}}</span>\n    </a>\n    <span class=\"hidden-xs\" email-importer email-from=\"from_owner\" post-email-callback=\"completeEmailItemCallback()\">\n      <!-- TODO EVENTS: id=ooqu4 fixtype=event-dir name=click_email_todo_item subsystem=generosity-todo vars=tags trigger=click dom=button category-new=TBD . review -->\n      <button class=\"pc-cta pc-cta--todoItem pc-cta--email pc-dashboard-todoItem-cta\" href=\"\"\n        event-on=\"click\" event-name=\"click_email_todo_item\" event-tags=\"{{eventTags()}}\">\n        <svg-icon icon=\"icon-icon-mail\"></svg-icon>\n        <span class=\"text\">{{::i18n.t('email')}}</span>\n      </button>\n    </span>\n  </div>\n\n  <div class=\"pc-dashboard-todoItems-additionalTips hidden-xs\" ng-if=\"showTips\">\n    <div class=\"pc-dashboard-todoItem pc-dashboard-promotionProgram-todoItem\" ng-if=\"showPromotionProgramTodoItem\">\n      <todo-item-status-icon status=\"todoItems.promotion_program\"></todo-item-status-icon>\n      <div class=\"pc-dashboard-todoItem-content\">\n        <div class=\"pc-dashboard-todoItem-title\">{{::i18n.t('generosity.fundraiser_dashboard.join_promotion_program')}}</div>\n        <div class=\"pc-dashboard-todoItem-description\">{{::i18n.t('generosity.fundraiser_dashboard.share_for_promotional_opportunities')}}</div>\n        <a class=\"pc-cta--todoItem pc-dashboard-todoItem-cta pc-cta--additionalItem ghost-cta--light\"\n          ng-click=\"completePromotionProgramCallback()\"\n          ng-href=\"{{urls.promotion_program_url}}\"\n          target=\"_blank\">\n          <span class=\"text\">{{::i18n.t('join')}}</span>\n        </a>\n      </div>\n    </div>\n  </div>\n\n  <div class=\"pc-dashboard-todoItems-additionalTips hidden-xs\" ng-if=\"showTips\">\n    <div class=\"pc-dashboard-todoItem pc-dashboard-offlineFundraiser-todoItem\">\n      <todo-item-status-icon status=\"todoItems.offline_fundraiser\"></todo-item-status-icon>\n      <div class=\"pc-dashboard-todoItem-content\">\n        <div class=\"pc-dashboard-todoItem-title\">{{::i18n.t('generosity.fundraiser_dashboard.run_an_offline_fundraiser')}}</div>\n        <div class=\"pc-dashboard-todoItem-description\">{{::i18n.t('generosity.fundraiser_dashboard.raise_more_funds_offline')}}</div>\n        <a class=\"pc-cta--todoItem pc-dashboard-todoItem-cta pc-cta--additionalItem ghost-cta--light\"\n          ng-click=\"clickOfflineFundraiser()\">\n          <span class=\"text\">{{::i18n.t('learn_how')}}</span>\n        </a>\n      </div>\n    </div>\n  </div>\n</div>\n\n<div class=\"pc-dashboard-section-showTips hidden-xs\">\n  <a href=\"\" ng-click=\"toggleShowTips()\">{{showTips ? i18n.t('generosity.fundraiser_dashboard.hide_tips') : i18n.t('generosity.fundraiser_dashboard.show_tips')}}</a>\n</div>\n<div pc-dashboard-mobile-fundraiser-link class=\"visible-xs pc-dashboard-section-body pc-dashboard-mobile-fundraiserLink\"></div>\n";

/***/ },
/* 50 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal\">\n  <div class=\"modal-dialog lifeModal-dialog lifeModal-dialog--wider\">\n    <div class=\"modal-content lifeModal-content\">\n      <a class=\"lifeModal-close\" ng-click=\"$hide()\"><svg-icon icon=\"icon-icon-close\"></svg-icon></a>\n      <div class=\"lifeModal-illusHeader\">\n        <span class=\"hidden-xs lifeModal-illusHeader-svg\">\n          <svg-icon icon=\"icon-icon-megaphone\"></svg-icon>\n        </span>\n        <div class=\"lifeModal-illusHeader-content\">\n          <div class=\"lifeModal-headerText\">{{::i18n.t('generosity.fundraiser_dashboard.offline_fundraiser_modal.header')}}</div>\n          <div class=\"lifeModal-bodyText\">{{::i18n.t('generosity.fundraiser_dashboard.offline_fundraiser_modal.spreading_the_word')}}</div>\n        </div>\n      </div>\n      <div class=\"lifeModal-illusOptions\">\n        <div class=\"lifeModal-bodyText lifeModal-options-item\">{{::i18n.t('generosity.fundraiser_dashboard.offline_fundraiser_modal.some_ideas')}}</div>\n        <div class=\"lifeModal-options-item\" ng-repeat=\"item in offlineFundraiserItems\">\n          <div class=\"lifeModal-options-content\">\n            <div class=\"lifeModal-bodyHeading\">{{::i18n.t('generosity.fundraiser_dashboard.offline_fundraiser_modal.' + item)}}</div>\n            <div class=\"lifeModal-bodyText\">{{::i18n.t('generosity.fundraiser_dashboard.offline_fundraiser_modal.' + item + '_explanation')}}</div>\n          </div>\n          <svg-icon icon=\"icon-icon-check\" class=\"lifeModal-options-check\"></svg-icon>\n        </div>\n      </div>\n      <div class=\"lifeModal-illusFooter\">\n        <div class=\"lifeModal-buttons\">\n          <a class=\"primary-cta lifeModal-button\" ng-click=\"$hide()\">{{::i18n.t('generosity.fundraiser_dashboard.offline_fundraiser_modal.got_it')}}</a>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 51 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	pcVisitStatsDirective.$inject = ["i18n", "gon", "$filter", "browser"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = pcVisitStatsDirective;
	/*@ngInject*/
	
	function pcVisitStatsDirective(i18n, gon, $filter, browser) {
	  return {
	    scope: {},
	    template: __webpack_require__(52),
	    link: function link(scope) {
	      scope.currentTab = 'today';
	      scope.i18n = i18n;
	
	      var previousKeyForTab = {
	        today: 'yesterday',
	        this_week: 'last_week'
	      };
	
	      scope.tabs = ['today', 'this_week', 'total'];
	
	      scope.header = function (tab) {
	        return i18n.t('generosity.dashboard.visits.tab_headers.' + tab);
	      };
	
	      scope.visits = function (tab) {
	        var visits = gon.visits[tab];
	        if (browser.isMobile() || visits >= 1000000) {
	          return $filter('abbrevNumFmt')(visits);
	        }
	        return $filter('number')(visits);
	      };
	
	      scope.percentChange = function (tab) {
	        if (tab === 'total') {
	          return '';
	        }
	        var currentCount = gon.visits[tab];
	        var initialCount = gon.visits[previousKeyForTab[tab]];
	        if (initialCount === 0) {
	          return '';
	        }
	        var change = (currentCount - initialCount) / initialCount;
	        return $filter('percentChange')(change);
	      };
	
	      scope.changeTab = function (tab) {
	        scope.currentTab = tab;
	      };
	    }
	  };
	}

/***/ },
/* 52 */
/***/ function(module, exports) {

	module.exports = "<div class=\"visible-xs\">\n  <div class=\"dropdown pc-dashboard-visitStats-dropdownCol\">\n    <a href=\"\" bs-dropdown class=\"pc-dashboard-visitStats-dropdown\">\n      <span class=\"pc-dashboard-visitStats-dropdown-text\">{{header(currentTab)}}</span>\n    </a>\n    <div class=\"dropdown-menu i-linklist-dropdown pc-dashboard-visitStats-dropdownMenu\">\n      <a href=\"\" ng-repeat=\"tab in tabs\" ng-click=\"changeTab(tab)\" class=\"pc-dashboard-visitStats-dropdownMenu-item\" ng-class=\"{'selected': currentTab === tab}\">{{header(tab)}}</a>\n    </div>\n  </div>\n  <div class=\"pc-dashboard-visitStats-statCol\">\n    <div class=\"pc-dashboard-visitStats-stat\">{{visits(currentTab)}}</div>\n  </div>\n</div>\n<div class=\"hidden-xs\">\n  <div class=\"pc-dashboard-visitStats-header\">{{header(currentTab)}}</div>\n  <div class=\"pc-dashboard-visitStats-stat\">{{visits(currentTab)}}</div>\n  <div class=\"pc-dashboard-visitStats-change\">{{percentChange(currentTab)}}</div>\n  <div class=\"i-float-tab-links pc-dashboard-visitStats-tabs\">\n    <a href=\"\" ng-repeat=\"tab in tabs\" ng-click=\"changeTab(tab)\" class=\"i-tab pc-dashboard-visitStats-tab\" ng-class=\"{'i-selected': currentTab === tab}\"><span>{{::i18n.t('generosity.dashboard.visits.tabs.' + tab)}}</span></a>\n  </div>\n</div>\n";

/***/ },
/* 53 */
/***/ function(module, exports) {

	'use strict';
	
	percentChangeFilter.$inject = ["$filter"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = percentChangeFilter;
	/*@ngInject*/
	
	function percentChangeFilter($filter) {
	  return function (input) {
	    var stringValue = $filter('number')(input * 100, 0);
	    if (input < 0) {
	      return stringValue + '%';
	    } else {
	      return '+' + stringValue + '%';
	    }
	  };
	}

/***/ },
/* 54 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = todoItemStatusIconDirective;
	/*@ngInject*/
	
	function todoItemStatusIconDirective() {
	  return {
	    scope: {
	      status: '='
	    },
	    replace: true,
	    template: __webpack_require__(55)
	  };
	}

/***/ },
/* 55 */
/***/ function(module, exports) {

	module.exports = "<span class=\"pc-dashboard-todoItem-statusIcon\" ng-class=\"status.completedRecently ? 'pc-dashboard-todoItem-statusIcon--check' : 'pc-dashboard-todoItem-statusIcon--exclamation'\">\n    <svg-icon icon=\"icon-icon-check\" ng-if=\"status.completedRecently\"></svg-icon>\n    <svg-icon icon=\"icon-icon-exclamation\" ng-if=\"!status.completedRecently\"></svg-icon>\n</span>\n";

/***/ },
/* 56 */
/***/ function(module, exports) {

	'use strict';
	
	weekOfFilter.$inject = ["i18n"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = weekOfFilter;
	/*@ngInject*/
	
	function weekOfFilter(i18n) {
	  return function (value) {
	    return i18n.t('generosity.dashboard.funds.week_of_x', {
	      x: moment(value).day(1).format('MMM D, YYYY')
	    });
	  };
	}

/***/ },
/* 57 */
/***/ function(module, exports) {

	'use strict';
	
	campaignCommentsService.$inject = ["$http", "gon", "$sce", "$q", "campaignPusher", "ga", "$location"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = campaignCommentsService;
	/*@ngInject*/
	
	function campaignCommentsService($http, gon, $sce, $q, campaignPusher, ga, $location) {
	  var service = {};
	  var loaded = false;
	  var toggleSpamPath = gon.urls.toggle_spam_path;
	  var createReplyPath = gon.urls.create_reply_path;
	  var deleteReplyPath = gon.urls.delete_reply_path;
	
	  function processCommentJson(commentJson) {
	    commentJson.comment_html = $sce.trustAsHtml(commentJson.comment_html);
	  }
	
	  function loadMany() {
	    return $http.get(gon.urls.comments).then(function (result) {
	      loaded = true;
	      var comments = result.data.response;
	      comments.forEach(function (comment) {
	        processCommentJson(comment);
	      });
	      service.comments = comments;
	      service.pagination = result.data.pagination;
	    });
	  }
	
	  function loadOne() {
	    return $http.get(gon.urls.comments + '/' + $location.$$search.id).then(function (result) {
	      var newComment = result.data;
	      processCommentJson(newComment);
	      service.comments = [newComment];
	      service.pagination = null;
	    });
	  }
	
	  function load() {
	    if (loaded) {
	      var deferred = $q.defer();
	      deferred.resolve();
	      return deferred.promise;
	    }
	    if ($location.$$search.id) {
	      return loadOne();
	    }
	    return loadMany();
	  }
	
	  function loadMore() {
	    return $http.get(gon.urls.comments + '?page=' + service.pagination.next).then(function (result) {
	      var newComments = result.data.response;
	      newComments.forEach(function (comment) {
	        processCommentJson(comment);
	      });
	      service.comments = service.comments.concat(newComments);
	      service.pagination = result.data.pagination;
	    });
	  }
	
	  function deleteComment(comment) {
	    return $http.delete(comment.delete_path, comment).then(function () {
	      service.comments = _.without(service.comments, comment);
	    });
	  }
	
	  function postComment(newComment) {
	    var gaAppearance = newComment.appearance === 'STAP_PRVT' ? 'private' : 'public';
	    // TODO EVENTS: id=izo8i fixtype=bare-ga category=Campaign.Comment action=dynamic label=dynamic name-new=TBD subsystem=comms . review
	    ga('send', 'event', 'Campaign Comment', 'comment sent - ' + gaAppearance, gon.ga_impression_data.name);
	    return $http.post(gon.urls.comments, { comment: newComment }).then(function (response) {
	      var responseComment = response.data;
	      processCommentJson(responseComment);
	      service.comments = [responseComment].concat(service.comments);
	    });
	  }
	
	  function toggleSpam(comment) {
	    return $http.put(toggleSpamPath, { comment: comment });
	  }
	
	  function postReply(comment, replyText) {
	    return $http.post(createReplyPath, { comment_id: comment.id, reply_text: replyText }).then(function (response) {
	      var responseReply = response.data;
	      comment.replies.push(responseReply);
	    });
	  }
	
	  function deleteReply(comment, reply) {
	    return $http.put(deleteReplyPath, { reply_id: reply.id }).then(function () {
	      comment.replies = _.without(comment.replies, reply);
	    });
	  }
	
	  campaignPusher.bind('new_comment', function (message) {
	    var existingComment = _.findWhere(service.comments, { id: message.comment_id });
	    if (!existingComment) {
	      $http.get(gon.urls.comments + '/' + message.comment_id).then(function (response) {
	        var responseComment = response.data;
	        processCommentJson(responseComment);
	        service.comments = [responseComment].concat(service.comments);
	      });
	    }
	  });
	
	  service = {
	    load: load,
	    loadMore: loadMore,
	    deleteComment: deleteComment,
	    postComment: postComment,
	    toggleSpam: toggleSpam,
	    postReply: postReply,
	    deleteReply: deleteReply,
	    allowPublicComments: gon.allow_public_comments
	  };
	
	  return service;
	}

/***/ },
/* 58 */
/***/ function(module, exports) {

	'use strict';
	
	campaignUpdatesService.$inject = ["$http", "gon"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = campaignUpdatesService;
	/*@ngInject*/
	
	function campaignUpdatesService($http, gon) {
	  var service = {};
	  var updatesUrl = gon.urls.updates;
	  var previewUrl = gon.urls.preview_update;
	
	  function getUpdates() {
	    return $http.get(updatesUrl);
	  }
	
	  function postUpdate(update) {
	    return $http.post(updatesUrl, update);
	  }
	
	  function deleteUpdate(update) {
	    return $http.delete(update.delete_path, update);
	  }
	
	  function showMore(next) {
	    return $http.get(updatesUrl + '?page=' + next);
	  }
	
	  function previewUpdate(update) {
	    return $http.get(previewUrl + '?announcement[body_html]=' + encodeURIComponent(update.bodyHtml));
	  }
	
	  service = {
	    getUpdates: getUpdates,
	    postUpdate: postUpdate,
	    deleteUpdate: deleteUpdate,
	    showMore: showMore,
	    previewUpdate: previewUpdate
	  };
	
	  return service;
	}

/***/ },
/* 59 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	campaignHeaderRecommendationsDirective.$inject = ["campaignHeaderRecommendations", "gon", "i18n"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = campaignHeaderRecommendationsDirective;
	/*@ngInject*/
	
	function campaignHeaderRecommendationsDirective(campaignHeaderRecommendations, gon, i18n) {
	  return {
	    scope: {
	      experimentGroup: '@'
	    },
	    template: __webpack_require__(60),
	    link: function link(scope) {
	      scope.campaignId = gon.campaign.id;
	      scope.i18n = i18n;
	
	      scope.campaigns = [];
	      campaignHeaderRecommendations.getCampaigns('picks_for_you').then(function (campaigns) {
	        scope.campaigns = campaigns.filter(function (campaign) {
	          return campaign.card_type !== 'static' && campaign.title.length < 65;
	        });
	      });
	
	      scope.urlWithIggref = function (url) {
	        return url + '/pshr';
	      };
	    }
	  };
	}

/***/ },
/* 60 */
/***/ function(module, exports) {

	module.exports = "<i18n>\n  <carousel objects=\"campaigns\" window=\"visibleCampaigns\" visible=\"4\">\n    <ul class=\"row\">\n      <li ng-repeat=\"campaign in visibleCampaigns\" class=\"campaignHeaderRecommendationCampaign\">\n        <!-- TODO EVENTS: id=eiy1d fixtype=ga-event-dir subsystem=campaign-page trigger=click dom=a category=campaign_header_recommendations category-new=TBD action=click label=dynamic name-new=TBD . review -->\n        <a class=\"campaignHeaderRecommendationCampaign-link\" ng-href=\"{{urlWithIggref(campaign.url)}}\"\n           analytics-on=\"click\"\n           analytics-name=\"campaign_header_recommendations_click\"\n           analytics-category=\"campaign_header_recommendations\"\n           analytics-event=\"click\"\n           analytics-label=\"{{campaign.category_name}}\">\n          <div class=\"campaignHeaderRecommendationCampaign-image\" ng-style=\"{'background-image': 'url(' + campaign.igg_image_url + ')'}\">\n          </div>\n          <div class=\"campaignHeaderRecommendationCampaign-meta\">\n            <div class=\"campaignHeaderRecommendationCampaign-title\">{{campaign.title}}</div>\n            <div class=\"campaignHeaderRecommendationCampaign-backers\">{{campaign.cached_collected_pledges_count}} {{::i18n.t('backers')}}</div>\n          </div>\n        </a>\n      </li>\n    </ul>\n  </carousel>\n</i18n>\n";

/***/ },
/* 61 */
/***/ function(module, exports) {

	"use strict";
	
	campaignHeaderRecommendationsService.$inject = ["$http", "i18n", "gon"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = campaignHeaderRecommendationsService;
	/*@ngInject*/
	
	function campaignHeaderRecommendationsService($http, i18n, gon) {
	  function getCampaigns(quickFilter) {
	    var params = {
	      quick_filter: quickFilter,
	      locale: i18n.locale
	    };
	    return $http.get(gon.urls.campaign_header_recommendations, { params: params }).then(function (response) {
	      return response.data.campaigns;
	    });
	  }
	
	  return {
	    getCampaigns: getCampaigns
	  };
	}

/***/ },
/* 62 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = pusherWrapperService;
	
	var _pusherWrapper = __webpack_require__(63);
	
	var _pusherWrapper2 = _interopRequireDefault(_pusherWrapper);
	
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
	
	function pusherWrapperService() {
	  return {
	    createPusher: function createPusher(appId, options) {
	      return new _pusherWrapper2.default(appId, options);
	    }
	  };
	} /*@ngInject*/

/***/ },
/* 63 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";
	
	var pusher = __webpack_require__(64);
	module.exports = pusher;

/***/ },
/* 64 */
/***/ function(module, exports) {

	/*** IMPORTS FROM imports-loader ***/
	(function() {
	
	/*!
	 * Pusher JavaScript Library v2.2.4
	 * http://pusher.com/
	 *
	 * Copyright 2014, Pusher
	 * Released under the MIT licence.
	 */
	
	;(function() {
	  function Pusher(app_key, options) {
	    checkAppKey(app_key);
	    options = options || {};
	
	    var self = this;
	
	    this.key = app_key;
	    this.config = Pusher.Util.extend(
	      Pusher.getGlobalConfig(),
	      options.cluster ? Pusher.getClusterConfig(options.cluster) : {},
	      options
	    );
	
	    this.channels = new Pusher.Channels();
	    this.global_emitter = new Pusher.EventsDispatcher();
	    this.sessionID = Math.floor(Math.random() * 1000000000);
	
	    this.timeline = new Pusher.Timeline(this.key, this.sessionID, {
	      cluster: this.config.cluster,
	      features: Pusher.Util.getClientFeatures(),
	      params: this.config.timelineParams || {},
	      limit: 50,
	      level: Pusher.Timeline.INFO,
	      version: Pusher.VERSION
	    });
	    if (!this.config.disableStats) {
	      this.timelineSender = new Pusher.TimelineSender(this.timeline, {
	        host: this.config.statsHost,
	        path: "/timeline/v2/jsonp"
	      });
	    }
	
	    var getStrategy = function(options) {
	      var config = Pusher.Util.extend({}, self.config, options);
	      return Pusher.StrategyBuilder.build(
	        Pusher.getDefaultStrategy(config), config
	      );
	    };
	
	    this.connection = new Pusher.ConnectionManager(
	      this.key,
	      Pusher.Util.extend(
	        { getStrategy: getStrategy,
	          timeline: this.timeline,
	          activityTimeout: this.config.activity_timeout,
	          pongTimeout: this.config.pong_timeout,
	          unavailableTimeout: this.config.unavailable_timeout
	        },
	        this.config,
	        { encrypted: this.isEncrypted() }
	      )
	    );
	
	    this.connection.bind('connected', function() {
	      self.subscribeAll();
	      if (self.timelineSender) {
	        self.timelineSender.send(self.connection.isEncrypted());
	      }
	    });
	    this.connection.bind('message', function(params) {
	      var internal = (params.event.indexOf('pusher_internal:') === 0);
	      if (params.channel) {
	        var channel = self.channel(params.channel);
	        if (channel) {
	          channel.handleEvent(params.event, params.data);
	        }
	      }
	      // Emit globaly [deprecated]
	      if (!internal) {
	        self.global_emitter.emit(params.event, params.data);
	      }
	    });
	    this.connection.bind('disconnected', function() {
	      self.channels.disconnect();
	    });
	    this.connection.bind('error', function(err) {
	      Pusher.warn('Error', err);
	    });
	
	    Pusher.instances.push(this);
	    this.timeline.info({ instances: Pusher.instances.length });
	
	    if (Pusher.isReady) {
	      self.connect();
	    }
	  }
	  var prototype = Pusher.prototype;
	
	  Pusher.instances = [];
	  Pusher.isReady = false;
	
	  // To receive log output provide a Pusher.log function, for example
	  // Pusher.log = function(m){console.log(m)}
	  Pusher.debug = function() {
	    if (!Pusher.log) {
	      return;
	    }
	    Pusher.log(Pusher.Util.stringify.apply(this, arguments));
	  };
	
	  Pusher.warn = function() {
	    var message = Pusher.Util.stringify.apply(this, arguments);
	    if (window.console) {
	      if (window.console.warn) {
	        window.console.warn(message);
	      } else if (window.console.log) {
	        window.console.log(message);
	      }
	    }
	    if (Pusher.log) {
	      Pusher.log(message);
	    }
	  };
	
	  Pusher.ready = function() {
	    Pusher.isReady = true;
	    for (var i = 0, l = Pusher.instances.length; i < l; i++) {
	      Pusher.instances[i].connect();
	    }
	  };
	
	  prototype.channel = function(name) {
	    return this.channels.find(name);
	  };
	
	  prototype.allChannels = function() {
	    return this.channels.all();
	  };
	
	  prototype.connect = function() {
	    this.connection.connect();
	
	    if (this.timelineSender) {
	      if (!this.timelineSenderTimer) {
	        var encrypted = this.connection.isEncrypted();
	        var timelineSender = this.timelineSender;
	        this.timelineSenderTimer = new Pusher.PeriodicTimer(60000, function() {
	          timelineSender.send(encrypted);
	        });
	      }
	    }
	  };
	
	  prototype.disconnect = function() {
	    this.connection.disconnect();
	
	    if (this.timelineSenderTimer) {
	      this.timelineSenderTimer.ensureAborted();
	      this.timelineSenderTimer = null;
	    }
	  };
	
	  prototype.bind = function(event_name, callback) {
	    this.global_emitter.bind(event_name, callback);
	    return this;
	  };
	
	  prototype.bind_all = function(callback) {
	    this.global_emitter.bind_all(callback);
	    return this;
	  };
	
	  prototype.subscribeAll = function() {
	    var channelName;
	    for (channelName in this.channels.channels) {
	      if (this.channels.channels.hasOwnProperty(channelName)) {
	        this.subscribe(channelName);
	      }
	    }
	  };
	
	  prototype.subscribe = function(channel_name) {
	    var channel = this.channels.add(channel_name, this);
	    if (this.connection.state === 'connected') {
	      channel.subscribe();
	    }
	    return channel;
	  };
	
	  prototype.unsubscribe = function(channel_name) {
	    var channel = this.channels.remove(channel_name);
	    if (this.connection.state === 'connected') {
	      channel.unsubscribe();
	    }
	  };
	
	  prototype.send_event = function(event_name, data, channel) {
	    return this.connection.send_event(event_name, data, channel);
	  };
	
	  prototype.isEncrypted = function() {
	    if (Pusher.Util.getDocument().location.protocol === "https:") {
	      return true;
	    } else {
	      return Boolean(this.config.encrypted);
	    }
	  };
	
	  function checkAppKey(key) {
	    if (key === null || key === undefined) {
	      Pusher.warn(
	        'Warning', 'You must pass your app key when you instantiate Pusher.'
	      );
	    }
	  }
	
	  Pusher.HTTP = {};
	
	  this.Pusher = Pusher;
	}).call(this);
	
	;(function() {
	  // We need to bind clear functions this way to avoid exceptions on IE8
	  function clearTimeout(timer) {
	    window.clearTimeout(timer);
	  }
	  function clearInterval(timer) {
	    window.clearInterval(timer);
	  }
	
	  function GenericTimer(set, clear, delay, callback) {
	    var self = this;
	
	    this.clear = clear;
	    this.timer = set(function() {
	      if (self.timer !== null) {
	        self.timer = callback(self.timer);
	      }
	    }, delay);
	  }
	  var prototype = GenericTimer.prototype;
	
	  /** Returns whether the timer is still running.
	   *
	   * @return {Boolean}
	   */
	  prototype.isRunning = function() {
	    return this.timer !== null;
	  };
	
	  /** Aborts a timer when it's running. */
	  prototype.ensureAborted = function() {
	    if (this.timer) {
	      // Clear function is already bound
	      this.clear(this.timer);
	      this.timer = null;
	    }
	  };
	
	  /** Cross-browser compatible one-off timer abstraction.
	   *
	   * @param {Number} delay
	   * @param {Function} callback
	   */
	  Pusher.Timer = function(delay, callback) {
	    return new GenericTimer(setTimeout, clearTimeout, delay, function(timer) {
	      callback();
	      return null;
	    });
	  };
	  /** Cross-browser compatible periodic timer abstraction.
	   *
	   * @param {Number} delay
	   * @param {Function} callback
	   */
	  Pusher.PeriodicTimer = function(delay, callback) {
	    return new GenericTimer(setInterval, clearInterval, delay, function(timer) {
	      callback();
	      return timer;
	    });
	  };
	}).call(this);
	
	;(function() {
	  Pusher.Util = {
	    now: function() {
	      if (Date.now) {
	        return Date.now();
	      } else {
	        return new Date().valueOf();
	      }
	    },
	
	    defer: function(callback) {
	      return new Pusher.Timer(0, callback);
	    },
	
	    /** Merges multiple objects into the target argument.
	     *
	     * For properties that are plain Objects, performs a deep-merge. For the
	     * rest it just copies the value of the property.
	     *
	     * To extend prototypes use it as following:
	     *   Pusher.Util.extend(Target.prototype, Base.prototype)
	     *
	     * You can also use it to merge objects without altering them:
	     *   Pusher.Util.extend({}, object1, object2)
	     *
	     * @param  {Object} target
	     * @return {Object} the target argument
	     */
	    extend: function(target) {
	      for (var i = 1; i < arguments.length; i++) {
	        var extensions = arguments[i];
	        for (var property in extensions) {
	          if (extensions[property] && extensions[property].constructor &&
	              extensions[property].constructor === Object) {
	            target[property] = Pusher.Util.extend(
	              target[property] || {}, extensions[property]
	            );
	          } else {
	            target[property] = extensions[property];
	          }
	        }
	      }
	      return target;
	    },
	
	    stringify: function() {
	      var m = ["Pusher"];
	      for (var i = 0; i < arguments.length; i++) {
	        if (typeof arguments[i] === "string") {
	          m.push(arguments[i]);
	        } else {
	          if (window.JSON === undefined) {
	            m.push(arguments[i].toString());
	          } else {
	            m.push(JSON.stringify(arguments[i]));
	          }
	        }
	      }
	      return m.join(" : ");
	    },
	
	    arrayIndexOf: function(array, item) { // MSIE doesn't have array.indexOf
	      var nativeIndexOf = Array.prototype.indexOf;
	      if (array === null) {
	        return -1;
	      }
	      if (nativeIndexOf && array.indexOf === nativeIndexOf) {
	        return array.indexOf(item);
	      }
	      for (var i = 0, l = array.length; i < l; i++) {
	        if (array[i] === item) {
	          return i;
	        }
	      }
	      return -1;
	    },
	
	    /** Applies a function f to all properties of an object.
	     *
	     * Function f gets 3 arguments passed:
	     * - element from the object
	     * - key of the element
	     * - reference to the object
	     *
	     * @param {Object} object
	     * @param {Function} f
	     */
	    objectApply: function(object, f) {
	      for (var key in object) {
	        if (Object.prototype.hasOwnProperty.call(object, key)) {
	          f(object[key], key, object);
	        }
	      }
	    },
	
	    /** Return a list of object's own property keys
	     *
	     * @param {Object} object
	     * @returns {Array}
	     */
	    keys: function(object) {
	      var keys = [];
	      Pusher.Util.objectApply(object, function(_, key) {
	        keys.push(key);
	      });
	      return keys;
	    },
	
	    /** Return a list of object's own property values
	     *
	     * @param {Object} object
	     * @returns {Array}
	     */
	    values: function(object) {
	      var values = [];
	      Pusher.Util.objectApply(object, function(value) {
	        values.push(value);
	      });
	      return values;
	    },
	
	    /** Applies a function f to all elements of an array.
	     *
	     * Function f gets 3 arguments passed:
	     * - element from the array
	     * - index of the element
	     * - reference to the array
	     *
	     * @param {Array} array
	     * @param {Function} f
	     */
	    apply: function(array, f, context) {
	      for (var i = 0; i < array.length; i++) {
	        f.call(context || window, array[i], i, array);
	      }
	    },
	
	    /** Maps all elements of the array and returns the result.
	     *
	     * Function f gets 4 arguments passed:
	     * - element from the array
	     * - index of the element
	     * - reference to the source array
	     * - reference to the destination array
	     *
	     * @param {Array} array
	     * @param {Function} f
	     */
	    map: function(array, f) {
	      var result = [];
	      for (var i = 0; i < array.length; i++) {
	        result.push(f(array[i], i, array, result));
	      }
	      return result;
	    },
	
	    /** Maps all elements of the object and returns the result.
	     *
	     * Function f gets 4 arguments passed:
	     * - element from the object
	     * - key of the element
	     * - reference to the source object
	     * - reference to the destination object
	     *
	     * @param {Object} object
	     * @param {Function} f
	     */
	    mapObject: function(object, f) {
	      var result = {};
	      Pusher.Util.objectApply(object, function(value, key) {
	        result[key] = f(value);
	      });
	      return result;
	    },
	
	    /** Filters elements of the array using a test function.
	     *
	     * Function test gets 4 arguments passed:
	     * - element from the array
	     * - index of the element
	     * - reference to the source array
	     * - reference to the destination array
	     *
	     * @param {Array} array
	     * @param {Function} f
	     */
	    filter: function(array, test) {
	      test = test || function(value) { return !!value; };
	
	      var result = [];
	      for (var i = 0; i < array.length; i++) {
	        if (test(array[i], i, array, result)) {
	          result.push(array[i]);
	        }
	      }
	      return result;
	    },
	
	    /** Filters properties of the object using a test function.
	     *
	     * Function test gets 4 arguments passed:
	     * - element from the object
	     * - key of the element
	     * - reference to the source object
	     * - reference to the destination object
	     *
	     * @param {Object} object
	     * @param {Function} f
	     */
	    filterObject: function(object, test) {
	      var result = {};
	      Pusher.Util.objectApply(object, function(value, key) {
	        if ((test && test(value, key, object, result)) || Boolean(value)) {
	          result[key] = value;
	        }
	      });
	      return result;
	    },
	
	    /** Flattens an object into a two-dimensional array.
	     *
	     * @param  {Object} object
	     * @return {Array} resulting array of [key, value] pairs
	     */
	    flatten: function(object) {
	      var result = [];
	      Pusher.Util.objectApply(object, function(value, key) {
	        result.push([key, value]);
	      });
	      return result;
	    },
	
	    /** Checks whether any element of the array passes the test.
	     *
	     * Function test gets 3 arguments passed:
	     * - element from the array
	     * - index of the element
	     * - reference to the source array
	     *
	     * @param {Array} array
	     * @param {Function} f
	     */
	    any: function(array, test) {
	      for (var i = 0; i < array.length; i++) {
	        if (test(array[i], i, array)) {
	          return true;
	        }
	      }
	      return false;
	    },
	
	    /** Checks whether all elements of the array pass the test.
	     *
	     * Function test gets 3 arguments passed:
	     * - element from the array
	     * - index of the element
	     * - reference to the source array
	     *
	     * @param {Array} array
	     * @param {Function} f
	     */
	    all: function(array, test) {
	      for (var i = 0; i < array.length; i++) {
	        if (!test(array[i], i, array)) {
	          return false;
	        }
	      }
	      return true;
	    },
	
	    /** Builds a function that will proxy a method call to its first argument.
	     *
	     * Allows partial application of arguments, so additional arguments are
	     * prepended to the argument list.
	     *
	     * @param  {String} name method name
	     * @return {Function} proxy function
	     */
	    method: function(name) {
	      var boundArguments = Array.prototype.slice.call(arguments, 1);
	      return function(object) {
	        return object[name].apply(object, boundArguments.concat(arguments));
	      };
	    },
	
	    getWindow: function() {
	      return window;
	    },
	
	    getDocument: function() {
	      return document;
	    },
	
	    getNavigator: function() {
	      return navigator;
	    },
	
	    getLocalStorage: function() {
	      try {
	        return window.localStorage;
	      } catch (e) {
	        return undefined;
	      }
	    },
	
	    getClientFeatures: function() {
	      return Pusher.Util.keys(
	        Pusher.Util.filterObject(
	          { "ws": Pusher.WSTransport, "flash": Pusher.FlashTransport },
	          function (t) { return t.isSupported({}); }
	        )
	      );
	    },
	
	    addWindowListener: function(event, listener) {
	      var _window = Pusher.Util.getWindow();
	      if (_window.addEventListener !== undefined) {
	        _window.addEventListener(event, listener, false);
	      } else {
	        _window.attachEvent("on" + event, listener);
	      }
	    },
	
	    removeWindowListener: function(event, listener) {
	      var _window = Pusher.Util.getWindow();
	      if (_window.addEventListener !== undefined) {
	        _window.removeEventListener(event, listener, false);
	      } else {
	        _window.detachEvent("on" + event, listener);
	      }
	    },
	
	    isXHRSupported: function() {
	      var XHR = window.XMLHttpRequest;
	      return Boolean(XHR) && (new XHR()).withCredentials !== undefined;
	    },
	
	    isXDRSupported: function(encrypted) {
	      var protocol = encrypted ? "https:" : "http:";
	      var documentProtocol = Pusher.Util.getDocument().location.protocol;
	      return Boolean(window.XDomainRequest) && documentProtocol === protocol;
	    }
	  };
	}).call(this);
	
	;(function() {
	  Pusher.VERSION = '2.2.4';
	  Pusher.PROTOCOL = 7;
	
	  // DEPRECATED: WS connection parameters
	  Pusher.host = 'ws.pusherapp.com';
	  Pusher.ws_port = 80;
	  Pusher.wss_port = 443;
	  // DEPRECATED: SockJS fallback parameters
	  Pusher.sockjs_host = 'sockjs.pusher.com';
	  Pusher.sockjs_http_port = 80;
	  Pusher.sockjs_https_port = 443;
	  Pusher.sockjs_path = "/pusher";
	  // DEPRECATED: Stats
	  Pusher.stats_host = 'stats.pusher.com';
	  // DEPRECATED: Other settings
	  Pusher.channel_auth_endpoint = '/pusher/auth';
	  Pusher.channel_auth_transport = 'ajax';
	  Pusher.activity_timeout = 120000;
	  Pusher.pong_timeout = 30000;
	  Pusher.unavailable_timeout = 10000;
	  // CDN configuration
	  Pusher.cdn_http = 'http://js.pusher.com/';
	  Pusher.cdn_https = 'https://js.pusher.com/';
	  Pusher.dependency_suffix = '';
	
	  Pusher.getDefaultStrategy = function(config) {
	    var wsStrategy;
	    if (config.encrypted) {
	      wsStrategy = [
	        ":best_connected_ever",
	        ":ws_loop",
	        [":delayed", 2000, [":http_fallback_loop"]]
	      ];
	    } else {
	      wsStrategy = [
	        ":best_connected_ever",
	        ":ws_loop",
	        [":delayed", 2000, [":wss_loop"]],
	        [":delayed", 5000, [":http_fallback_loop"]]
	      ];
	    }
	
	    return [
	      [":def", "ws_options", {
	        hostUnencrypted: config.wsHost + ":" + config.wsPort,
	        hostEncrypted: config.wsHost + ":" + config.wssPort
	      }],
	      [":def", "wss_options", [":extend", ":ws_options", {
	        encrypted: true
	      }]],
	      [":def", "sockjs_options", {
	        hostUnencrypted: config.httpHost + ":" + config.httpPort,
	        hostEncrypted: config.httpHost + ":" + config.httpsPort,
	        httpPath: config.httpPath
	      }],
	      [":def", "timeouts", {
	        loop: true,
	        timeout: 15000,
	        timeoutLimit: 60000
	      }],
	
	      [":def", "ws_manager", [":transport_manager", {
	        lives: 2,
	        minPingDelay: 10000,
	        maxPingDelay: config.activity_timeout
	      }]],
	      [":def", "streaming_manager", [":transport_manager", {
	        lives: 2,
	        minPingDelay: 10000,
	        maxPingDelay: config.activity_timeout
	      }]],
	
	      [":def_transport", "ws", "ws", 3, ":ws_options", ":ws_manager"],
	      [":def_transport", "wss", "ws", 3, ":wss_options", ":ws_manager"],
	      [":def_transport", "flash", "flash", 2, ":ws_options", ":ws_manager"],
	      [":def_transport", "sockjs", "sockjs", 1, ":sockjs_options"],
	      [":def_transport", "xhr_streaming", "xhr_streaming", 1, ":sockjs_options", ":streaming_manager"],
	      [":def_transport", "xdr_streaming", "xdr_streaming", 1, ":sockjs_options", ":streaming_manager"],
	      [":def_transport", "xhr_polling", "xhr_polling", 1, ":sockjs_options"],
	      [":def_transport", "xdr_polling", "xdr_polling", 1, ":sockjs_options"],
	
	      [":def", "ws_loop", [":sequential", ":timeouts", ":ws"]],
	      [":def", "wss_loop", [":sequential", ":timeouts", ":wss"]],
	      [":def", "flash_loop", [":sequential", ":timeouts", ":flash"]],
	      [":def", "sockjs_loop", [":sequential", ":timeouts", ":sockjs"]],
	
	      [":def", "streaming_loop", [":sequential", ":timeouts",
	        [":if", [":is_supported", ":xhr_streaming"],
	          ":xhr_streaming",
	          ":xdr_streaming"
	        ]
	      ]],
	      [":def", "polling_loop", [":sequential", ":timeouts",
	        [":if", [":is_supported", ":xhr_polling"],
	          ":xhr_polling",
	          ":xdr_polling"
	        ]
	      ]],
	
	      [":def", "http_loop", [":if", [":is_supported", ":streaming_loop"], [
	        ":best_connected_ever",
	          ":streaming_loop",
	          [":delayed", 4000, [":polling_loop"]]
	      ], [
	        ":polling_loop"
	      ]]],
	
	      [":def", "http_fallback_loop",
	        [":if", [":is_supported", ":http_loop"], [
	          ":http_loop"
	        ], [
	          ":sockjs_loop"
	        ]]
	      ],
	
	      [":def", "strategy",
	        [":cached", 1800000,
	          [":first_connected",
	            [":if", [":is_supported", ":ws"],
	              wsStrategy,
	            [":if", [":is_supported", ":flash"], [
	              ":best_connected_ever",
	              ":flash_loop",
	              [":delayed", 2000, [":http_fallback_loop"]]
	            ], [
	              ":http_fallback_loop"
	            ]]]
	          ]
	        ]
	      ]
	    ];
	  };
	}).call(this);
	
	;(function() {
	  Pusher.getGlobalConfig = function() {
	    return {
	      wsHost: Pusher.host,
	      wsPort: Pusher.ws_port,
	      wssPort: Pusher.wss_port,
	      httpHost: Pusher.sockjs_host,
	      httpPort: Pusher.sockjs_http_port,
	      httpsPort: Pusher.sockjs_https_port,
	      httpPath: Pusher.sockjs_path,
	      statsHost: Pusher.stats_host,
	      authEndpoint: Pusher.channel_auth_endpoint,
	      authTransport: Pusher.channel_auth_transport,
	      // TODO make this consistent with other options in next major version
	      activity_timeout: Pusher.activity_timeout,
	      pong_timeout: Pusher.pong_timeout,
	      unavailable_timeout: Pusher.unavailable_timeout
	    };
	  };
	
	  Pusher.getClusterConfig = function(clusterName) {
	    return {
	      wsHost: "ws-" + clusterName + ".pusher.com",
	      httpHost: "sockjs-" + clusterName + ".pusher.com"
	    };
	  };
	}).call(this);
	
	;(function() {
	  function buildExceptionClass(name) {
	    var constructor = function(message) {
	      Error.call(this, message);
	      this.name = name;
	    };
	    Pusher.Util.extend(constructor.prototype, Error.prototype);
	
	    return constructor;
	  }
	
	  /** Error classes used throughout pusher-js library. */
	  Pusher.Errors = {
	    BadEventName: buildExceptionClass("BadEventName"),
	    RequestTimedOut: buildExceptionClass("RequestTimedOut"),
	    TransportPriorityTooLow: buildExceptionClass("TransportPriorityTooLow"),
	    TransportClosed: buildExceptionClass("TransportClosed"),
	    UnsupportedTransport: buildExceptionClass("UnsupportedTransport"),
	    UnsupportedStrategy: buildExceptionClass("UnsupportedStrategy")
	  };
	}).call(this);
	
	;(function() {
	  /** Manages callback bindings and event emitting.
	   *
	   * @param Function failThrough called when no listeners are bound to an event
	   */
	  function EventsDispatcher(failThrough) {
	    this.callbacks = new CallbackRegistry();
	    this.global_callbacks = [];
	    this.failThrough = failThrough;
	  }
	  var prototype = EventsDispatcher.prototype;
	
	  prototype.bind = function(eventName, callback, context) {
	    this.callbacks.add(eventName, callback, context);
	    return this;
	  };
	
	  prototype.bind_all = function(callback) {
	    this.global_callbacks.push(callback);
	    return this;
	  };
	
	  prototype.unbind = function(eventName, callback, context) {
	    this.callbacks.remove(eventName, callback, context);
	    return this;
	  };
	
	  prototype.unbind_all = function(eventName, callback) {
	    this.callbacks.remove(eventName, callback);
	    return this;
	  };
	
	  prototype.emit = function(eventName, data) {
	    var i;
	
	    for (i = 0; i < this.global_callbacks.length; i++) {
	      this.global_callbacks[i](eventName, data);
	    }
	
	    var callbacks = this.callbacks.get(eventName);
	    if (callbacks && callbacks.length > 0) {
	      for (i = 0; i < callbacks.length; i++) {
	        callbacks[i].fn.call(callbacks[i].context || window, data);
	      }
	    } else if (this.failThrough) {
	      this.failThrough(eventName, data);
	    }
	
	    return this;
	  };
	
	  /** Callback registry helper. */
	
	  function CallbackRegistry() {
	    this._callbacks = {};
	  }
	
	  CallbackRegistry.prototype.get = function(name) {
	    return this._callbacks[prefix(name)];
	  };
	
	  CallbackRegistry.prototype.add = function(name, callback, context) {
	    var prefixedEventName = prefix(name);
	    this._callbacks[prefixedEventName] = this._callbacks[prefixedEventName] || [];
	    this._callbacks[prefixedEventName].push({
	      fn: callback,
	      context: context
	    });
	  };
	
	  CallbackRegistry.prototype.remove = function(name, callback, context) {
	    if (!name && !callback && !context) {
	      this._callbacks = {};
	      return;
	    }
	
	    var names = name ? [prefix(name)] : Pusher.Util.keys(this._callbacks);
	
	    if (callback || context) {
	      Pusher.Util.apply(names, function(name) {
	        this._callbacks[name] = Pusher.Util.filter(
	          this._callbacks[name] || [],
	          function(binding) {
	            return (callback && callback !== binding.fn) ||
	                   (context && context !== binding.context);
	          }
	        );
	        if (this._callbacks[name].length === 0) {
	          delete this._callbacks[name];
	        }
	      }, this);
	    } else {
	      Pusher.Util.apply(names, function(name) {
	        delete this._callbacks[name];
	      }, this);
	    }
	  };
	
	  function prefix(name) {
	    return "_" + name;
	  }
	
	  Pusher.EventsDispatcher = EventsDispatcher;
	}).call(this);
	
	(function() {
	  /** Builds receivers for JSONP and Script requests.
	   *
	   * Each receiver is an object with following fields:
	   * - number - unique (for the factory instance), numerical id of the receiver
	   * - id - a string ID that can be used in DOM attributes
	   * - name - name of the function triggering the receiver
	   * - callback - callback function
	   *
	   * Receivers are triggered only once, on the first callback call.
	   *
	   * Receivers can be called by their name or by accessing factory object
	   * by the number key.
	   *
	   * @param {String} prefix the prefix used in ids
	   * @param {String} name the name of the object
	   */
	  function ScriptReceiverFactory(prefix, name) {
	    this.lastId = 0;
	    this.prefix = prefix;
	    this.name = name;
	  }
	  var prototype = ScriptReceiverFactory.prototype;
	
	  /** Creates a script receiver.
	   *
	   * @param {Function} callback
	   * @return {ScriptReceiver}
	   */
	  prototype.create = function(callback) {
	    this.lastId++;
	
	    var number = this.lastId;
	    var id = this.prefix + number;
	    var name = this.name + "[" + number + "]";
	
	    var called = false;
	    var callbackWrapper = function() {
	      if (!called) {
	        callback.apply(null, arguments);
	        called = true;
	      }
	    };
	
	    this[number] = callbackWrapper;
	    return { number: number, id: id, name: name, callback: callbackWrapper };
	  };
	
	  /** Removes the script receiver from the list.
	   *
	   * @param {ScriptReceiver} receiver
	   */
	  prototype.remove = function(receiver) {
	    delete this[receiver.number];
	  };
	
	  Pusher.ScriptReceiverFactory = ScriptReceiverFactory;
	  Pusher.ScriptReceivers = new ScriptReceiverFactory(
	    "_pusher_script_", "Pusher.ScriptReceivers"
	  );
	}).call(this);
	
	(function() {
	  /** Sends a generic HTTP GET request using a script tag.
	   *
	   * By constructing URL in a specific way, it can be used for loading
	   * JavaScript resources or JSONP requests. It can notify about errors, but
	   * only in certain environments. Please take care of monitoring the state of
	   * the request yourself.
	   *
	   * @param {String} src
	   */
	  function ScriptRequest(src) {
	    this.src = src;
	  }
	  var prototype = ScriptRequest.prototype;
	
	  /** Sends the actual script request.
	   *
	   * @param {ScriptReceiver} receiver
	   */
	  prototype.send = function(receiver) {
	    var self = this;
	    var errorString = "Error loading " + self.src;
	
	    self.script = document.createElement("script");
	    self.script.id = receiver.id;
	    self.script.src = self.src;
	    self.script.type = "text/javascript";
	    self.script.charset = "UTF-8";
	
	    if (self.script.addEventListener) {
	      self.script.onerror = function() {
	        receiver.callback(errorString);
	      };
	      self.script.onload = function() {
	        receiver.callback(null);
	      };
	    } else {
	      self.script.onreadystatechange = function() {
	        if (self.script.readyState === 'loaded' ||
	            self.script.readyState === 'complete') {
	          receiver.callback(null);
	        }
	      };
	    }
	
	    // Opera<11.6 hack for missing onerror callback
	    if (self.script.async === undefined && document.attachEvent &&
	        /opera/i.test(navigator.userAgent)) {
	      self.errorScript = document.createElement("script");
	      self.errorScript.id = receiver.id + "_error";
	      self.errorScript.text = receiver.name + "('" + errorString + "');";
	      self.script.async = self.errorScript.async = false;
	    } else {
	      self.script.async = true;
	    }
	
	    var head = document.getElementsByTagName('head')[0];
	    head.insertBefore(self.script, head.firstChild);
	    if (self.errorScript) {
	      head.insertBefore(self.errorScript, self.script.nextSibling);
	    }
	  };
	
	  /** Cleans up the DOM remains of the script request. */
	  prototype.cleanup = function() {
	    if (this.script) {
	      this.script.onload = this.script.onerror = null;
	      this.script.onreadystatechange = null;
	    }
	    if (this.script && this.script.parentNode) {
	      this.script.parentNode.removeChild(this.script);
	    }
	    if (this.errorScript && this.errorScript.parentNode) {
	      this.errorScript.parentNode.removeChild(this.errorScript);
	    }
	    this.script = null;
	    this.errorScript = null;
	  };
	
	  Pusher.ScriptRequest = ScriptRequest;
	}).call(this);
	
	;(function() {
	  /** Handles loading dependency files.
	   *
	   * Dependency loaders don't remember whether a resource has been loaded or
	   * not. It is caller's responsibility to make sure the resource is not loaded
	   * twice. This is because it's impossible to detect resource loading status
	   * without knowing its content.
	   *
	   * Options:
	   * - cdn_http - url to HTTP CND
	   * - cdn_https - url to HTTPS CDN
	   * - version - version of pusher-js
	   * - suffix - suffix appended to all names of dependency files
	   *
	   * @param {Object} options
	   */
	  function DependencyLoader(options) {
	    this.options = options;
	    this.receivers = options.receivers || Pusher.ScriptReceivers;
	    this.loading = {};
	  }
	  var prototype = DependencyLoader.prototype;
	
	  /** Loads the dependency from CDN.
	   *
	   * @param  {String} name
	   * @param  {Function} callback
	   */
	  prototype.load = function(name, options, callback) {
	    var self = this;
	
	    if (self.loading[name] && self.loading[name].length > 0) {
	      self.loading[name].push(callback);
	    } else {
	      self.loading[name] = [callback];
	
	      var request = new Pusher.ScriptRequest(self.getPath(name, options));
	      var receiver = self.receivers.create(function(error) {
	        self.receivers.remove(receiver);
	
	        if (self.loading[name]) {
	          var callbacks = self.loading[name];
	          delete self.loading[name];
	
	          var successCallback = function(wasSuccessful) {
	            if (!wasSuccessful) {
	              request.cleanup();
	            }
	          };
	          for (var i = 0; i < callbacks.length; i++) {
	            callbacks[i](error, successCallback);
	          }
	        }
	      });
	      request.send(receiver);
	    }
	  };
	
	  /** Returns a root URL for pusher-js CDN.
	   *
	   * @returns {String}
	   */
	  prototype.getRoot = function(options) {
	    var cdn;
	    var protocol = Pusher.Util.getDocument().location.protocol;
	    if ((options && options.encrypted) || protocol === "https:") {
	      cdn = this.options.cdn_https;
	    } else {
	      cdn = this.options.cdn_http;
	    }
	    // make sure there are no double slashes
	    return cdn.replace(/\/*$/, "") + "/" + this.options.version;
	  };
	
	  /** Returns a full path to a dependency file.
	   *
	   * @param {String} name
	   * @returns {String}
	   */
	  prototype.getPath = function(name, options) {
	    return this.getRoot(options) + '/' + name + this.options.suffix + '.js';
	  };
	
	  Pusher.DependencyLoader = DependencyLoader;
	}).call(this);
	
	;(function() {
	  Pusher.DependenciesReceivers = new Pusher.ScriptReceiverFactory(
	    "_pusher_dependencies", "Pusher.DependenciesReceivers"
	  );
	  Pusher.Dependencies = new Pusher.DependencyLoader({
	    cdn_http: Pusher.cdn_http,
	    cdn_https: Pusher.cdn_https,
	    version: Pusher.VERSION,
	    suffix: Pusher.dependency_suffix,
	    receivers: Pusher.DependenciesReceivers
	  });
	
	  function initialize() {
	    Pusher.ready();
	  }
	
	  // Allows calling a function when the document body is available
	   function onDocumentBody(callback) {
	    if (document.body) {
	      callback();
	    } else {
	      setTimeout(function() {
	        onDocumentBody(callback);
	      }, 0);
	    }
	  }
	
	  function initializeOnDocumentBody() {
	    onDocumentBody(initialize);
	  }
	
	  if (!window.JSON) {
	    Pusher.Dependencies.load("json2", {}, initializeOnDocumentBody);
	  } else {
	    initializeOnDocumentBody();
	  }
	})();
	
	(function() {
	
	  var Base64 = {
	    encode: function (s) {
	      return btoa(utob(s));
	    }
	  };
	
	  var fromCharCode = String.fromCharCode;
	
	  var b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
	  var b64tab = {};
	
	  for (var i = 0, l = b64chars.length; i < l; i++) {
	    b64tab[b64chars.charAt(i)] = i;
	  }
	
	  var cb_utob = function(c) {
	    var cc = c.charCodeAt(0);
	    return cc < 0x80 ? c
	        : cc < 0x800 ? fromCharCode(0xc0 | (cc >>> 6)) +
	                       fromCharCode(0x80 | (cc & 0x3f))
	        : fromCharCode(0xe0 | ((cc >>> 12) & 0x0f)) +
	          fromCharCode(0x80 | ((cc >>>  6) & 0x3f)) +
	          fromCharCode(0x80 | ( cc         & 0x3f));
	  };
	
	  var utob = function(u) {
	    return u.replace(/[^\x00-\x7F]/g, cb_utob);
	  };
	
	  var cb_encode = function(ccc) {
	    var padlen = [0, 2, 1][ccc.length % 3];
	    var ord = ccc.charCodeAt(0) << 16
	      | ((ccc.length > 1 ? ccc.charCodeAt(1) : 0) << 8)
	      | ((ccc.length > 2 ? ccc.charCodeAt(2) : 0));
	    var chars = [
	      b64chars.charAt( ord >>> 18),
	      b64chars.charAt((ord >>> 12) & 63),
	      padlen >= 2 ? '=' : b64chars.charAt((ord >>> 6) & 63),
	      padlen >= 1 ? '=' : b64chars.charAt(ord & 63)
	    ];
	    return chars.join('');
	  };
	
	  var btoa = window.btoa || function(b) {
	    return b.replace(/[\s\S]{1,3}/g, cb_encode);
	  };
	
	  Pusher.Base64 = Base64;
	
	}).call(this);
	
	(function() {
	  /** Sends data via JSONP.
	   *
	   * Data is a key-value map. Its values are JSON-encoded and then passed
	   * through base64. Finally, keys and encoded values are appended to the query
	   * string.
	   *
	   * The class itself does not guarantee raising errors on failures, as it's not
	   * possible to support such feature on all browsers. Instead, JSONP endpoint
	   * should call back in a way that's easy to distinguish from browser calls,
	   * for example by passing a second argument to the receiver.
	   *
	   * @param {String} url
	   * @param {Object} data key-value map of data to be submitted
	   */
	  function JSONPRequest(url, data) {
	    this.url = url;
	    this.data = data;
	  }
	  var prototype = JSONPRequest.prototype;
	
	  /** Sends the actual JSONP request.
	   *
	   * @param {ScriptReceiver} receiver
	   */
	  prototype.send = function(receiver) {
	    if (this.request) {
	      return;
	    }
	
	    var params = Pusher.Util.filterObject(this.data, function(value) {
	      return value !== undefined;
	    });
	    var query = Pusher.Util.map(
	      Pusher.Util.flatten(encodeParamsObject(params)),
	      Pusher.Util.method("join", "=")
	    ).join("&");
	    var url = this.url + "/" + receiver.number + "?" + query;
	
	    this.request = new Pusher.ScriptRequest(url);
	    this.request.send(receiver);
	  };
	
	  /** Cleans up the DOM remains of the JSONP request. */
	  prototype.cleanup = function() {
	    if (this.request) {
	      this.request.cleanup();
	    }
	  };
	
	  function encodeParamsObject(data) {
	    return Pusher.Util.mapObject(data, function(value) {
	      if (typeof value === "object") {
	        value = JSON.stringify(value);
	      }
	      return encodeURIComponent(Pusher.Base64.encode(value.toString()));
	    });
	  }
	
	  Pusher.JSONPRequest = JSONPRequest;
	}).call(this);
	
	(function() {
	  function Timeline(key, session, options) {
	    this.key = key;
	    this.session = session;
	    this.events = [];
	    this.options = options || {};
	    this.sent = 0;
	    this.uniqueID = 0;
	  }
	  var prototype = Timeline.prototype;
	
	  // Log levels
	  Timeline.ERROR = 3;
	  Timeline.INFO = 6;
	  Timeline.DEBUG = 7;
	
	  prototype.log = function(level, event) {
	    if (level <= this.options.level) {
	      this.events.push(
	        Pusher.Util.extend({}, event, { timestamp: Pusher.Util.now() })
	      );
	      if (this.options.limit && this.events.length > this.options.limit) {
	        this.events.shift();
	      }
	    }
	  };
	
	  prototype.error = function(event) {
	    this.log(Timeline.ERROR, event);
	  };
	
	  prototype.info = function(event) {
	    this.log(Timeline.INFO, event);
	  };
	
	  prototype.debug = function(event) {
	    this.log(Timeline.DEBUG, event);
	  };
	
	  prototype.isEmpty = function() {
	    return this.events.length === 0;
	  };
	
	  prototype.send = function(sendJSONP, callback) {
	    var self = this;
	
	    var data = Pusher.Util.extend({
	      session: self.session,
	      bundle: self.sent + 1,
	      key: self.key,
	      lib: "js",
	      version: self.options.version,
	      cluster: self.options.cluster,
	      features: self.options.features,
	      timeline: self.events
	    }, self.options.params);
	
	    self.events = [];
	    sendJSONP(data, function(error, result) {
	      if (!error) {
	        self.sent++;
	      }
	      if (callback) {
	        callback(error, result);
	      }
	    });
	
	    return true;
	  };
	
	  prototype.generateUniqueID = function() {
	    this.uniqueID++;
	    return this.uniqueID;
	  };
	
	  Pusher.Timeline = Timeline;
	}).call(this);
	
	(function() {
	  function TimelineSender(timeline, options) {
	    this.timeline = timeline;
	    this.options = options || {};
	  }
	  var prototype = TimelineSender.prototype;
	
	  prototype.send = function(encrypted, callback) {
	    var self = this;
	
	    if (self.timeline.isEmpty()) {
	      return;
	    }
	
	    var sendJSONP = function(data, callback) {
	      var scheme = "http" + (encrypted ? "s" : "") + "://";
	      var url = scheme + (self.host || self.options.host) + self.options.path;
	      var request = new Pusher.JSONPRequest(url, data);
	
	      var receiver = Pusher.ScriptReceivers.create(function(error, result) {
	        Pusher.ScriptReceivers.remove(receiver);
	        request.cleanup();
	
	        if (result && result.host) {
	          self.host = result.host;
	        }
	        if (callback) {
	          callback(error, result);
	        }
	      });
	      request.send(receiver);
	    };
	    self.timeline.send(sendJSONP, callback);
	  };
	
	  Pusher.TimelineSender = TimelineSender;
	}).call(this);
	
	;(function() {
	  /** Launches all substrategies and emits prioritized connected transports.
	   *
	   * @param {Array} strategies
	   */
	  function BestConnectedEverStrategy(strategies) {
	    this.strategies = strategies;
	  }
	  var prototype = BestConnectedEverStrategy.prototype;
	
	  prototype.isSupported = function() {
	    return Pusher.Util.any(this.strategies, Pusher.Util.method("isSupported"));
	  };
	
	  prototype.connect = function(minPriority, callback) {
	    return connect(this.strategies, minPriority, function(i, runners) {
	      return function(error, handshake) {
	        runners[i].error = error;
	        if (error) {
	          if (allRunnersFailed(runners)) {
	            callback(true);
	          }
	          return;
	        }
	        Pusher.Util.apply(runners, function(runner) {
	          runner.forceMinPriority(handshake.transport.priority);
	        });
	        callback(null, handshake);
	      };
	    });
	  };
	
	  /** Connects to all strategies in parallel.
	   *
	   * Callback builder should be a function that takes two arguments: index
	   * and a list of runners. It should return another function that will be
	   * passed to the substrategy with given index. Runners can be aborted using
	   * abortRunner(s) functions from this class.
	   *
	   * @param  {Array} strategies
	   * @param  {Function} callbackBuilder
	   * @return {Object} strategy runner
	   */
	  function connect(strategies, minPriority, callbackBuilder) {
	    var runners = Pusher.Util.map(strategies, function(strategy, i, _, rs) {
	      return strategy.connect(minPriority, callbackBuilder(i, rs));
	    });
	    return {
	      abort: function() {
	        Pusher.Util.apply(runners, abortRunner);
	      },
	      forceMinPriority: function(p) {
	        Pusher.Util.apply(runners, function(runner) {
	          runner.forceMinPriority(p);
	        });
	      }
	    };
	  }
	
	  function allRunnersFailed(runners) {
	    return Pusher.Util.all(runners, function(runner) {
	      return Boolean(runner.error);
	    });
	  }
	
	  function abortRunner(runner) {
	    if (!runner.error && !runner.aborted) {
	      runner.abort();
	      runner.aborted = true;
	    }
	  }
	
	  Pusher.BestConnectedEverStrategy = BestConnectedEverStrategy;
	}).call(this);
	
	;(function() {
	  /** Caches last successful transport and uses it for following attempts.
	   *
	   * @param {Strategy} strategy
	   * @param {Object} transports
	   * @param {Object} options
	   */
	  function CachedStrategy(strategy, transports, options) {
	    this.strategy = strategy;
	    this.transports = transports;
	    this.ttl = options.ttl || 1800*1000;
	    this.encrypted = options.encrypted;
	    this.timeline = options.timeline;
	  }
	  var prototype = CachedStrategy.prototype;
	
	  prototype.isSupported = function() {
	    return this.strategy.isSupported();
	  };
	
	  prototype.connect = function(minPriority, callback) {
	    var encrypted = this.encrypted;
	    var info = fetchTransportCache(encrypted);
	
	    var strategies = [this.strategy];
	    if (info && info.timestamp + this.ttl >= Pusher.Util.now()) {
	      var transport = this.transports[info.transport];
	      if (transport) {
	        this.timeline.info({
	          cached: true,
	          transport: info.transport,
	          latency: info.latency
	        });
	        strategies.push(new Pusher.SequentialStrategy([transport], {
	          timeout: info.latency * 2 + 1000,
	          failFast: true
	        }));
	      }
	    }
	
	    var startTimestamp = Pusher.Util.now();
	    var runner = strategies.pop().connect(
	      minPriority,
	      function cb(error, handshake) {
	        if (error) {
	          flushTransportCache(encrypted);
	          if (strategies.length > 0) {
	            startTimestamp = Pusher.Util.now();
	            runner = strategies.pop().connect(minPriority, cb);
	          } else {
	            callback(error);
	          }
	        } else {
	          storeTransportCache(
	            encrypted,
	            handshake.transport.name,
	            Pusher.Util.now() - startTimestamp
	          );
	          callback(null, handshake);
	        }
	      }
	    );
	
	    return {
	      abort: function() {
	        runner.abort();
	      },
	      forceMinPriority: function(p) {
	        minPriority = p;
	        if (runner) {
	          runner.forceMinPriority(p);
	        }
	      }
	    };
	  };
	
	  function getTransportCacheKey(encrypted) {
	    return "pusherTransport" + (encrypted ? "Encrypted" : "Unencrypted");
	  }
	
	  function fetchTransportCache(encrypted) {
	    var storage = Pusher.Util.getLocalStorage();
	    if (storage) {
	      try {
	        var serializedCache = storage[getTransportCacheKey(encrypted)];
	        if (serializedCache) {
	          return JSON.parse(serializedCache);
	        }
	      } catch (e) {
	        flushTransportCache(encrypted);
	      }
	    }
	    return null;
	  }
	
	  function storeTransportCache(encrypted, transport, latency) {
	    var storage = Pusher.Util.getLocalStorage();
	    if (storage) {
	      try {
	        storage[getTransportCacheKey(encrypted)] = JSON.stringify({
	          timestamp: Pusher.Util.now(),
	          transport: transport,
	          latency: latency
	        });
	      } catch (e) {
	        // catch over quota exceptions raised by localStorage
	      }
	    }
	  }
	
	  function flushTransportCache(encrypted) {
	    var storage = Pusher.Util.getLocalStorage();
	    if (storage) {
	      try {
	        delete storage[getTransportCacheKey(encrypted)];
	      } catch (e) {
	        // catch exceptions raised by localStorage
	      }
	    }
	  }
	
	  Pusher.CachedStrategy = CachedStrategy;
	}).call(this);
	
	;(function() {
	  /** Runs substrategy after specified delay.
	   *
	   * Options:
	   * - delay - time in miliseconds to delay the substrategy attempt
	   *
	   * @param {Strategy} strategy
	   * @param {Object} options
	   */
	  function DelayedStrategy(strategy, options) {
	    this.strategy = strategy;
	    this.options = { delay: options.delay };
	  }
	  var prototype = DelayedStrategy.prototype;
	
	  prototype.isSupported = function() {
	    return this.strategy.isSupported();
	  };
	
	  prototype.connect = function(minPriority, callback) {
	    var strategy = this.strategy;
	    var runner;
	    var timer = new Pusher.Timer(this.options.delay, function() {
	      runner = strategy.connect(minPriority, callback);
	    });
	
	    return {
	      abort: function() {
	        timer.ensureAborted();
	        if (runner) {
	          runner.abort();
	        }
	      },
	      forceMinPriority: function(p) {
	        minPriority = p;
	        if (runner) {
	          runner.forceMinPriority(p);
	        }
	      }
	    };
	  };
	
	  Pusher.DelayedStrategy = DelayedStrategy;
	}).call(this);
	
	;(function() {
	  /** Launches the substrategy and terminates on the first open connection.
	   *
	   * @param {Strategy} strategy
	   */
	  function FirstConnectedStrategy(strategy) {
	    this.strategy = strategy;
	  }
	  var prototype = FirstConnectedStrategy.prototype;
	
	  prototype.isSupported = function() {
	    return this.strategy.isSupported();
	  };
	
	  prototype.connect = function(minPriority, callback) {
	    var runner = this.strategy.connect(
	      minPriority,
	      function(error, handshake) {
	        if (handshake) {
	          runner.abort();
	        }
	        callback(error, handshake);
	      }
	    );
	    return runner;
	  };
	
	  Pusher.FirstConnectedStrategy = FirstConnectedStrategy;
	}).call(this);
	
	;(function() {
	  /** Proxies method calls to one of substrategies basing on the test function.
	   *
	   * @param {Function} test
	   * @param {Strategy} trueBranch strategy used when test returns true
	   * @param {Strategy} falseBranch strategy used when test returns false
	   */
	  function IfStrategy(test, trueBranch, falseBranch) {
	    this.test = test;
	    this.trueBranch = trueBranch;
	    this.falseBranch = falseBranch;
	  }
	  var prototype = IfStrategy.prototype;
	
	  prototype.isSupported = function() {
	    var branch = this.test() ? this.trueBranch : this.falseBranch;
	    return branch.isSupported();
	  };
	
	  prototype.connect = function(minPriority, callback) {
	    var branch = this.test() ? this.trueBranch : this.falseBranch;
	    return branch.connect(minPriority, callback);
	  };
	
	  Pusher.IfStrategy = IfStrategy;
	}).call(this);
	
	;(function() {
	  /** Loops through strategies with optional timeouts.
	   *
	   * Options:
	   * - loop - whether it should loop through the substrategy list
	   * - timeout - initial timeout for a single substrategy
	   * - timeoutLimit - maximum timeout
	   *
	   * @param {Strategy[]} strategies
	   * @param {Object} options
	   */
	  function SequentialStrategy(strategies, options) {
	    this.strategies = strategies;
	    this.loop = Boolean(options.loop);
	    this.failFast = Boolean(options.failFast);
	    this.timeout = options.timeout;
	    this.timeoutLimit = options.timeoutLimit;
	  }
	  var prototype = SequentialStrategy.prototype;
	
	  prototype.isSupported = function() {
	    return Pusher.Util.any(this.strategies, Pusher.Util.method("isSupported"));
	  };
	
	  prototype.connect = function(minPriority, callback) {
	    var self = this;
	
	    var strategies = this.strategies;
	    var current = 0;
	    var timeout = this.timeout;
	    var runner = null;
	
	    var tryNextStrategy = function(error, handshake) {
	      if (handshake) {
	        callback(null, handshake);
	      } else {
	        current = current + 1;
	        if (self.loop) {
	          current = current % strategies.length;
	        }
	
	        if (current < strategies.length) {
	          if (timeout) {
	            timeout = timeout * 2;
	            if (self.timeoutLimit) {
	              timeout = Math.min(timeout, self.timeoutLimit);
	            }
	          }
	          runner = self.tryStrategy(
	            strategies[current],
	            minPriority,
	            { timeout: timeout, failFast: self.failFast },
	            tryNextStrategy
	          );
	        } else {
	          callback(true);
	        }
	      }
	    };
	
	    runner = this.tryStrategy(
	      strategies[current],
	      minPriority,
	      { timeout: timeout, failFast: this.failFast },
	      tryNextStrategy
	    );
	
	    return {
	      abort: function() {
	        runner.abort();
	      },
	      forceMinPriority: function(p) {
	        minPriority = p;
	        if (runner) {
	          runner.forceMinPriority(p);
	        }
	      }
	    };
	  };
	
	  /** @private */
	  prototype.tryStrategy = function(strategy, minPriority, options, callback) {
	    var timer = null;
	    var runner = null;
	
	    if (options.timeout > 0) {
	      timer = new Pusher.Timer(options.timeout, function() {
	        runner.abort();
	        callback(true);
	      });
	    }
	
	    runner = strategy.connect(minPriority, function(error, handshake) {
	      if (error && timer && timer.isRunning() && !options.failFast) {
	        // advance to the next strategy after the timeout
	        return;
	      }
	      if (timer) {
	        timer.ensureAborted();
	      }
	      callback(error, handshake);
	    });
	
	    return {
	      abort: function() {
	        if (timer) {
	          timer.ensureAborted();
	        }
	        runner.abort();
	      },
	      forceMinPriority: function(p) {
	        runner.forceMinPriority(p);
	      }
	    };
	  };
	
	  Pusher.SequentialStrategy = SequentialStrategy;
	}).call(this);
	
	;(function() {
	  /** Provides a strategy interface for transports.
	   *
	   * @param {String} name
	   * @param {Number} priority
	   * @param {Class} transport
	   * @param {Object} options
	   */
	  function TransportStrategy(name, priority, transport, options) {
	    this.name = name;
	    this.priority = priority;
	    this.transport = transport;
	    this.options = options || {};
	  }
	  var prototype = TransportStrategy.prototype;
	
	  /** Returns whether the transport is supported in the browser.
	   *
	   * @returns {Boolean}
	   */
	  prototype.isSupported = function() {
	    return this.transport.isSupported({
	      encrypted: this.options.encrypted
	    });
	  };
	
	  /** Launches a connection attempt and returns a strategy runner.
	   *
	   * @param  {Function} callback
	   * @return {Object} strategy runner
	   */
	  prototype.connect = function(minPriority, callback) {
	    if (!this.isSupported()) {
	      return failAttempt(new Pusher.Errors.UnsupportedStrategy(), callback);
	    } else if (this.priority < minPriority) {
	      return failAttempt(new Pusher.Errors.TransportPriorityTooLow(), callback);
	    }
	
	    var self = this;
	    var connected = false;
	
	    var transport = this.transport.createConnection(
	      this.name, this.priority, this.options.key, this.options
	    );
	    var handshake = null;
	
	    var onInitialized = function() {
	      transport.unbind("initialized", onInitialized);
	      transport.connect();
	    };
	    var onOpen = function() {
	      handshake = new Pusher.Handshake(transport, function(result) {
	        connected = true;
	        unbindListeners();
	        callback(null, result);
	      });
	    };
	    var onError = function(error) {
	      unbindListeners();
	      callback(error);
	    };
	    var onClosed = function() {
	      unbindListeners();
	      callback(new Pusher.Errors.TransportClosed(transport));
	    };
	
	    var unbindListeners = function() {
	      transport.unbind("initialized", onInitialized);
	      transport.unbind("open", onOpen);
	      transport.unbind("error", onError);
	      transport.unbind("closed", onClosed);
	    };
	
	    transport.bind("initialized", onInitialized);
	    transport.bind("open", onOpen);
	    transport.bind("error", onError);
	    transport.bind("closed", onClosed);
	
	    // connect will be called automatically after initialization
	    transport.initialize();
	
	    return {
	      abort: function() {
	        if (connected) {
	          return;
	        }
	        unbindListeners();
	        if (handshake) {
	          handshake.close();
	        } else {
	          transport.close();
	        }
	      },
	      forceMinPriority: function(p) {
	        if (connected) {
	          return;
	        }
	        if (self.priority < p) {
	          if (handshake) {
	            handshake.close();
	          } else {
	            transport.close();
	          }
	        }
	      }
	    };
	  };
	
	  function failAttempt(error, callback) {
	    Pusher.Util.defer(function() {
	      callback(error);
	    });
	    return {
	      abort: function() {},
	      forceMinPriority: function() {}
	    };
	  }
	
	  Pusher.TransportStrategy = TransportStrategy;
	}).call(this);
	
	(function() {
	  function getGenericURL(baseScheme, params, path) {
	    var scheme = baseScheme + (params.encrypted ? "s" : "");
	    var host = params.encrypted ? params.hostEncrypted : params.hostUnencrypted;
	    return scheme + "://" + host + path;
	  }
	
	  function getGenericPath(key, queryString) {
	    var path = "/app/" + key;
	    var query =
	      "?protocol=" + Pusher.PROTOCOL +
	      "&client=js" +
	      "&version=" + Pusher.VERSION +
	      (queryString ? ("&" + queryString) : "");
	    return path + query;
	  }
	
	  /** URL schemes for different transport types. */
	  Pusher.URLSchemes = {
	    /** Standard WebSocket URL scheme. */
	    ws: {
	      getInitial: function(key, params) {
	        return getGenericURL("ws", params, getGenericPath(key, "flash=false"));
	      }
	    },
	    /** URL scheme for Flash. Same as WebSocket, but with a flash parameter. */
	    flash: {
	      getInitial: function(key, params) {
	        return getGenericURL("ws", params, getGenericPath(key, "flash=true"));
	      }
	    },
	    /** SockJS URL scheme. Supplies the path separately from the initial URL. */
	    sockjs: {
	      getInitial: function(key, params) {
	        return getGenericURL("http", params, params.httpPath || "/pusher", "");
	      },
	      getPath: function(key, params) {
	        return getGenericPath(key);
	      }
	    },
	    /** URL scheme for HTTP transports. Basically, WS scheme with a prefix. */
	    http: {
	      getInitial: function(key, params) {
	        var path = (params.httpPath || "/pusher") + getGenericPath(key);
	        return getGenericURL("http", params, path);
	      }
	    }
	  };
	}).call(this);
	
	(function() {
	  /** Provides universal API for transport connections.
	   *
	   * Transport connection is a low-level object that wraps a connection method
	   * and exposes a simple evented interface for the connection state and
	   * messaging. It does not implement Pusher-specific WebSocket protocol.
	   *
	   * Additionally, it fetches resources needed for transport to work and exposes
	   * an interface for querying transport features.
	   *
	   * States:
	   * - new - initial state after constructing the object
	   * - initializing - during initialization phase, usually fetching resources
	   * - intialized - ready to establish a connection
	   * - connection - when connection is being established
	   * - open - when connection ready to be used
	   * - closed - after connection was closed be either side
	   *
	   * Emits:
	   * - error - after the connection raised an error
	   *
	   * Options:
	   * - encrypted - whether connection should use ssl
	   * - hostEncrypted - host to connect to when connection is encrypted
	   * - hostUnencrypted - host to connect to when connection is not encrypted
	   *
	   * @param {String} key application key
	   * @param {Object} options
	   */
	  function TransportConnection(hooks, name, priority, key, options) {
	    Pusher.EventsDispatcher.call(this);
	
	    this.hooks = hooks;
	    this.name = name;
	    this.priority = priority;
	    this.key = key;
	    this.options = options;
	
	    this.state = "new";
	    this.timeline = options.timeline;
	    this.activityTimeout = options.activityTimeout;
	    this.id = this.timeline.generateUniqueID();
	  }
	  var prototype = TransportConnection.prototype;
	  Pusher.Util.extend(prototype, Pusher.EventsDispatcher.prototype);
	
	  /** Checks whether the transport handles activity checks by itself.
	   *
	   * @return {Boolean}
	   */
	  prototype.handlesActivityChecks = function() {
	    return Boolean(this.hooks.handlesActivityChecks);
	  };
	
	  /** Checks whether the transport supports the ping/pong API.
	   *
	   * @return {Boolean}
	   */
	  prototype.supportsPing = function() {
	    return Boolean(this.hooks.supportsPing);
	  };
	
	  /** Initializes the transport.
	   *
	   * Fetches resources if needed and then transitions to initialized.
	   */
	  prototype.initialize = function() {
	    var self = this;
	
	    self.timeline.info(self.buildTimelineMessage({
	      transport: self.name + (self.options.encrypted ? "s" : "")
	    }));
	
	    if (self.hooks.beforeInitialize) {
	      self.hooks.beforeInitialize.call(self);
	    }
	
	    if (self.hooks.isInitialized()) {
	      self.changeState("initialized");
	    } else if (self.hooks.file) {
	      self.changeState("initializing");
	      Pusher.Dependencies.load(
	        self.hooks.file,
	        { encrypted: self.options.encrypted },
	        function(error, callback) {
	          if (self.hooks.isInitialized()) {
	            self.changeState("initialized");
	            callback(true);
	          } else {
	            if (error) {
	              self.onError(error);
	            }
	            self.onClose();
	            callback(false);
	          }
	        }
	      );
	    } else {
	      self.onClose();
	    }
	  };
	
	  /** Tries to establish a connection.
	   *
	   * @returns {Boolean} false if transport is in invalid state
	   */
	  prototype.connect = function() {
	    var self = this;
	
	    if (self.socket || self.state !== "initialized") {
	      return false;
	    }
	
	    var url = self.hooks.urls.getInitial(self.key, self.options);
	    try {
	      self.socket = self.hooks.getSocket(url, self.options);
	    } catch (e) {
	      Pusher.Util.defer(function() {
	        self.onError(e);
	        self.changeState("closed");
	      });
	      return false;
	    }
	
	    self.bindListeners();
	
	    Pusher.debug("Connecting", { transport: self.name, url: url });
	    self.changeState("connecting");
	    return true;
	  };
	
	  /** Closes the connection.
	   *
	   * @return {Boolean} true if there was a connection to close
	   */
	  prototype.close = function() {
	    if (this.socket) {
	      this.socket.close();
	      return true;
	    } else {
	      return false;
	    }
	  };
	
	  /** Sends data over the open connection.
	   *
	   * @param {String} data
	   * @return {Boolean} true only when in the "open" state
	   */
	  prototype.send = function(data) {
	    var self = this;
	
	    if (self.state === "open") {
	      // Workaround for MobileSafari bug (see https://gist.github.com/2052006)
	      Pusher.Util.defer(function() {
	        if (self.socket) {
	          self.socket.send(data);
	        }
	      });
	      return true;
	    } else {
	      return false;
	    }
	  };
	
	  /** Sends a ping if the connection is open and transport supports it. */
	  prototype.ping = function() {
	    if (this.state === "open" && this.supportsPing()) {
	      this.socket.ping();
	    }
	  };
	
	  /** @private */
	  prototype.onOpen = function() {
	    if (this.hooks.beforeOpen) {
	      this.hooks.beforeOpen(
	        this.socket, this.hooks.urls.getPath(this.key, this.options)
	      );
	    }
	    this.changeState("open");
	    this.socket.onopen = undefined;
	  };
	
	  /** @private */
	  prototype.onError = function(error) {
	    this.emit("error", { type: 'WebSocketError', error: error });
	    this.timeline.error(this.buildTimelineMessage({ error: error.toString() }));
	  };
	
	  /** @private */
	  prototype.onClose = function(closeEvent) {
	    if (closeEvent) {
	      this.changeState("closed", {
	        code: closeEvent.code,
	        reason: closeEvent.reason,
	        wasClean: closeEvent.wasClean
	      });
	    } else {
	      this.changeState("closed");
	    }
	    this.unbindListeners();
	    this.socket = undefined;
	  };
	
	  /** @private */
	  prototype.onMessage = function(message) {
	    this.emit("message", message);
	  };
	
	  /** @private */
	  prototype.onActivity = function() {
	    this.emit("activity");
	  };
	
	  /** @private */
	  prototype.bindListeners = function() {
	    var self = this;
	
	    self.socket.onopen = function() {
	      self.onOpen();
	    };
	    self.socket.onerror = function(error) {
	      self.onError(error);
	    };
	    self.socket.onclose = function(closeEvent) {
	      self.onClose(closeEvent);
	    };
	    self.socket.onmessage = function(message) {
	      self.onMessage(message);
	    };
	
	    if (self.supportsPing()) {
	      self.socket.onactivity = function() { self.onActivity(); };
	    }
	  };
	
	  /** @private */
	  prototype.unbindListeners = function() {
	    if (this.socket) {
	      this.socket.onopen = undefined;
	      this.socket.onerror = undefined;
	      this.socket.onclose = undefined;
	      this.socket.onmessage = undefined;
	      if (this.supportsPing()) {
	        this.socket.onactivity = undefined;
	      }
	    }
	  };
	
	  /** @private */
	  prototype.changeState = function(state, params) {
	    this.state = state;
	    this.timeline.info(this.buildTimelineMessage({
	      state: state,
	      params: params
	    }));
	    this.emit(state, params);
	  };
	
	  /** @private */
	  prototype.buildTimelineMessage = function(message) {
	    return Pusher.Util.extend({ cid: this.id }, message);
	  };
	
	  Pusher.TransportConnection = TransportConnection;
	}).call(this);
	
	(function() {
	  /** Provides interface for transport connection instantiation.
	   *
	   * Takes transport-specific hooks as the only argument, which allow checking
	   * for transport support and creating its connections.
	   *
	   * Supported hooks:
	   * - file - the name of the file to be fetched during initialization
	   * - urls - URL scheme to be used by transport
	   * - handlesActivityCheck - true when the transport handles activity checks
	   * - supportsPing - true when the transport has a ping/activity API
	   * - isSupported - tells whether the transport is supported in the environment
	   * - getSocket - creates a WebSocket-compatible transport socket
	   *
	   * See transports.js for specific implementations.
	   *
	   * @param {Object} hooks object containing all needed transport hooks
	   */
	  function Transport(hooks) {
	    this.hooks = hooks;
	  }
	  var prototype = Transport.prototype;
	
	  /** Returns whether the transport is supported in the environment.
	   *
	   * @param {Object} environment the environment details (encryption, settings)
	   * @returns {Boolean} true when the transport is supported
	   */
	  prototype.isSupported = function(environment) {
	    return this.hooks.isSupported(environment);
	  };
	
	  /** Creates a transport connection.
	   *
	   * @param {String} name
	   * @param {Number} priority
	   * @param {String} key the application key
	   * @param {Object} options
	   * @returns {TransportConnection}
	   */
	  prototype.createConnection = function(name, priority, key, options) {
	    return new Pusher.TransportConnection(
	      this.hooks, name, priority, key, options
	    );
	  };
	
	  Pusher.Transport = Transport;
	}).call(this);
	
	(function() {
	  /** WebSocket transport.
	   *
	   * Uses native WebSocket implementation, including MozWebSocket supported by
	   * earlier Firefox versions.
	   */
	  Pusher.WSTransport = new Pusher.Transport({
	    urls: Pusher.URLSchemes.ws,
	    handlesActivityChecks: false,
	    supportsPing: false,
	
	    isInitialized: function() {
	      return Boolean(window.WebSocket || window.MozWebSocket);
	    },
	    isSupported: function() {
	      return Boolean(window.WebSocket || window.MozWebSocket);
	    },
	    getSocket: function(url) {
	      var Constructor = window.WebSocket || window.MozWebSocket;
	      return new Constructor(url);
	    }
	  });
	
	  /** Flash transport using the WebSocket protocol. */
	  Pusher.FlashTransport = new Pusher.Transport({
	    file: "flashfallback",
	    urls: Pusher.URLSchemes.flash,
	    handlesActivityChecks: false,
	    supportsPing: false,
	
	    isSupported: function() {
	      try {
	        return Boolean(new ActiveXObject('ShockwaveFlash.ShockwaveFlash'));
	      } catch (e1) {
	        try {
	          var nav = Pusher.Util.getNavigator();
	          return Boolean(
	            nav &&
	            nav.mimeTypes &&
	            nav.mimeTypes["application/x-shockwave-flash"] !== undefined
	          );
	        } catch (e2) {
	          return false;
	        }
	      }
	    },
	    beforeInitialize: function() {
	      if (window.WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR === undefined) {
	        window.WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR = true;
	      }
	      window.WEB_SOCKET_SWF_LOCATION =
	        Pusher.Dependencies.getRoot({ encrypted: this.options.encrypted }) +
	        "/WebSocketMain.swf";
	    },
	    isInitialized: function() {
	      return window.FlashWebSocket !== undefined;
	    },
	    getSocket: function(url) {
	      return new FlashWebSocket(url);
	    }
	  });
	
	  /** SockJS transport. */
	  Pusher.SockJSTransport = new Pusher.Transport({
	    file: "sockjs",
	    urls: Pusher.URLSchemes.sockjs,
	    handlesActivityChecks: true,
	    supportsPing: false,
	
	    isSupported: function() {
	      return true;
	    },
	    isInitialized: function() {
	      return window.SockJS !== undefined;
	    },
	    getSocket: function(url, options) {
	      return new SockJS(url, null, {
	        js_path: Pusher.Dependencies.getPath("sockjs", {
	          encrypted: options.encrypted
	        }),
	        ignore_null_origin: options.ignoreNullOrigin
	      });
	    },
	    beforeOpen: function(socket, path) {
	      socket.send(JSON.stringify({
	        path: path
	      }));
	    }
	  });
	
	  var httpConfiguration = {
	    urls: Pusher.URLSchemes.http,
	    handlesActivityChecks: false,
	    supportsPing: true,
	    isInitialized: function() {
	      return Boolean(Pusher.HTTP.Socket);
	    }
	  };
	
	  var streamingConfiguration = Pusher.Util.extend(
	    { getSocket: function(url) {
	        return Pusher.HTTP.getStreamingSocket(url);
	      }
	    },
	    httpConfiguration
	  );
	  var pollingConfiguration = Pusher.Util.extend(
	    { getSocket: function(url) {
	        return Pusher.HTTP.getPollingSocket(url);
	      }
	    },
	    httpConfiguration
	  );
	
	  var xhrConfiguration = {
	    file: "xhr",
	    isSupported: Pusher.Util.isXHRSupported
	  };
	  var xdrConfiguration = {
	    file: "xdr",
	    isSupported: function(environment) {
	      return Pusher.Util.isXDRSupported(environment.encrypted);
	    }
	  };
	
	  /** HTTP streaming transport using CORS-enabled XMLHttpRequest. */
	  Pusher.XHRStreamingTransport = new Pusher.Transport(
	    Pusher.Util.extend({}, streamingConfiguration, xhrConfiguration)
	  );
	  /** HTTP streaming transport using XDomainRequest (IE 8,9). */
	  Pusher.XDRStreamingTransport = new Pusher.Transport(
	    Pusher.Util.extend({}, streamingConfiguration, xdrConfiguration)
	  );
	  /** HTTP long-polling transport using CORS-enabled XMLHttpRequest. */
	  Pusher.XHRPollingTransport = new Pusher.Transport(
	    Pusher.Util.extend({}, pollingConfiguration, xhrConfiguration)
	  );
	  /** HTTP long-polling transport using XDomainRequest (IE 8,9). */
	  Pusher.XDRPollingTransport = new Pusher.Transport(
	    Pusher.Util.extend({}, pollingConfiguration, xdrConfiguration)
	  );
	}).call(this);
	
	;(function() {
	  /** Creates transport connections monitored by a transport manager.
	   *
	   * When a transport is closed, it might mean the environment does not support
	   * it. It's possible that messages get stuck in an intermediate buffer or
	   * proxies terminate inactive connections. To combat these problems,
	   * assistants monitor the connection lifetime, report unclean exits and
	   * adjust ping timeouts to keep the connection active. The decision to disable
	   * a transport is the manager's responsibility.
	   *
	   * @param {TransportManager} manager
	   * @param {TransportConnection} transport
	   * @param {Object} options
	   */
	  function AssistantToTheTransportManager(manager, transport, options) {
	    this.manager = manager;
	    this.transport = transport;
	    this.minPingDelay = options.minPingDelay;
	    this.maxPingDelay = options.maxPingDelay;
	    this.pingDelay = undefined;
	  }
	  var prototype = AssistantToTheTransportManager.prototype;
	
	  /** Creates a transport connection.
	   *
	   * This function has the same API as Transport#createConnection.
	   *
	   * @param {String} name
	   * @param {Number} priority
	   * @param {String} key the application key
	   * @param {Object} options
	   * @returns {TransportConnection}
	   */
	  prototype.createConnection = function(name, priority, key, options) {
	    var self = this;
	
	    options = Pusher.Util.extend({}, options, {
	      activityTimeout: self.pingDelay
	    });
	    var connection = self.transport.createConnection(
	      name, priority, key, options
	    );
	
	    var openTimestamp = null;
	
	    var onOpen = function() {
	      connection.unbind("open", onOpen);
	      connection.bind("closed", onClosed);
	      openTimestamp = Pusher.Util.now();
	    };
	    var onClosed = function(closeEvent) {
	      connection.unbind("closed", onClosed);
	
	      if (closeEvent.code === 1002 || closeEvent.code === 1003) {
	        // we don't want to use transports not obeying the protocol
	        self.manager.reportDeath();
	      } else if (!closeEvent.wasClean && openTimestamp) {
	        // report deaths only for short-living transport
	        var lifespan = Pusher.Util.now() - openTimestamp;
	        if (lifespan < 2 * self.maxPingDelay) {
	          self.manager.reportDeath();
	          self.pingDelay = Math.max(lifespan / 2, self.minPingDelay);
	        }
	      }
	    };
	
	    connection.bind("open", onOpen);
	    return connection;
	  };
	
	  /** Returns whether the transport is supported in the environment.
	   *
	   * This function has the same API as Transport#isSupported. Might return false
	   * when the manager decides to kill the transport.
	   *
	   * @param {Object} environment the environment details (encryption, settings)
	   * @returns {Boolean} true when the transport is supported
	   */
	  prototype.isSupported = function(environment) {
	    return this.manager.isAlive() && this.transport.isSupported(environment);
	  };
	
	  Pusher.AssistantToTheTransportManager = AssistantToTheTransportManager;
	}).call(this);
	
	;(function() {
	  /** Keeps track of the number of lives left for a transport.
	   *
	   * In the beginning of a session, transports may be assigned a number of
	   * lives. When an AssistantToTheTransportManager instance reports a transport
	   * connection closed uncleanly, the transport loses a life. When the number
	   * of lives drops to zero, the transport gets disabled by its manager.
	   *
	   * @param {Object} options
	   */
	  function TransportManager(options) {
	    this.options = options || {};
	    this.livesLeft = this.options.lives || Infinity;
	  }
	  var prototype = TransportManager.prototype;
	
	  /** Creates a assistant for the transport.
	   *
	   * @param {Transport} transport
	   * @returns {AssistantToTheTransportManager}
	   */
	  prototype.getAssistant = function(transport) {
	    return new Pusher.AssistantToTheTransportManager(this, transport, {
	      minPingDelay: this.options.minPingDelay,
	      maxPingDelay: this.options.maxPingDelay
	    });
	  };
	
	  /** Returns whether the transport has any lives left.
	   *
	   * @returns {Boolean}
	   */
	  prototype.isAlive = function() {
	    return this.livesLeft > 0;
	  };
	
	  /** Takes one life from the transport. */
	  prototype.reportDeath = function() {
	    this.livesLeft -= 1;
	  };
	
	  Pusher.TransportManager = TransportManager;
	}).call(this);
	
	;(function() {
	  var StrategyBuilder = {
	    /** Transforms a JSON scheme to a strategy tree.
	     *
	     * @param {Array} scheme JSON strategy scheme
	     * @param {Object} options a hash of symbols to be included in the scheme
	     * @returns {Strategy} strategy tree that's represented by the scheme
	     */
	    build: function(scheme, options) {
	      var context = Pusher.Util.extend({}, globalContext, options);
	      return evaluate(scheme, context)[1].strategy;
	    }
	  };
	
	  var transports = {
	    ws: Pusher.WSTransport,
	    flash: Pusher.FlashTransport,
	    sockjs: Pusher.SockJSTransport,
	    xhr_streaming: Pusher.XHRStreamingTransport,
	    xdr_streaming: Pusher.XDRStreamingTransport,
	    xhr_polling: Pusher.XHRPollingTransport,
	    xdr_polling: Pusher.XDRPollingTransport
	  };
	
	  var UnsupportedStrategy = {
	    isSupported: function() {
	      return false;
	    },
	    connect: function(_, callback) {
	      var deferred = Pusher.Util.defer(function() {
	        callback(new Pusher.Errors.UnsupportedStrategy());
	      });
	      return {
	        abort: function() {
	          deferred.ensureAborted();
	        },
	        forceMinPriority: function() {}
	      };
	    }
	  };
	
	  // DSL bindings
	
	  function returnWithOriginalContext(f) {
	    return function(context) {
	      return [f.apply(this, arguments), context];
	    };
	  }
	
	  var globalContext = {
	    extend: function(context, first, second) {
	      return [Pusher.Util.extend({}, first, second), context];
	    },
	
	    def: function(context, name, value) {
	      if (context[name] !== undefined) {
	        throw "Redefining symbol " + name;
	      }
	      context[name] = value;
	      return [undefined, context];
	    },
	
	    def_transport: function(context, name, type, priority, options, manager) {
	      var transportClass = transports[type];
	      if (!transportClass) {
	        throw new Pusher.Errors.UnsupportedTransport(type);
	      }
	
	      var enabled =
	        (!context.enabledTransports ||
	          Pusher.Util.arrayIndexOf(context.enabledTransports, name) !== -1) &&
	        (!context.disabledTransports ||
	          Pusher.Util.arrayIndexOf(context.disabledTransports, name) === -1) &&
	        (name !== "flash" || context.disableFlash !== true);
	
	      var transport;
	      if (enabled) {
	        transport = new Pusher.TransportStrategy(
	          name,
	          priority,
	          manager ? manager.getAssistant(transportClass) : transportClass,
	          Pusher.Util.extend({
	            key: context.key,
	            encrypted: context.encrypted,
	            timeline: context.timeline,
	            ignoreNullOrigin: context.ignoreNullOrigin
	          }, options)
	        );
	      } else {
	        transport = UnsupportedStrategy;
	      }
	
	      var newContext = context.def(context, name, transport)[1];
	      newContext.transports = context.transports || {};
	      newContext.transports[name] = transport;
	      return [undefined, newContext];
	    },
	
	    transport_manager: returnWithOriginalContext(function(_, options) {
	      return new Pusher.TransportManager(options);
	    }),
	
	    sequential: returnWithOriginalContext(function(_, options) {
	      var strategies = Array.prototype.slice.call(arguments, 2);
	      return new Pusher.SequentialStrategy(strategies, options);
	    }),
	
	    cached: returnWithOriginalContext(function(context, ttl, strategy){
	      return new Pusher.CachedStrategy(strategy, context.transports, {
	        ttl: ttl,
	        timeline: context.timeline,
	        encrypted: context.encrypted
	      });
	    }),
	
	    first_connected: returnWithOriginalContext(function(_, strategy) {
	      return new Pusher.FirstConnectedStrategy(strategy);
	    }),
	
	    best_connected_ever: returnWithOriginalContext(function() {
	      var strategies = Array.prototype.slice.call(arguments, 1);
	      return new Pusher.BestConnectedEverStrategy(strategies);
	    }),
	
	    delayed: returnWithOriginalContext(function(_, delay, strategy) {
	      return new Pusher.DelayedStrategy(strategy, { delay: delay });
	    }),
	
	    "if": returnWithOriginalContext(function(_, test, trueBranch, falseBranch) {
	      return new Pusher.IfStrategy(test, trueBranch, falseBranch);
	    }),
	
	    is_supported: returnWithOriginalContext(function(_, strategy) {
	      return function() {
	        return strategy.isSupported();
	      };
	    })
	  };
	
	  // DSL interpreter
	
	  function isSymbol(expression) {
	    return (typeof expression === "string") && expression.charAt(0) === ":";
	  }
	
	  function getSymbolValue(expression, context) {
	    return context[expression.slice(1)];
	  }
	
	  function evaluateListOfExpressions(expressions, context) {
	    if (expressions.length === 0) {
	      return [[], context];
	    }
	    var head = evaluate(expressions[0], context);
	    var tail = evaluateListOfExpressions(expressions.slice(1), head[1]);
	    return [[head[0]].concat(tail[0]), tail[1]];
	  }
	
	  function evaluateString(expression, context) {
	    if (!isSymbol(expression)) {
	      return [expression, context];
	    }
	    var value = getSymbolValue(expression, context);
	    if (value === undefined) {
	      throw "Undefined symbol " + expression;
	    }
	    return [value, context];
	  }
	
	  function evaluateArray(expression, context) {
	    if (isSymbol(expression[0])) {
	      var f = getSymbolValue(expression[0], context);
	      if (expression.length > 1) {
	        if (typeof f !== "function") {
	          throw "Calling non-function " + expression[0];
	        }
	        var args = [Pusher.Util.extend({}, context)].concat(
	          Pusher.Util.map(expression.slice(1), function(arg) {
	            return evaluate(arg, Pusher.Util.extend({}, context))[0];
	          })
	        );
	        return f.apply(this, args);
	      } else {
	        return [f, context];
	      }
	    } else {
	      return evaluateListOfExpressions(expression, context);
	    }
	  }
	
	  function evaluate(expression, context) {
	    var expressionType = typeof expression;
	    if (typeof expression === "string") {
	      return evaluateString(expression, context);
	    } else if (typeof expression === "object") {
	      if (expression instanceof Array && expression.length > 0) {
	        return evaluateArray(expression, context);
	      }
	    }
	    return [expression, context];
	  }
	
	  Pusher.StrategyBuilder = StrategyBuilder;
	}).call(this);
	
	;(function() {
	  /**
	   * Provides functions for handling Pusher protocol-specific messages.
	   */
	  var Protocol = {};
	
	  /**
	   * Decodes a message in a Pusher format.
	   *
	   * Throws errors when messages are not parse'able.
	   *
	   * @param  {Object} message
	   * @return {Object}
	   */
	  Protocol.decodeMessage = function(message) {
	    try {
	      var params = JSON.parse(message.data);
	      if (typeof params.data === 'string') {
	        try {
	          params.data = JSON.parse(params.data);
	        } catch (e) {
	          if (!(e instanceof SyntaxError)) {
	            // TODO looks like unreachable code
	            // https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/JSON/parse
	            throw e;
	          }
	        }
	      }
	      return params;
	    } catch (e) {
	      throw { type: 'MessageParseError', error: e, data: message.data};
	    }
	  };
	
	  /**
	   * Encodes a message to be sent.
	   *
	   * @param  {Object} message
	   * @return {String}
	   */
	  Protocol.encodeMessage = function(message) {
	    return JSON.stringify(message);
	  };
	
	  /** Processes a handshake message and returns appropriate actions.
	   *
	   * Returns an object with an 'action' and other action-specific properties.
	   *
	   * There are three outcomes when calling this function. First is a successful
	   * connection attempt, when pusher:connection_established is received, which
	   * results in a 'connected' action with an 'id' property. When passed a
	   * pusher:error event, it returns a result with action appropriate to the
	   * close code and an error. Otherwise, it raises an exception.
	   *
	   * @param {String} message
	   * @result Object
	   */
	  Protocol.processHandshake = function(message) {
	    message = this.decodeMessage(message);
	
	    if (message.event === "pusher:connection_established") {
	      if (!message.data.activity_timeout) {
	        throw "No activity timeout specified in handshake";
	      }
	      return {
	        action: "connected",
	        id: message.data.socket_id,
	        activityTimeout: message.data.activity_timeout * 1000
	      };
	    } else if (message.event === "pusher:error") {
	      // From protocol 6 close codes are sent only once, so this only
	      // happens when connection does not support close codes
	      return {
	        action: this.getCloseAction(message.data),
	        error: this.getCloseError(message.data)
	      };
	    } else {
	      throw "Invalid handshake";
	    }
	  };
	
	  /**
	   * Dispatches the close event and returns an appropriate action name.
	   *
	   * See:
	   * 1. https://developer.mozilla.org/en-US/docs/WebSockets/WebSockets_reference/CloseEvent
	   * 2. http://pusher.com/docs/pusher_protocol
	   *
	   * @param  {CloseEvent} closeEvent
	   * @return {String} close action name
	   */
	  Protocol.getCloseAction = function(closeEvent) {
	    if (closeEvent.code < 4000) {
	      // ignore 1000 CLOSE_NORMAL, 1001 CLOSE_GOING_AWAY,
	      //        1005 CLOSE_NO_STATUS, 1006 CLOSE_ABNORMAL
	      // ignore 1007...3999
	      // handle 1002 CLOSE_PROTOCOL_ERROR, 1003 CLOSE_UNSUPPORTED,
	      //        1004 CLOSE_TOO_LARGE
	      if (closeEvent.code >= 1002 && closeEvent.code <= 1004) {
	        return "backoff";
	      } else {
	        return null;
	      }
	    } else if (closeEvent.code === 4000) {
	      return "ssl_only";
	    } else if (closeEvent.code < 4100) {
	      return "refused";
	    } else if (closeEvent.code < 4200) {
	      return "backoff";
	    } else if (closeEvent.code < 4300) {
	      return "retry";
	    } else {
	      // unknown error
	      return "refused";
	    }
	  };
	
	  /**
	   * Returns an error or null basing on the close event.
	   *
	   * Null is returned when connection was closed cleanly. Otherwise, an object
	   * with error details is returned.
	   *
	   * @param  {CloseEvent} closeEvent
	   * @return {Object} error object
	   */
	  Protocol.getCloseError = function(closeEvent) {
	    if (closeEvent.code !== 1000 && closeEvent.code !== 1001) {
	      return {
	        type: 'PusherError',
	        data: {
	          code: closeEvent.code,
	          message: closeEvent.reason || closeEvent.message
	        }
	      };
	    } else {
	      return null;
	    }
	  };
	
	  Pusher.Protocol = Protocol;
	}).call(this);
	
	;(function() {
	  /**
	   * Provides Pusher protocol interface for transports.
	   *
	   * Emits following events:
	   * - message - on received messages
	   * - ping - on ping requests
	   * - pong - on pong responses
	   * - error - when the transport emits an error
	   * - closed - after closing the transport
	   *
	   * It also emits more events when connection closes with a code.
	   * See Protocol.getCloseAction to get more details.
	   *
	   * @param {Number} id
	   * @param {AbstractTransport} transport
	   */
	  function Connection(id, transport) {
	    Pusher.EventsDispatcher.call(this);
	
	    this.id = id;
	    this.transport = transport;
	    this.activityTimeout = transport.activityTimeout;
	    this.bindListeners();
	  }
	  var prototype = Connection.prototype;
	  Pusher.Util.extend(prototype, Pusher.EventsDispatcher.prototype);
	
	  /** Returns whether used transport handles activity checks by itself
	   *
	   * @returns {Boolean} true if activity checks are handled by the transport
	   */
	  prototype.handlesActivityChecks = function() {
	    return this.transport.handlesActivityChecks();
	  };
	
	  /** Sends raw data.
	   *
	   * @param {String} data
	   */
	  prototype.send = function(data) {
	    return this.transport.send(data);
	  };
	
	  /** Sends an event.
	   *
	   * @param {String} name
	   * @param {String} data
	   * @param {String} [channel]
	   * @returns {Boolean} whether message was sent or not
	   */
	  prototype.send_event = function(name, data, channel) {
	    var message = { event: name, data: data };
	    if (channel) {
	      message.channel = channel;
	    }
	    Pusher.debug('Event sent', message);
	    return this.send(Pusher.Protocol.encodeMessage(message));
	  };
	
	  /** Sends a ping message to the server.
	   *
	   * Basing on the underlying transport, it might send either transport's
	   * protocol-specific ping or pusher:ping event.
	   */
	  prototype.ping = function() {
	    if (this.transport.supportsPing()) {
	      this.transport.ping();
	    } else {
	      this.send_event('pusher:ping', {});
	    }
	  };
	
	  /** Closes the connection. */
	  prototype.close = function() {
	    this.transport.close();
	  };
	
	  /** @private */
	  prototype.bindListeners = function() {
	    var self = this;
	
	    var listeners = {
	      message: function(m) {
	        var message;
	        try {
	          message = Pusher.Protocol.decodeMessage(m);
	        } catch(e) {
	          self.emit('error', {
	            type: 'MessageParseError',
	            error: e,
	            data: m.data
	          });
	        }
	
	        if (message !== undefined) {
	          Pusher.debug('Event recd', message);
	
	          switch (message.event) {
	            case 'pusher:error':
	              self.emit('error', { type: 'PusherError', data: message.data });
	              break;
	            case 'pusher:ping':
	              self.emit("ping");
	              break;
	            case 'pusher:pong':
	              self.emit("pong");
	              break;
	          }
	          self.emit('message', message);
	        }
	      },
	      activity: function() {
	        self.emit("activity");
	      },
	      error: function(error) {
	        self.emit("error", { type: "WebSocketError", error: error });
	      },
	      closed: function(closeEvent) {
	        unbindListeners();
	
	        if (closeEvent && closeEvent.code) {
	          self.handleCloseEvent(closeEvent);
	        }
	
	        self.transport = null;
	        self.emit("closed");
	      }
	    };
	
	    var unbindListeners = function() {
	      Pusher.Util.objectApply(listeners, function(listener, event) {
	        self.transport.unbind(event, listener);
	      });
	    };
	
	    Pusher.Util.objectApply(listeners, function(listener, event) {
	      self.transport.bind(event, listener);
	    });
	  };
	
	  /** @private */
	  prototype.handleCloseEvent = function(closeEvent) {
	    var action = Pusher.Protocol.getCloseAction(closeEvent);
	    var error = Pusher.Protocol.getCloseError(closeEvent);
	    if (error) {
	      this.emit('error', error);
	    }
	    if (action) {
	      this.emit(action);
	    }
	  };
	
	  Pusher.Connection = Connection;
	}).call(this);
	
	;(function() {
	  /**
	   * Handles Pusher protocol handshakes for transports.
	   *
	   * Calls back with a result object after handshake is completed. Results
	   * always have two fields:
	   * - action - string describing action to be taken after the handshake
	   * - transport - the transport object passed to the constructor
	   *
	   * Different actions can set different additional properties on the result.
	   * In the case of 'connected' action, there will be a 'connection' property
	   * containing a Connection object for the transport. Other actions should
	   * carry an 'error' property.
	   *
	   * @param {AbstractTransport} transport
	   * @param {Function} callback
	   */
	  function Handshake(transport, callback) {
	    this.transport = transport;
	    this.callback = callback;
	    this.bindListeners();
	  }
	  var prototype = Handshake.prototype;
	
	  prototype.close = function() {
	    this.unbindListeners();
	    this.transport.close();
	  };
	
	  /** @private */
	  prototype.bindListeners = function() {
	    var self = this;
	
	    self.onMessage = function(m) {
	      self.unbindListeners();
	
	      try {
	        var result = Pusher.Protocol.processHandshake(m);
	        if (result.action === "connected") {
	          self.finish("connected", {
	            connection: new Pusher.Connection(result.id, self.transport),
	            activityTimeout: result.activityTimeout
	          });
	        } else {
	          self.finish(result.action, { error: result.error });
	          self.transport.close();
	        }
	      } catch (e) {
	        self.finish("error", { error: e });
	        self.transport.close();
	      }
	    };
	
	    self.onClosed = function(closeEvent) {
	      self.unbindListeners();
	
	      var action = Pusher.Protocol.getCloseAction(closeEvent) || "backoff";
	      var error = Pusher.Protocol.getCloseError(closeEvent);
	      self.finish(action, { error: error });
	    };
	
	    self.transport.bind("message", self.onMessage);
	    self.transport.bind("closed", self.onClosed);
	  };
	
	  /** @private */
	  prototype.unbindListeners = function() {
	    this.transport.unbind("message", this.onMessage);
	    this.transport.unbind("closed", this.onClosed);
	  };
	
	  /** @private */
	  prototype.finish = function(action, params) {
	    this.callback(
	      Pusher.Util.extend({ transport: this.transport, action: action }, params)
	    );
	  };
	
	  Pusher.Handshake = Handshake;
	}).call(this);
	
	;(function() {
	  /** Manages connection to Pusher.
	   *
	   * Uses a strategy (currently only default), timers and network availability
	   * info to establish a connection and export its state. In case of failures,
	   * manages reconnection attempts.
	   *
	   * Exports state changes as following events:
	   * - "state_change", { previous: p, current: state }
	   * - state
	   *
	   * States:
	   * - initialized - initial state, never transitioned to
	   * - connecting - connection is being established
	   * - connected - connection has been fully established
	   * - disconnected - on requested disconnection
	   * - unavailable - after connection timeout or when there's no network
	   * - failed - when the connection strategy is not supported
	   *
	   * Options:
	   * - unavailableTimeout - time to transition to unavailable state
	   * - activityTimeout - time after which ping message should be sent
	   * - pongTimeout - time for Pusher to respond with pong before reconnecting
	   *
	   * @param {String} key application key
	   * @param {Object} options
	   */
	  function ConnectionManager(key, options) {
	    Pusher.EventsDispatcher.call(this);
	
	    this.key = key;
	    this.options = options || {};
	    this.state = "initialized";
	    this.connection = null;
	    this.encrypted = !!options.encrypted;
	    this.timeline = this.options.timeline;
	
	    this.connectionCallbacks = this.buildConnectionCallbacks();
	    this.errorCallbacks = this.buildErrorCallbacks();
	    this.handshakeCallbacks = this.buildHandshakeCallbacks(this.errorCallbacks);
	
	    var self = this;
	
	    Pusher.Network.bind("online", function() {
	      self.timeline.info({ netinfo: "online" });
	      if (self.state === "connecting" || self.state === "unavailable") {
	        self.retryIn(0);
	      }
	    });
	    Pusher.Network.bind("offline", function() {
	      self.timeline.info({ netinfo: "offline" });
	      if (self.connection) {
	        self.sendActivityCheck();
	      }
	    });
	
	    this.updateStrategy();
	  }
	  var prototype = ConnectionManager.prototype;
	
	  Pusher.Util.extend(prototype, Pusher.EventsDispatcher.prototype);
	
	  /** Establishes a connection to Pusher.
	   *
	   * Does nothing when connection is already established. See top-level doc
	   * to find events emitted on connection attempts.
	   */
	  prototype.connect = function() {
	    if (this.connection || this.runner) {
	      return;
	    }
	    if (!this.strategy.isSupported()) {
	      this.updateState("failed");
	      return;
	    }
	    this.updateState("connecting");
	    this.startConnecting();
	    this.setUnavailableTimer();
	  };
	
	  /** Sends raw data.
	   *
	   * @param {String} data
	   */
	  prototype.send = function(data) {
	    if (this.connection) {
	      return this.connection.send(data);
	    } else {
	      return false;
	    }
	  };
	
	  /** Sends an event.
	   *
	   * @param {String} name
	   * @param {String} data
	   * @param {String} [channel]
	   * @returns {Boolean} whether message was sent or not
	   */
	  prototype.send_event = function(name, data, channel) {
	    if (this.connection) {
	      return this.connection.send_event(name, data, channel);
	    } else {
	      return false;
	    }
	  };
	
	  /** Closes the connection. */
	  prototype.disconnect = function() {
	    this.disconnectInternally();
	    this.updateState("disconnected");
	  };
	
	  prototype.isEncrypted = function() {
	    return this.encrypted;
	  };
	
	  /** @private */
	  prototype.startConnecting = function() {
	    var self = this;
	    var callback = function(error, handshake) {
	      if (error) {
	        self.runner = self.strategy.connect(0, callback);
	      } else {
	        if (handshake.action === "error") {
	          self.emit("error", { type: "HandshakeError", error: handshake.error });
	          self.timeline.error({ handshakeError: handshake.error });
	        } else {
	          self.abortConnecting(); // we don't support switching connections yet
	          self.handshakeCallbacks[handshake.action](handshake);
	        }
	      }
	    };
	    self.runner = self.strategy.connect(0, callback);
	  };
	
	  /** @private */
	  prototype.abortConnecting = function() {
	    if (this.runner) {
	      this.runner.abort();
	      this.runner = null;
	    }
	  };
	
	  /** @private */
	  prototype.disconnectInternally = function() {
	    this.abortConnecting();
	    this.clearRetryTimer();
	    this.clearUnavailableTimer();
	    if (this.connection) {
	      var connection = this.abandonConnection();
	      connection.close();
	    }
	  };
	
	  /** @private */
	  prototype.updateStrategy = function() {
	    this.strategy = this.options.getStrategy({
	      key: this.key,
	      timeline: this.timeline,
	      encrypted: this.encrypted
	    });
	  };
	
	  /** @private */
	  prototype.retryIn = function(delay) {
	    var self = this;
	    self.timeline.info({ action: "retry", delay: delay });
	    if (delay > 0) {
	      self.emit("connecting_in", Math.round(delay / 1000));
	    }
	    self.retryTimer = new Pusher.Timer(delay || 0, function() {
	      self.disconnectInternally();
	      self.connect();
	    });
	  };
	
	  /** @private */
	  prototype.clearRetryTimer = function() {
	    if (this.retryTimer) {
	      this.retryTimer.ensureAborted();
	      this.retryTimer = null;
	    }
	  };
	
	  /** @private */
	  prototype.setUnavailableTimer = function() {
	    var self = this;
	    self.unavailableTimer = new Pusher.Timer(
	      self.options.unavailableTimeout,
	      function() {
	        self.updateState("unavailable");
	      }
	    );
	  };
	
	  /** @private */
	  prototype.clearUnavailableTimer = function() {
	    if (this.unavailableTimer) {
	      this.unavailableTimer.ensureAborted();
	    }
	  };
	
	  /** @private */
	  prototype.sendActivityCheck = function() {
	    var self = this;
	    self.stopActivityCheck();
	    self.connection.ping();
	    // wait for pong response
	    self.activityTimer = new Pusher.Timer(
	      self.options.pongTimeout,
	      function() {
	        self.timeline.error({ pong_timed_out: self.options.pongTimeout });
	        self.retryIn(0);
	      }
	    );
	  };
	
	  /** @private */
	  prototype.resetActivityCheck = function() {
	    var self = this;
	    self.stopActivityCheck();
	    // send ping after inactivity
	    if (!self.connection.handlesActivityChecks()) {
	      self.activityTimer = new Pusher.Timer(self.activityTimeout, function() {
	        self.sendActivityCheck();
	      });
	    }
	  };
	
	  /** @private */
	  prototype.stopActivityCheck = function() {
	    if (this.activityTimer) {
	      this.activityTimer.ensureAborted();
	    }
	  };
	
	  /** @private */
	  prototype.buildConnectionCallbacks = function() {
	    var self = this;
	    return {
	      message: function(message) {
	        // includes pong messages from server
	        self.resetActivityCheck();
	        self.emit('message', message);
	      },
	      ping: function() {
	        self.send_event('pusher:pong', {});
	      },
	      activity: function() {
	        self.resetActivityCheck();
	      },
	      error: function(error) {
	        // just emit error to user - socket will already be closed by browser
	        self.emit("error", { type: "WebSocketError", error: error });
	      },
	      closed: function() {
	        self.abandonConnection();
	        if (self.shouldRetry()) {
	          self.retryIn(1000);
	        }
	      }
	    };
	  };
	
	  /** @private */
	  prototype.buildHandshakeCallbacks = function(errorCallbacks) {
	    var self = this;
	    return Pusher.Util.extend({}, errorCallbacks, {
	      connected: function(handshake) {
	        self.activityTimeout = Math.min(
	          self.options.activityTimeout,
	          handshake.activityTimeout,
	          handshake.connection.activityTimeout || Infinity
	        );
	        self.clearUnavailableTimer();
	        self.setConnection(handshake.connection);
	        self.socket_id = self.connection.id;
	        self.updateState("connected", { socket_id: self.socket_id });
	      }
	    });
	  };
	
	  /** @private */
	  prototype.buildErrorCallbacks = function() {
	    var self = this;
	
	    function withErrorEmitted(callback) {
	      return function(result) {
	        if (result.error) {
	          self.emit("error", { type: "WebSocketError", error: result.error });
	        }
	        callback(result);
	      };
	    }
	
	    return {
	      ssl_only: withErrorEmitted(function() {
	        self.encrypted = true;
	        self.updateStrategy();
	        self.retryIn(0);
	      }),
	      refused: withErrorEmitted(function() {
	        self.disconnect();
	      }),
	      backoff: withErrorEmitted(function() {
	        self.retryIn(1000);
	      }),
	      retry: withErrorEmitted(function() {
	        self.retryIn(0);
	      })
	    };
	  };
	
	  /** @private */
	  prototype.setConnection = function(connection) {
	    this.connection = connection;
	    for (var event in this.connectionCallbacks) {
	      this.connection.bind(event, this.connectionCallbacks[event]);
	    }
	    this.resetActivityCheck();
	  };
	
	  /** @private */
	  prototype.abandonConnection = function() {
	    if (!this.connection) {
	      return;
	    }
	    this.stopActivityCheck();
	    for (var event in this.connectionCallbacks) {
	      this.connection.unbind(event, this.connectionCallbacks[event]);
	    }
	    var connection = this.connection;
	    this.connection = null;
	    return connection;
	  };
	
	  /** @private */
	  prototype.updateState = function(newState, data) {
	    var previousState = this.state;
	    this.state = newState;
	    if (previousState !== newState) {
	      Pusher.debug('State changed', previousState + ' -> ' + newState);
	      this.timeline.info({ state: newState, params: data });
	      this.emit('state_change', { previous: previousState, current: newState });
	      this.emit(newState, data);
	    }
	  };
	
	  /** @private */
	  prototype.shouldRetry = function() {
	    return this.state === "connecting" || this.state === "connected";
	  };
	
	  Pusher.ConnectionManager = ConnectionManager;
	}).call(this);
	
	;(function() {
	  /** Really basic interface providing network availability info.
	   *
	   * Emits:
	   * - online - when browser goes online
	   * - offline - when browser goes offline
	   */
	  function NetInfo() {
	    Pusher.EventsDispatcher.call(this);
	
	    var self = this;
	    // This is okay, as IE doesn't support this stuff anyway.
	    if (window.addEventListener !== undefined) {
	      window.addEventListener("online", function() {
	        self.emit('online');
	      }, false);
	      window.addEventListener("offline", function() {
	        self.emit('offline');
	      }, false);
	    }
	  }
	  Pusher.Util.extend(NetInfo.prototype, Pusher.EventsDispatcher.prototype);
	
	  var prototype = NetInfo.prototype;
	
	  /** Returns whether browser is online or not
	   *
	   * Offline means definitely offline (no connection to router).
	   * Inverse does NOT mean definitely online (only currently supported in Safari
	   * and even there only means the device has a connection to the router).
	   *
	   * @return {Boolean}
	   */
	  prototype.isOnline = function() {
	    if (window.navigator.onLine === undefined) {
	      return true;
	    } else {
	      return window.navigator.onLine;
	    }
	  };
	
	  Pusher.NetInfo = NetInfo;
	  Pusher.Network = new NetInfo();
	}).call(this);
	
	;(function() {
	  /** Represents a collection of members of a presence channel. */
	  function Members() {
	    this.reset();
	  }
	  var prototype = Members.prototype;
	
	  /** Returns member's info for given id.
	   *
	   * Resulting object containts two fields - id and info.
	   *
	   * @param {Number} id
	   * @return {Object} member's info or null
	   */
	  prototype.get = function(id) {
	    if (Object.prototype.hasOwnProperty.call(this.members, id)) {
	      return {
	        id: id,
	        info: this.members[id]
	      };
	    } else {
	      return null;
	    }
	  };
	
	  /** Calls back for each member in unspecified order.
	   *
	   * @param  {Function} callback
	   */
	  prototype.each = function(callback) {
	    var self = this;
	    Pusher.Util.objectApply(self.members, function(member, id) {
	      callback(self.get(id));
	    });
	  };
	
	  /** Updates the id for connected member. For internal use only. */
	  prototype.setMyID = function(id) {
	    this.myID = id;
	  };
	
	  /** Handles subscription data. For internal use only. */
	  prototype.onSubscription = function(subscriptionData) {
	    this.members = subscriptionData.presence.hash;
	    this.count = subscriptionData.presence.count;
	    this.me = this.get(this.myID);
	  };
	
	  /** Adds a new member to the collection. For internal use only. */
	  prototype.addMember = function(memberData) {
	    if (this.get(memberData.user_id) === null) {
	      this.count++;
	    }
	    this.members[memberData.user_id] = memberData.user_info;
	    return this.get(memberData.user_id);
	  };
	
	  /** Adds a member from the collection. For internal use only. */
	  prototype.removeMember = function(memberData) {
	    var member = this.get(memberData.user_id);
	    if (member) {
	      delete this.members[memberData.user_id];
	      this.count--;
	    }
	    return member;
	  };
	
	  /** Resets the collection to the initial state. For internal use only. */
	  prototype.reset = function() {
	    this.members = {};
	    this.count = 0;
	    this.myID = null;
	    this.me = null;
	  };
	
	  Pusher.Members = Members;
	}).call(this);
	
	;(function() {
	  /** Provides base public channel interface with an event emitter.
	   *
	   * Emits:
	   * - pusher:subscription_succeeded - after subscribing successfully
	   * - other non-internal events
	   *
	   * @param {String} name
	   * @param {Pusher} pusher
	   */
	  function Channel(name, pusher) {
	    Pusher.EventsDispatcher.call(this, function(event, data) {
	      Pusher.debug('No callbacks on ' + name + ' for ' + event);
	    });
	
	    this.name = name;
	    this.pusher = pusher;
	    this.subscribed = false;
	  }
	  var prototype = Channel.prototype;
	  Pusher.Util.extend(prototype, Pusher.EventsDispatcher.prototype);
	
	  /** Skips authorization, since public channels don't require it.
	   *
	   * @param {Function} callback
	   */
	  prototype.authorize = function(socketId, callback) {
	    return callback(false, {});
	  };
	
	  /** Triggers an event */
	  prototype.trigger = function(event, data) {
	    if (event.indexOf("client-") !== 0) {
	      throw new Pusher.Errors.BadEventName(
	        "Event '" + event + "' does not start with 'client-'"
	      );
	    }
	    return this.pusher.send_event(event, data, this.name);
	  };
	
	  /** Signals disconnection to the channel. For internal use only. */
	  prototype.disconnect = function() {
	    this.subscribed = false;
	  };
	
	  /** Handles an event. For internal use only.
	   *
	   * @param {String} event
	   * @param {*} data
	   */
	  prototype.handleEvent = function(event, data) {
	    if (event.indexOf("pusher_internal:") === 0) {
	      if (event === "pusher_internal:subscription_succeeded") {
	        this.subscribed = true;
	        this.emit("pusher:subscription_succeeded", data);
	      }
	    } else {
	      this.emit(event, data);
	    }
	  };
	
	  /** Sends a subscription request. For internal use only. */
	  prototype.subscribe = function() {
	    var self = this;
	
	    self.authorize(self.pusher.connection.socket_id, function(error, data) {
	      if (error) {
	        self.handleEvent('pusher:subscription_error', data);
	      } else {
	        self.pusher.send_event('pusher:subscribe', {
	          auth: data.auth,
	          channel_data: data.channel_data,
	          channel: self.name
	        });
	      }
	    });
	  };
	
	  /** Sends an unsubscription request. For internal use only. */
	  prototype.unsubscribe = function() {
	    this.pusher.send_event('pusher:unsubscribe', {
	      channel: this.name
	    });
	  };
	
	  Pusher.Channel = Channel;
	}).call(this);
	
	;(function() {
	  /** Extends public channels to provide private channel interface.
	   *
	   * @param {String} name
	   * @param {Pusher} pusher
	   */
	  function PrivateChannel(name, pusher) {
	    Pusher.Channel.call(this, name, pusher);
	  }
	  var prototype = PrivateChannel.prototype;
	  Pusher.Util.extend(prototype, Pusher.Channel.prototype);
	
	  /** Authorizes the connection to use the channel.
	   *
	   * @param  {String} socketId
	   * @param  {Function} callback
	   */
	  prototype.authorize = function(socketId, callback) {
	    var authorizer = new Pusher.Channel.Authorizer(this, this.pusher.config);
	    return authorizer.authorize(socketId, callback);
	  };
	
	  Pusher.PrivateChannel = PrivateChannel;
	}).call(this);
	
	;(function() {
	  /** Adds presence channel functionality to private channels.
	   *
	   * @param {String} name
	   * @param {Pusher} pusher
	   */
	  function PresenceChannel(name, pusher) {
	    Pusher.PrivateChannel.call(this, name, pusher);
	    this.members = new Pusher.Members();
	  }
	  var prototype = PresenceChannel.prototype;
	  Pusher.Util.extend(prototype, Pusher.PrivateChannel.prototype);
	
	  /** Authenticates the connection as a member of the channel.
	   *
	   * @param  {String} socketId
	   * @param  {Function} callback
	   */
	  prototype.authorize = function(socketId, callback) {
	    var _super = Pusher.PrivateChannel.prototype.authorize;
	    var self = this;
	    _super.call(self, socketId, function(error, authData) {
	      if (!error) {
	        if (authData.channel_data === undefined) {
	          Pusher.warn(
	            "Invalid auth response for channel '" +
	            self.name +
	            "', expected 'channel_data' field"
	          );
	          callback("Invalid auth response");
	          return;
	        }
	        var channelData = JSON.parse(authData.channel_data);
	        self.members.setMyID(channelData.user_id);
	      }
	      callback(error, authData);
	    });
	  };
	
	  /** Handles presence and subscription events. For internal use only.
	   *
	   * @param {String} event
	   * @param {*} data
	   */
	  prototype.handleEvent = function(event, data) {
	    switch (event) {
	      case "pusher_internal:subscription_succeeded":
	        this.members.onSubscription(data);
	        this.subscribed = true;
	        this.emit("pusher:subscription_succeeded", this.members);
	        break;
	      case "pusher_internal:member_added":
	        var addedMember = this.members.addMember(data);
	        this.emit('pusher:member_added', addedMember);
	        break;
	      case "pusher_internal:member_removed":
	        var removedMember = this.members.removeMember(data);
	        if (removedMember) {
	          this.emit('pusher:member_removed', removedMember);
	        }
	        break;
	      default:
	        Pusher.PrivateChannel.prototype.handleEvent.call(this, event, data);
	    }
	  };
	
	  /** Resets the channel state, including members map. For internal use only. */
	  prototype.disconnect = function() {
	    this.members.reset();
	    Pusher.PrivateChannel.prototype.disconnect.call(this);
	  };
	
	  Pusher.PresenceChannel = PresenceChannel;
	}).call(this);
	
	;(function() {
	  /** Handles a channel map. */
	  function Channels() {
	    this.channels = {};
	  }
	  var prototype = Channels.prototype;
	
	  /** Creates or retrieves an existing channel by its name.
	   *
	   * @param {String} name
	   * @param {Pusher} pusher
	   * @return {Channel}
	   */
	  prototype.add = function(name, pusher) {
	    if (!this.channels[name]) {
	      this.channels[name] = createChannel(name, pusher);
	    }
	    return this.channels[name];
	  };
	
	  /** Returns a list of all channels
	   *
	   * @return {Array}
	   */
	  prototype.all = function(name) {
	    return Pusher.Util.values(this.channels);
	  };
	
	  /** Finds a channel by its name.
	   *
	   * @param {String} name
	   * @return {Channel} channel or null if it doesn't exist
	   */
	  prototype.find = function(name) {
	    return this.channels[name];
	  };
	
	  /** Removes a channel from the map.
	   *
	   * @param {String} name
	   */
	  prototype.remove = function(name) {
	    var channel = this.channels[name];
	    delete this.channels[name];
	    return channel;
	  };
	
	  /** Proxies disconnection signal to all channels. */
	  prototype.disconnect = function() {
	    Pusher.Util.objectApply(this.channels, function(channel) {
	      channel.disconnect();
	    });
	  };
	
	  function createChannel(name, pusher) {
	    if (name.indexOf('private-') === 0) {
	      return new Pusher.PrivateChannel(name, pusher);
	    } else if (name.indexOf('presence-') === 0) {
	      return new Pusher.PresenceChannel(name, pusher);
	    } else {
	      return new Pusher.Channel(name, pusher);
	    }
	  }
	
	  Pusher.Channels = Channels;
	}).call(this);
	
	;(function() {
	  Pusher.Channel.Authorizer = function(channel, options) {
	    this.channel = channel;
	    this.type = options.authTransport;
	
	    this.options = options;
	    this.authOptions = (options || {}).auth || {};
	  };
	
	  Pusher.Channel.Authorizer.prototype = {
	    composeQuery: function(socketId) {
	      var query = 'socket_id=' + encodeURIComponent(socketId) +
	        '&channel_name=' + encodeURIComponent(this.channel.name);
	
	      for(var i in this.authOptions.params) {
	        query += "&" + encodeURIComponent(i) + "=" + encodeURIComponent(this.authOptions.params[i]);
	      }
	
	      return query;
	    },
	
	    authorize: function(socketId, callback) {
	      return Pusher.authorizers[this.type].call(this, socketId, callback);
	    }
	  };
	
	  var nextAuthCallbackID = 1;
	
	  Pusher.auth_callbacks = {};
	  Pusher.authorizers = {
	    ajax: function(socketId, callback){
	      var self = this, xhr;
	
	      if (Pusher.XHR) {
	        xhr = new Pusher.XHR();
	      } else {
	        xhr = (window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
	      }
	
	      xhr.open("POST", self.options.authEndpoint, true);
	
	      // add request headers
	      xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	      for(var headerName in this.authOptions.headers) {
	        xhr.setRequestHeader(headerName, this.authOptions.headers[headerName]);
	      }
	
	      xhr.onreadystatechange = function() {
	        if (xhr.readyState === 4) {
	          if (xhr.status === 200) {
	            var data, parsed = false;
	
	            try {
	              data = JSON.parse(xhr.responseText);
	              parsed = true;
	            } catch (e) {
	              callback(true, 'JSON returned from webapp was invalid, yet status code was 200. Data was: ' + xhr.responseText);
	            }
	
	            if (parsed) { // prevents double execution.
	              callback(false, data);
	            }
	          } else {
	            Pusher.warn("Couldn't get auth info from your webapp", xhr.status);
	            callback(true, xhr.status);
	          }
	        }
	      };
	
	      xhr.send(this.composeQuery(socketId));
	      return xhr;
	    },
	
	    jsonp: function(socketId, callback){
	      if(this.authOptions.headers !== undefined) {
	        Pusher.warn("Warn", "To send headers with the auth request, you must use AJAX, rather than JSONP.");
	      }
	
	      var callbackName = nextAuthCallbackID.toString();
	      nextAuthCallbackID++;
	
	      var document = Pusher.Util.getDocument();
	      var script = document.createElement("script");
	      // Hacked wrapper.
	      Pusher.auth_callbacks[callbackName] = function(data) {
	        callback(false, data);
	      };
	
	      var callback_name = "Pusher.auth_callbacks['" + callbackName + "']";
	      script.src = this.options.authEndpoint +
	        '?callback=' +
	        encodeURIComponent(callback_name) +
	        '&' +
	        this.composeQuery(socketId);
	
	      var head = document.getElementsByTagName("head")[0] || document.documentElement;
	      head.insertBefore( script, head.firstChild );
	    }
	  };
	}).call(this);
	
	
	
	/*** EXPORTS FROM exports-loader ***/
	module.exports = this.Pusher
	}.call(window));

/***/ },
/* 65 */
/***/ function(module, exports) {

	'use strict';
	
	campaignPusherService.$inject = ["gon", "$window", "$timeout", "$pusher", "pusherWrapper"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = campaignPusherService;
	/*@ngInject*/
	
	function campaignPusherService(gon, $window, $timeout, $pusher, pusherWrapper) {
	  var pusher, channel, pusherTimeout;
	  var boundCallbacks = [];
	
	  var createPusher = function createPusher() {
	    $timeout.cancel(pusherTimeout);
	    if (!pusher) {
	      pusher = $pusher(pusherWrapper.createPusher(gon.pusher.app_id, gon.pusher.options));
	      channel = pusher.subscribe(gon.pusher.channel);
	      boundCallbacks.forEach(function (boundCallback) {
	        channel.bind(boundCallback.bindMessage, boundCallback.callback);
	      });
	    }
	  };
	
	  var timeoutPusher = function timeoutPusher() {
	    pusherTimeout = $timeout(function () {
	      if (pusher) {
	        pusher.disconnect();
	        pusher = null;
	      }
	    }, 1000 * 30);
	  };
	
	  $window.campaignPusherService = {
	    start: function start() {
	      createPusher();
	      $window.addEventListener('focus', createPusher);
	      $window.addEventListener('blur', timeoutPusher);
	    },
	    forceStart: createPusher,
	    bind: function bind(bindMessage, callback) {
	      boundCallbacks.push({ bindMessage: bindMessage, callback: callback });
	      if (pusher) {
	        channel.bind(bindMessage, callback);
	      }
	    },
	    active: function active() {
	      return !!pusher;
	    },
	    push: function push(channelName, json) {
	      boundCallbacks.forEach(function (boundCallback) {
	        if (boundCallback.bindMessage === channelName) {
	          boundCallback.callback(json);
	        }
	      });
	    }
	  };
	
	  return $window.campaignPusherService;
	}

/***/ },
/* 66 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	campaignShareModalDirective.$inject = ["$modal", "i18n", "gon", "$window", "gogoEvents"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = campaignShareModalDirective;
	/*@ngInject*/
	
	function campaignShareModalDirective($modal, i18n, gon, $window, gogoEvents) {
	  var launchEmailAfterHide = false;
	  return {
	    scope: {},
	    replace: true,
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.share_info = gon.share;
	      var modal = $modal({
	        scope: scope,
	        template: __webpack_require__(67),
	        show: gon.show_share_modal
	      });
	      scope.shareFacebook = function () {
	        // TODO EVENTS: id=chu1n fixtype=captureEvent name=click_fb_share category-new=TBD subsystem=campaign-page . review
	        gogoEvents.captureEvent('click_fb_share');
	        scope.openWindow(scope.share_info.facebook_share_url);
	      };
	      scope.openWindow = function (url) {
	        $window.open(url, '', 'width=640, height=480, top=' + ($window.innerHeight / 2 - 480 / 2) + ', left=' + ($window.innerWidth / 2 - 640 / 2));
	      };
	
	      scope.onEmailClick = function () {
	        launchEmailAfterHide = true;
	        modal.hide();
	      };
	
	      scope.$on('modal.hide', function (event, hidingModal) {
	        if (modal === hidingModal) {
	          if (launchEmailAfterHide) {
	            scope.$broadcast('emailImporter.launch');
	            launchEmailAfterHide = false;
	          }
	        } else {
	          modal.show();
	        }
	      });
	    }
	  };
	}

/***/ },
/* 67 */
/***/ function(module, exports) {

	module.exports = "<div id=\"share_modal\" class=\"modal i-modal i-share-modal\">\n  <div class=\"modal-dialog\">\n    <div class=\"modal-content\">\n      <a class=\"modal-close\" href=\"\" ng-click=\"$hide()\" aria-hidden=\"true\"><svg><use xlink:href=\"#icon-icon-close\"></use></svg></a>\n      <svg class=\"i-green-check-icon\"><use xlink:href=\"#icon-icon-check\"></use></svg>\n      <div class=\"i-green-check-title\">{{::i18n.t('share_modal.your_campaign_is_live')}}</div>\n      <div class=\"i-start-sharing\">\n        <h3>{{::i18n.t('share_modal.get_on_your_way')}}</h3>\n        <div>{{::i18n.t('share_modal.start_sharing')}}</div>\n      </div>\n\n      <div class=\"i-social-promote\">{{::i18n.t('share_modal.promote_social')}}</div>\n\n      <div class=\"shareModalSocial\">\n        <a class=\"shareModalSocial-icon\" href=\"\" ng-click=\"shareFacebook()\">\n          <svg class=\"socialSquare socialSquare--facebook\"><use xlink:href=\"#icon-icon-facebook\"></use></svg>\n        </a>\n        <a class=\"shareModalSocial-icon\" ng-href=\"{{share_info.twitter_share_url}}\">\n          <svg class=\"socialSquare socialSquare--twitter\"><use xlink:href=\"#icon-icon-twitter\"></use></svg>\n        </a>\n        <a class=\"shareModalSocial-icon\" href=\"\" ng-click=\"openWindow(share_info.google_plus_share_url)\">\n          <svg class=\"socialSquare socialSquare--gplus\"><use xlink:href=\"#icon-icon-gplus\"></use></svg>\n        </a>\n      </div>\n\n      <div class=\"i-email-promote\">{{::i18n.t('share_modal.promote_email')}}</div>\n\n      <a href=\"\" class=\"i-email i-cta-1 i-cta-1--grey\" email-importer email-importer-click=\"onEmailClick()\">\n        <svg><use xlink:href=\"#icon-icon-mail\"></use></svg>\n        <span>{{::i18n.t('share_modal.connect_email')}}</span>\n      </a>\n\n      <div class=\"i-link-promote\">{{::i18n.t('share_modal.share_link')}}</div>\n\n      <div class=\"i-link-url\">\n        <input type=\"text\" class=\"i-text-field\" value=\"{{share_info.sharing_url}}\" />\n      </div>\n    </div>\n  </div>\n</div>\n</div>\n";

/***/ },
/* 68 */
/***/ function(module, exports) {

	'use strict';
	
	contributeButtonGaTrackingDirective.$inject = ["ga", "gon"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = contributeButtonGaTrackingDirective;
	/*@ngInject*/
	
	function contributeButtonGaTrackingDirective(ga, gon) {
	  return {
	    scope: {
	      gaPerkName: '@',
	      gaAction: '@',
	      gaLabel: '@',
	      gaSecretPerk: '='
	    },
	    link: function link(scope, element) {
	      element.bind('click', function () {
	        var coupon;
	        if (scope.gaPerkName) {
	          var perkLabel = scope.gaSecretPerk ? 'Secret Perk' : 'Perk';
	          coupon = perkLabel + ' | ' + gon.ga_impression_data.name + ' | ' + scope.gaPerkName;
	        } else {
	          coupon = 'No Perk';
	        }
	
	        // TODO EVENTS: id=jei5i fixtype=infra subsystem=ga-ecommerce . unify EC event usage
	        ga('ec:addProduct', _.merge({}, gon.ga_impression_data, { coupon: coupon }));
	        ga('ec:setAction', 'add', {});
	        ga('ec:setAction', 'click', {});
	        // TODO EVENTS: id=aiz2z fixtype=bare-ga subsystem=ga-ecommerce action=unknown label=unknown name-new=TBD . Fix mislabeled category/action/label
	        ga('send', 'event', scope.gaAction, scope.gaLabel);
	
	        if (gon && gon.tracking_info && gon.tracking_info.google_analytics_id) {
	          // TODO EVENTS: id=yuz4e fixtype=ga-create subsystem=ga-ecommerce . unify campaign creators
	          ga('create', gon.tracking_info.google_analytics_id, 'auto', { 'name': 'campaign' });
	          ga('campaign.require', 'ec', 'ec.js');
	          ga('campaign.ec:addProduct', _.merge({}, gon.ga_impression_data, { coupon: coupon }));
	          ga('campaign.ec:setAction', 'add', {});
	          ga('campaign.ec:setAction', 'click', {});
	          // TODO EVENTS: id=eix1t fixtype=campaigner-analytics category=dynamic action=dynamic subsystem=ga-ecommerce . Fix mislabeled category/action/label in directive
	          ga('campaign.send', 'event', scope.gaAction, scope.gaLabel);
	        }
	      });
	    }
	  };
	}

/***/ },
/* 69 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	desktopApprovalButtonDirective.$inject = ["$modal", "i18n", "browser", "$http"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = desktopApprovalButtonDirective;
	/*@ngInject*/
	
	function desktopApprovalButtonDirective($modal, i18n, browser, $http) {
	  return {
	    scope: {
	      approvalHref: '@approvalHref'
	    },
	    replace: true,
	    link: function link(scope, element) {
	      scope.launchText = i18n.t("campaign_editor.buttons.launch_campaign");
	
	      var showModal = function showModal() {
	        $modal({
	          scope: scope,
	          template: __webpack_require__(70)
	        });
	      };
	
	      scope.publishAndRefresh = function () {
	        scope.launchText = i18n.t("campaign_editor.buttons.launching");
	        $http.post(scope.approvalHref).then(function () {
	          browser.refreshPage();
	        });
	      };
	
	      scope.i18n = i18n;
	      element.bind('click', showModal);
	    }
	  };
	}

/***/ },
/* 70 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal i-modal i-confirm-launch-modal\">\n  <div class=\"modal-dialog\">\n    <div class=\"modal-content\">\n      <a class=\"modal-close\" href=\"\" ng-click=\"$hide()\" aria-hidden=\"true\"><svg><use xlink:href=\"#icon-icon-close\"></use></svg></a>\n      <h2>{{ i18n.t(\"campaign_editor.confirm_publish.confirm_launch\") }}</h2>\n      <p>{{ i18n.t(\"campaign_editor.confirm_publish.are_you_sure_you_want_to_launch\") }}</p>\n      <div class=\"i-button-row\">\n        <a class=\"i-cta-1 i-cta-1--grey\" href=\"\" ng-click=\"$hide()\">{{ i18n.t(\"cancel\") }}</a>\n        <a class=\"i-cta-1\" href=\"\" ng-click=\"publishAndRefresh()\">{{ launchText }}</a>\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 71 */
/***/ function(module, exports) {

	'use strict';
	
	desktopCampaignPageDirective.$inject = ["gon", "ga", "$window", "$state", "$stateParams"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = desktopCampaignPageDirective;
	/*@ngInject*/
	
	function desktopCampaignPageDirective(gon, ga, $window, $state, $stateParams) {
	  var gaTracking = function gaTracking() {
	    if (gon && gon.tracking_info && gon.tracking_info.google_analytics_id) {
	      // TODO EVENTS: id=iw1oo fixtype=ga-create subsystem=ga-ecommerce . unify campaign creator
	      ga('create', gon.tracking_info.google_analytics_id, 'auto', { 'name': 'campaign' });
	      ga('campaign.require', 'ec', 'ec.js');
	      ga('campaign.ec:addImpression', gon.ga_impression_data);
	      ga('campaign.ec:addProduct', gon.ga_impression_data);
	      ga('campaign.ec:setAction', 'detail', {});
	      // TODO EVENTS: id=oo8ee subsystem=campaigner-analytics fixtype=pageview . review campaigner ecommerce
	      ga('campaign.send', 'pageview', gon.pageview_data.analytics_friendly_url);
	    }
	
	    ga('ec:addImpression', gon.ga_impression_data);
	    ga('ec:addProduct', gon.ga_impression_data);
	    ga('ec:setAction', 'detail', {});
	    // TODO EVENTS: id=dae4i fixtype=infra subsystem=campaign-page . unify contentGroup usage
	    ga('set', 'contentGroup1', 'Campaign');
	    // TODO EVENTS: id=ju6ph fixtype=pageview subsystem=campaign-page . review pageview
	    ga('send', 'pageview', gon.pageview_data.analytics_friendly_url);
	  };
	
	  var setupFacebookAnalytics = function setupFacebookAnalytics(trackingInfo) {
	    $window.fb_param = {
	      'pixel_id': trackingInfo.fb_pixel_id,
	      'value': trackingInfo.amount,
	      'currency': trackingInfo.currency_iso_code
	    };
	  };
	
	  var setupGoogleTracking = function setupGoogleTracking(trackingInfo) {
	    // TODO EVENTS: id=zoo6w fixtype=gaq subsystem=campaign-page . pageview also here
	    $window._gaq = [['campaign._setAccount', trackingInfo.google_analytics_id], ['campaign._trackPageview']];
	    setTimeout(pushAdjustedBounceEvent, 30000);
	  };
	
	  var pushAdjustedBounceEvent = function pushAdjustedBounceEvent() {
	    // TODO EVENTS: id=zoo6y fixtype=gaq category=30_seconds category-new=TBD action=read subsystem=campaign-page . Upgrade from _gaq to modern usage
	    $window._gaq.push(['campaign._trackEvent', '30_seconds', 'read']);
	  };
	
	  return {
	    scope: {},
	    link: function link(scope) {
	      gaTracking();
	      if (gon.tracking_info) {
	        var trackingInfo = gon.tracking_info;
	        if (trackingInfo.fb_pixel_id) {
	          setupFacebookAnalytics(trackingInfo);
	        }
	        if (trackingInfo.google_analytics_id) {
	          setupGoogleTracking(trackingInfo);
	        }
	      }
	      function scrollToPerk() {
	        var perkIdStr = "#perk_id_" + $stateParams.perkId;
	        $("html, body").animate({ scrollTop: $(perkIdStr).offset().top }, 600);
	      }
	
	      angular.element(document).ready(function () {
	        if ($state.current.name == "perks") {
	          if ($stateParams.perkId) {
	            scrollToPerk();
	          } else {
	            $state.transitionTo('story');
	          }
	        }
	      });
	    }
	  };
	}

/***/ },
/* 72 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	desktopCommentDirective.$inject = ["$window", "i18n", "gon", "campaignComments", "flash", "browser", "$modal", "contributionsApi", "ga", "gogoEvents"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = desktopCommentDirective;
	/*@ngInject*/
	
	function desktopCommentDirective($window, i18n, gon, campaignComments, flash, browser, $modal, contributionsApi, ga, gogoEvents) {
	  return {
	    scope: {
	      comment: '='
	    },
	    template: __webpack_require__(73),
	    link: function link(scope) {
	
	      scope.i18n = i18n;
	      scope.current_user = gon.current_user;
	      scope.canViewFundingDetails = scope.current_user && (scope.current_user.is_admin || scope.current_user.on_campaign_team);
	      scope.contributions = null;
	      scope.commandCenterPath = gon.urls.command_center_path;
	
	      scope.showFundingDetails = function () {
	        ga('send', 'event', 'Comments', 'Click View Funding Details', 'Project ID: ' + gon.campaign.id);
	        gogoEvents.captureEvent('comments_click_view_funding_details', {
	          project_id: gon.campaign.id
	        });
	        if (!scope.contributions) {
	          contributionsApi.getContributions({ filter_account: scope.comment.account_id }).then(function (response) {
	            scope.contributions = response.data.response;
	          });
	        }
	
	        $modal({
	          template: __webpack_require__(74),
	          scope: scope
	        });
	      };
	
	      scope.deleteComment = function (comment) {
	        if ($window.confirm(i18n.t('deleting_comment_cant_be_undone') + '\n' + i18n.t('are_you_sure_you_want_to_continue'))) {
	          campaignComments.deleteComment(comment).then(function () {
	            flash.addMessage('info', i18n.t('delete_success'));
	          }, function (response) {
	            flash.addMessage('error', response.data.error_description);
	          });
	        }
	      };
	
	      scope.toggleSpam = function (comment) {
	        campaignComments.toggleSpam(comment).then(function () {
	          comment.spam = !comment.spam;
	          $('.comment-' + comment.id).toggleClass('spam-faded');
	        });
	      };
	
	      scope.postReply = function (comment, replyText) {
	        campaignComments.postReply(comment, replyText).then(function () {}, function (response) {
	          if (response.status === 401) {
	            browser.redirectTo('/accounts/sign_up');
	          } else {
	            flash.addMessage('error', response.data.error_description);
	          }
	        });
	      };
	
	      scope.deleteReply = function (comment, reply) {
	        if ($window.confirm(i18n.t('deleting_reply_cant_be_undone') + '\n' + i18n.t('are_you_sure_you_want_to_continue'))) {
	          campaignComments.deleteReply(comment, reply);
	        }
	      };
	
	      scope.noContributions = function () {
	        return scope.contributions && scope.contributions.length === 0;
	      };
	    }
	  };
	}

/***/ },
/* 73 */
/***/ function(module, exports) {

	module.exports = "<div class=\"commentLayout\">\n  <div class=\"commentLayout-avatar\">\n    <img class=\"commentAvatar\" ng-src=\"{{comment.avatar_url}}\"/>\n  </div>\n  <div class=\"commentLayout-main\">\n    <div class=\"commentLayout-private i-annotation-pill i-annotation-pill--private\" ng-if=\"comment.private\">{{::i18n.t('private_caps')}}</div>\n    <div class=\"commentLayout-header\">\n      <a class=\"commentLayout-account\" ng-if=\"comment.profile_url\" ng-href=\"{{comment.profile_url}}\">{{comment.account_name}}</a>\n      <span class=\"commentLayout-account\" ng-if=\"!comment.profile_url\">{{comment.account_name}}</span>\n      <span class=\"i-annotation-pill i-annotation-pill--team\" ng-if=\"comment.campaign_team\">{{::i18n.t('campaigner')}}</span>\n      <span class=\"commentNote\">{{comment.timestamp}}</span>\n      <a href=\"\" ng-click=\"showFundingDetails()\" class=\"commentAction\" ng-if=\"::canViewFundingDetails\">{{::i18n.t('campaign_page_comments.view_funding_details')}}</a>\n    </div>\n    <div class=\"commentLayout-text\" ng-bind-html=\"comment.comment_html\"></div>\n    <div class=\"commentLayout-seeMoreReplies\" ng-if=\"comment.replies.length > 1\">\n      <a href=\"\" class=\"commentAction\" ng-click=\"comment.showReplies = !comment.showReplies\">{{ comment.showReplies ? 'See less' : 'See ' + (comment.replies.length - 1) + ' more ' + (comment.replies.length ==2 ? 'reply...' : 'replies...') }}</a>\n    </div>\n    <div class=\"commentLayout-reply commentLayout\" ng-repeat=\"reply in comment.replies\" ng-show=\"comment.showReplies || $last\">\n      <div class=\"commentLayout-avatar\">\n        <img class=\"commentAvatar\" ng-src=\"{{reply.avatar_url}}\"/>\n      </div>\n      <div class=\"commentLayout-main\">\n        <div class=\"commentLayout-header\">\n          <a class=\"commentLayout-account\" ng-if=\"reply.profile_url\" ng-href=\"{{reply.profile_url}}\">{{reply.account_name}}</a>\n          <span class=\"commentLayout-account\" ng-if=\"!reply.profile_url\">{{reply.account_name}}</span>\n          <span class=\"i-annotation-pill i-annotation-pill--team\" ng-if=\"reply.campaign_team\">{{::i18n.t('campaigner')}}</span>\n          <span class=\"commentNote\">{{reply.timestamp}}</span>\n        </div>\n        <div class=\"commentLayout-text\">{{reply.reply_text}}</div>\n        <div ng-if=\"current_user && current_user.is_admin\" class=\"commentLayout-actions\">\n          <a href=\"\" class=\"commentAction\" ng-click=\"deleteReply(comment, reply)\">{{::i18n.t('delete')}}</a>\n        </div>\n      </div>\n    </div>\n    <div class=\"commentLayout-actions\" ng-if=\"current_user && (current_user.on_campaign_team || current_user.id == comment.account_id || current_user.is_admin)\">\n      <a class=\"commentAction\" href=\"\" ng-click=\"comment.showReplyTextbox = true\">Reply</a>\n      <span ng-if=\"current_user && current_user.allowed_to_mark_as_spam\">\n        <span class=\"commentSeparator\">|</span>\n        <a class=\"commentAction\" href=\"\" ng-click=\"toggleSpam(comment)\">{{comment.spam\n          ? 'Unmark Spam' : 'Mark as Spam'}}</a>\n      </span>\n      <span ng-if=\"current_user && current_user.is_admin\">\n        <span class=\"commentSeparator\">|</span>\n        <a class=\"commentAction\" href=\"\" ng-click=\"deleteComment(comment)\">{{::i18n.t('delete')}}</a>\n      </span>\n    </div>\n\n    <div class=\"commentLayout-replyForm commentReplyForm\" ng-show=\"comment.showReplyTextbox\">\n      <textarea class=\"commentReplyForm-field\" placeholder=\"Write a reply...\" ng-model=\"replyText\"\n                ng-init=\"replyText = ''\"></textarea>\n      <div class=\"commentReplyForm-actions\">\n        <span class=\"commentReplyForm-counter\">{{$parent.counterText(replyText, 500)}}</span>\n        <button id=\"reply_button\" class=\"i-cta-1 i-cta-1--grey i-cta-1--mini\"\n                ng-click=\"postReply(comment, replyText); replyText = ''\" ng-disabled=\"$parent.isButtonDisabled(replyText)\">\n          reply\n        </button>\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 74 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal campaignSuperModal fundingDetailsModal\">\n  <div class=\"modal-dialog\">\n    <div class=\"modal-content\">\n      <div class=\"campaignSuperModal-header\">\n        <div class=\"campaignSuperModal-account\">\n          <div ng-if=\"comment.avatar_url\" class=\"campaignSuperModal-avatar\">\n            <img class=\"commentAvatar\" ng-src=\"{{comment.avatar_url}}\" />\n          </div>\n          <div class=\"campaignSuperModal-accountName\">\n            Funding details for {{comment.account_name}}\n            <div ng-if=\"comment.profile_url\" class=\"campaignSuperModal-profileLink\">\n              <a href=\"{{comment.profile_url}}\" target=\"_blank\" ng-bind=\"i18n.t('view_profile_caps')\"></a>\n            </div>\n          </div>\n        </div>\n        <a class=\"modal-close\" href=\"\" ng-click=\"$hide()\" aria-hidden=\"true\"><svg><use xlink:href=\"#icon-icon-close\"></use></svg></a>\n      </div>\n\n      <div class=\"campaignSuperModal-body\" ng-class=\"{'campaignSuperModal-body--empty': noContributions() }\">\n        <div desktop-comment-contribution-details ng-repeat=\"contribution in contributions\" contribution=\"contribution\" command-center-path=\"{{commandCenterPath}}\" class=\"campaignSuperModal-contribution\"></div>\n        <div ng-if=\"noContributions()\" class=\"campaignSuperModal-noFundingHistory\">\n          {{::i18n.t('campaign_page_comments.no_funding_history')}}\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 75 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	desktopCommentsDirective.$inject = ["i18n", "flash", "browser", "campaignComments", "gon", "$location"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = desktopCommentsDirective;
	/*@ngInject*/
	
	function desktopCommentsDirective(i18n, flash, browser, campaignComments, gon, $location) {
	  return {
	    scope: {},
	    template: __webpack_require__(76),
	    link: function link(scope, element) {
	      scope.i18n = i18n;
	      scope.current_user = gon.current_user;
	      scope.allowPublicComments = campaignComments.allowPublicComments;
	      scope.sessionModalStatus = { open: false };
	
	      scope.loadComments = function () {
	        if ($location.$$search.id) {
	          scope.oneComment = true;
	        }
	        campaignComments.load().then(function () {
	          scope.comments = campaignComments.comments;
	          scope.pagination = campaignComments.pagination;
	        });
	      };
	      scope.loadComments();
	
	      scope.$watch(function () {
	        return campaignComments.comments;
	      }, function (newValue) {
	        scope.comments = newValue;
	      });
	
	      scope.newComment = {
	        comment_html: '',
	        appearance: scope.allowPublicComments ? 'STAP_VSBL' : 'STAP_PRVT'
	      };
	
	      scope.postComment = function () {
	        campaignComments.postComment(scope.newComment).then(function () {
	          scope.newComment.comment_html = '';
	        }, function (response) {
	          if (response.status === 401) {
	            browser.redirectTo('/accounts/sign_up');
	          } else {
	            flash.addMessage('error', response.data.error_description);
	          }
	        });
	      };
	
	      scope.openSessionModal = function () {
	        gon.session_modal.from = { 'source': 'project_tab', 'project_id': gon.campaign && gon.campaign.id, 'hash': window.location.hash };
	        scope.sessionModalStatus.open = true;
	      };
	
	      scope.counterText = function (text, maxLength) {
	        return i18n.t("x_of_y", {
	          x: maxLength - text.length,
	          y: maxLength.toString()
	        });
	      };
	
	      scope.isButtonDisabled = function (text) {
	        return text.length > 500 || text.length === 0;
	      };
	
	      scope.appearanceClicked = function () {
	        if (!scope.allowPublicComments) {
	          scope.newComment.appearance = 'STAP_PRVT';
	          flash.addMessage('error', i18n.t('you_must_contribute_to_make_comment'));
	        }
	      };
	
	      scope.showMore = function () {
	        campaignComments.loadMore().then(function () {
	          scope.pagination = campaignComments.pagination;
	        });
	      };
	    }
	  };
	}

/***/ },
/* 76 */
/***/ function(module, exports) {

	module.exports = "<span ng-if=\"!oneComment\">\n\n  <div ng-if=\"current_user && allowPublicComments\" class=\"i-musty-background i-tab-form\">\n    <textarea class=\"i-comment-textarea\" id=\"comment_text\" ng-model=\"newComment.comment_html\"></textarea>\n\n    <div class=\"i-button-row\">\n      <div class=\"pull-left i-counter\">{{counterText(newComment.comment_html, 500)}}</div>\n      <button class=\"i-cta-1 i-cta-1--grey\" ng-click=\"postComment()\" ng-disabled=\"isButtonDisabled(newComment.comment_html)\">{{::i18n.t('post_comment')}}</button>\n    </div>\n  </div>\n\n  <div ng-if=\"current_user && !allowPublicComments\" class=\"i-musty-background i-tab-form i-not-contributor\">\n    <div>\n      <span>{{::i18n.t('you_must')}}</span> <a>{{::i18n.t('contribute')}}</a> <span>{{::i18n.t('to_this_campaign_to_post_a_comment')}}</span>\n    </div>\n  </div>\n</span>\n\n<div ng-if=\"!current_user && !allowPublicComments\" class=\"i-musty-background i-tab-form i-logged-out\">\n  <div>\n    <span>{{::i18n.t('log_in_contribute_to_comment')}}\n      <a ng-click=\"openSessionModal()\" href=\"\">{{::i18n.t('log_in')}}</a>\n    </span>\n  </div>\n</div>\n\n<div class=\"i-comments\">\n  <desktop-comment class=\"desktopComment\" comment=\"comment\"\n                   ng-class=\"comment.spam && (current_user.id != comment.account_id) ? 'desktopComment--spamFaded' : ''\"\n                   ng-repeat=\"comment in comments\"\n                   ng-init=\"comment.showReplyTextbox = false; comment.showReplies = false;\"></desktop-comment>\n</div>\n\n<div class=\"desktopComment-container\">\n  <a ui-sref=\"comments\" href=\"#\" ui-sref-opts=\"{reload: true}\" class=\"i-cta-2-thin desktopComment-button\" ng-if=\"oneComment && comments\">\n    {{::i18n.t('campaign_page_comments.view_all_comments')}}\n  </a>\n</div>\n\n<span ng-if=\"!oneComment\">\n\n  <div class=\"pull-right i-show-more\" ng-if=\"pagination.next\">\n    <a href=\"\" ng-click=\"showMore()\">{{::i18n.t('show_more')}}</a>\n  </div>\n\n</span>\n<session-modal status=\"sessionModalStatus\"></session-modal>\n";

/***/ },
/* 77 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	desktopCommentContributionDetails.$inject = ["i18n", "ga", "gogoEvents"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = desktopCommentContributionDetails;
	/*@ngInject*/
	
	function desktopCommentContributionDetails(i18n, ga, gogoEvents) {
	  return {
	    scope: {
	      'contribution': '=',
	      'commandCenterPath': '@'
	    },
	    template: __webpack_require__(78),
	    link: function link(scope) {
	      scope.i18n = i18n;
	
	      scope.formattedDate = function (dateString) {
	        return i18n.l(new Date(dateString), { format: 'short_with_year' });
	      };
	
	      scope.contributionPath = function (contribution) {
	        return scope.commandCenterPath + '#/contributions/' + contribution.id;
	      };
	
	      scope.fireViewOrderGaEvent = function () {
	        ga('send', 'event', 'Comments', 'View order from Funding Details', 'Project ID: ' + scope.contribution.campaign.id);
	        gogoEvents.captureEvent('comments_view_order_from_funding_details', {
	          project_id: scope.contribution.campaign.id
	        });
	      };
	    }
	  };
	}

/***/ },
/* 78 */
/***/ function(module, exports) {

	module.exports = "<div class=\"commentContributionDetailsLayout\">\n  <div class=\"commentContributionDetailsLayout-left\">\n    <div ng-if=\"::contribution.order\" class=\"contributionDetail\">\n      <div class=\"contributionDetail-title\" ng-bind=\"::i18n.t('contribution_details.order_number')\"></div>\n      <div class=\"contributionDetail-value\">\n        <a ng-click=\"fireViewOrderGaEvent()\" ng-href=\"{{contributionPath(contribution)}}\" ng-bind=\"contribution.order.sequence_number\" target=\"_blank\"></a>\n      </div>\n    </div>\n\n    <div ng-if=\"::!contribution.order\" class=\"contributionDetail\">\n      <div class=\"contributionDetail-value\">\n        <a ng-click=\"fireViewOrderGaEvent()\" ng-href=\"{{contributionPath(contribution)}}\" ng-bind=\"::i18n.t('view_donation')\" target=\"_blank\"></a>\n       </div>\n    </div>\n\n    <div class=\"contributionDetail\">\n      <div class=\"contributionDetail-title\" ng-bind=\"::i18n.t('contribution_details.date')\"></div>\n      <div class=\"contributionDetail-value\" ng-bind=\"::formattedDate(contribution.created_at)\"></div>\n    </div>\n\n    <div ng-if=\"::contribution.order\" class=\"contributionDetail\">\n      <div class=\"contributionDetail-title\" ng-bind=\"::i18n.t('contribution_details.order_status')\"></div>\n      <div order-state contribution=\"contribution\" class=\"contributionDetail-value\"></div>\n    </div>\n  </div>\n\n  <div class=\"commentContributionDetailsLayout-right\">\n    <div ng-if=\"::contribution.perk\" class=\"contributionDetail\">\n      <div class=\"contributionDetail-title\" ng-bind=\"::i18n.t('contribution_details.perk')\"></div>\n      <div class=\"contributionDetail-value\" ng-bind=\"contribution.perk.label\"></div>\n    </div>\n\n    <div class=\"contributionDetail\">\n      <div class=\"contributionDetail-title\" ng-bind=\"::i18n.t('contribution_details.payment_method')\"></div>\n      <div payment-method contribution=\"contribution\" class=\"contributionDetail-value\"></div>\n    </div>\n\n    <div ng-if=\"contribution.line_items\" class=\"contributionDetail\">\n      <div class=\"contributionDetail-title\" ng-bind=\"::i18n.t('command_center.contribution_amount')\"></div>\n      <div line-items contribution=\"contribution\" class=\"contributionDetail-value\"></div>\n    </div>\n  </div>\n</div>\n\n\n";

/***/ },
/* 79 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	desktopFacebookShareDirective.$inject = ["$http", "gon", "i18n", "fb", "ga", "gogoEvents"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = desktopFacebookShareDirective;
	/*@ngInject*/
	
	function desktopFacebookShareDirective($http, gon, i18n, fb, ga, gogoEvents) {
	  return {
	    scope: {},
	    restrict: 'A',
	    template: __webpack_require__(80),
	    link: function link(scope, element) {
	      scope.i18n = i18n;
	      scope.fb = fb;
	
	      scope.ga_impression_data = gon.ga_impression_data;
	      scope.shareFacebook = function () {
	        // TODO EVENTS: id=eej9h category=campaign_page_share category-new=TBD action=click_fb_share label=dynamic fixtype=ga+captureEvent name=click_fb_share subsystem=share . review
	        ga('send', 'event', 'campaign_page_share', 'click_fb_share', scope.ga_impression_data.category);
	        // TODO EVENTS: id=ee3sh fixtype=ga-social subsystem=share . review
	        ga('send', 'social', { 'socialNetwork': 'facebook_desktop', 'socialAction': 'share' });
	        gogoEvents.captureEvent('click_fb_share');
	
	        var options = gon.current_account ? { account_id: gon.current_account.account_id } : {};
	        options.utm_query_string = gon.fb_utm_query_string;
	
	        // TODO EVENTS: id=ahf7i fixtype=fb-share subsystem=campaign-page . think about fb.share
	        fb.share(gon.share.canonical_url, options);
	      };
	    }
	  };
	}

/***/ },
/* 80 */
/***/ function(module, exports) {

	module.exports = "<a href=\"\" class=\"i-cta-1\" ng-click=\"shareFacebook()\">\n  {{::i18n.t('share_on_facebook')}}\n</a>\n";

/***/ },
/* 81 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	desktopFundersDirective.$inject = ["$http", "gon", "i18n"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = desktopFundersDirective;
	/*@ngInject*/
	
	function desktopFundersDirective($http, gon, i18n) {
	  return {
	    scope: {},
	    template: __webpack_require__(82),
	    link: function link(scope) {
	      scope.i18n = i18n;
	      $http.get(gon.urls.funders).then(function (result) {
	        scope.pledges = result.data.response;
	        scope.pagination = result.data.pagination;
	      });
	
	      scope.showMore = function () {
	        $http.get(gon.urls.funders + '?page=' + scope.pagination.next).then(function (result) {
	          scope.pledges = scope.pledges.concat(result.data.response);
	          scope.pagination = result.data.pagination;
	        });
	      };
	    }
	  };
	}

/***/ },
/* 82 */
/***/ function(module, exports) {

	module.exports = "<div ng-if=\"pledges.length === 0\">\n  {{::i18n.t('campaign_has_no_contributors')}}\n</div>\n\n<div ng-if=\"pledges.length > 0\" class=\"row i-funder-row\" ng-repeat=\"pledge in pledges\">\n  <div class=\"col-sm-2\">\n    <img ng-src=\"{{ pledge.pledger_image_url }}\" />\n  </div>\n  <div class=\"col-sm-6 i-name-col\">\n    <div class=\"i-name\">\n      <a class=\"i-details-name\" ng-if=\"pledge.pledger_profile_url\" href=\"{{ pledge.pledger_profile_url }}\">{{pledge.pledger_display_name}}</a>\n      <div class=\"i-details-name\" ng-if=\"!pledge.pledger_profile_url\">{{pledge.pledger_display_name}}</div>\n    </div>\n    <div class=\"i-contribution-details-link\" ng-if=\"pledge.pledge_details_url\">\n      <a ng-if=\"pledge.order_id\" href=\"{{pledge.pledge_details_url}}\">{{::i18n.t('view_order')}}</a>\n      <a ng-if=\"!pledge.order_id\" href=\"{{pledge.pledge_details_url}}\">{{::i18n.t('view_donation')}}</a>\n    </div>\n    <div class=\"i-note\">{{pledge.time_ago}}</div>\n  </div>\n  <div class=\"col-sm-4 i-amount-col\">\n    <div ng-if=\"pledge.display_amount\" class=\"i-centered-block\"><span class=\"currency currency-small\"><span>{{pledge.display_amount}}</span><em>{{pledge.display_amount_iso_code}}</em></span></div>\n    <div ng-if=\"!pledge.display_amount\" class=\"i-centered-block\">{{::i18n.t('private_caps')}}</div>\n  </div>\n</div>\n\n<div ng-if=\"pagination.next\" class=\"pull-right i-show-more\">\n  <a href=\"\" ng-click=\"showMore()\">{{::i18n.t('show_more')}}</a>\n</div>\n";

/***/ },
/* 83 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	desktopGalleryDirective.$inject = ["$http", "gon", "i18n", "$sce"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = desktopGalleryDirective;
	/*@ngInject*/
	
	function desktopGalleryDirective($http, gon, i18n, $sce) {
	  return {
	    scope: {},
	    template: __webpack_require__(84),
	    link: function link(scope) {
	      scope.i18n = i18n;
	
	      scope.makeCurrentVideo = function (video) {
	        scope.currentVideoHtml = $sce.trustAsHtml(video.html);
	        scope.currentVideoDescription = video.description;
	      };
	
	      scope.selectImage = function (index) {
	        scope.currentImageIndex = index;
	      };
	
	      scope.nextImage = function () {
	        scope.selectImage((scope.currentImageIndex + 1) % scope.images.length);
	      };
	
	      $http.get(gon.urls.gallery).then(function (result) {
	        scope.videos = result.data.videos;
	        if (scope.videos.length > 0) {
	          scope.makeCurrentVideo(scope.videos[0]);
	        }
	        scope.images = result.data.images;
	        if (scope.images.length > 0) {
	          scope.selectImage(0);
	        }
	        scope.editLink = result.data.edit_link;
	      });
	    }
	  };
	}

/***/ },
/* 84 */
/***/ function(module, exports) {

	module.exports = "<div class=\"i-gallerySection\" ng-if=\"videos.length > 0\">\n  <div class=\"i-lined-header\">\n    <a class=\"pull-right i-edit\" ng-if=\"editLink\" ng-href=\"{{editLink}}\">{{::i18n.t('edit')}}</a>\n    {{::i18n.t('video_gallery')}}\n  </div>\n  <div class=\"i-player\">\n    <div ng-bind-html=\"currentVideoHtml\"></div>\n    <div class=\"caption_for_video\">{{currentVideoDescription}}</div>\n  </div>\n  <div class=\"i-thumbnails\">\n    <a ng-repeat=\"video in videos\" href=\"\" ng-click=\"makeCurrentVideo(video)\">\n      <img height=\"45px\" width=\"60px\" ng-src=\"{{video.thumbnail_url}}\" />\n    </a>\n  </div>\n</div>\n<div class=\"i-gallerySection\" ng-if=\"images.length > 0\">\n  <div class=\"i-lined-header\">\n    <a class=\"pull-right i-edit\" ng-if=\"editLink\" ng-href=\"{{editLink}}\">{{::i18n.t('edit')}}</a>\n    {{::i18n.t('image_gallery')}}\n  </div>\n  <div class=\"i-player\">\n    <div class=\"i-gallery-image\">\n      <a href=\"\" ng-click=\"nextImage()\">\n        <img ng-src=\"{{images[currentImageIndex].full_url}}\" />\n      </a>\n    </div>\n    <div class=\"caption\">\n      <p>{{images[currentImageIndex].title}}</p>\n      <p>{{images[currentImageIndex].description}}</p>\n    </div>\n  </div>\n  <div class=\"i-thumbnails\">\n    <a ng-repeat=\"image in images\" class=\"thumb\" href=\"\" ng-click=\"selectImage($index)\">\n      <img ng-src=\"{{image.thumbnail_url}}\" alt=\"{{image.title}}\"/>\n    </a>\n  </div>\n</div>\n";

/***/ },
/* 85 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	desktopNavBarDirective.$inject = ["i18n", "ga", "gon", "gogoEvents"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = desktopNavBarDirective;
	/*@ngInject*/
	
	function desktopNavBarDirective(i18n, ga, gon, gogoEvents) {
	  return {
	    scope: {},
	    replace: true,
	    template: __webpack_require__(86),
	    link: function link(scope, element) {
	      scope.i18n = i18n;
	      scope.tabs = gon.tabs;
	      scope.ga_impression_data = gon.ga_impression_data;
	    }
	  };
	}

/***/ },
/* 86 */
/***/ function(module, exports) {

	module.exports = "<span class=\"i-tab\" ng-class=\"{ 'i-selected': tab.id == 'story' }\" ui-sref-active=\"i-selected\" ng-repeat=\"tab in tabs\">\n  <span ng-class=\"{ 'i-disabled-tab': tab.disabled }\">\n    <!-- TODO EVENTS: id=aef5u fixtype=ga-event-dir+event-dir subsystem=campaign-page category=campaign_page_tabs category-new=TBD action=dynamic label=dynamic name=dynamic name-new=TBD vars=page-location+tags trigger=click dom=a . -->\n    <a href=\"#\" ui-sref=\"{{tab.id}}\"\n       analytics-on=\"click\"\n       analytics-name=\"campaign_page_tabs_{{tab.id}}_click\"\n       analytics-page-location=\"campaign_page\"\n       analytics-tags=\"{'action': 'click', 'object' : 'tab'}\"\n       analytics-category=\"campaign_page_tabs\"\n       analytics-event=\"{{tab.id}}\"\n       analytics-label=\"{{ga_impression_data.category}}\">{{tab.label}}</a>&nbsp;<span ng-hide=\"tab.count == null\" id=\"js-tab-{{tab.id}}-count\" class=\"i-count\">{{tab.count}}</span>\n  </span>\n</span>\n";

/***/ },
/* 87 */
/***/ function(module, exports) {

	'use strict';
	
	desktopProjectFunderCountDirective.$inject = ["gon", "campaignPusher"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = desktopProjectFunderCountDirective;
	/*@ngInject*/
	
	function desktopProjectFunderCountDirective(gon, campaignPusher) {
	  return {
	    scope: {},
	    link: function link(scope, element) {
	      campaignPusher.bind('balance_changed', function (message) {
	        element.find('#js-tab-funders-count').text(message.raised_funders_count);
	      });
	    }
	  };
	}

/***/ },
/* 88 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	desktopUpdatesDirective.$inject = ["campaignUpdates", "updatePreview", "gon", "i18n", "$sce", "flash", "$window", "$filter", "$modal", "$rootScope"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = desktopUpdatesDirective;
	/*@ngInject*/
	
	function desktopUpdatesDirective(campaignUpdates, updatePreview, gon, i18n, $sce, flash, $window, $filter, $modal, $rootScope) {
	
	  return {
	    scope: {},
	    template: __webpack_require__(89),
	    link: function link(scope, element) {
	      scope.i18n = i18n;
	      scope.showSpinner = false;
	      scope.newUpdate = { bodyHtml: '' };
	      scope.ckeditorTooLong = false;
	      scope.ckeditorPostDisabled = true;
	
	      var MIN_UPDATE_LENGTH = 2;
	      scope.MAX_UPDATE_LENGTH = 2500;
	
	      function stripTags(html) {
	        return $('<div>' + html + '</div>').text().replace(/\t+/g, " ").replace(/\n/g, "").replace(/^\s/g, "");
	      }
	
	      scope.$watch('newUpdate.bodyHtml', function (newVal, oldVal) {
	        var stripped = stripTags(newVal);
	        scope.ckeditorPostDisabled = stripped.length > scope.MAX_UPDATE_LENGTH || stripped.length < MIN_UPDATE_LENGTH;
	        scope.ckeditorTooLong = stripped.length > scope.MAX_UPDATE_LENGTH;
	        updatePreview.isDisabled = scope.ckeditorPostDisabled;
	      });
	
	      campaignUpdates.getUpdates().then(function (result) {
	        var updates = result.data.response;
	        updates.forEach(function (update) {
	          update.body_html = $sce.trustAsHtml(update.body_html);
	        });
	        scope.updates = updates;
	        scope.pagination = result.data.pagination;
	        scope.editable = result.data.editable;
	      });
	
	      scope.postUpdate = function () {
	        scope.showSpinner = scope.ckeditorPostDisabled = updatePreview.isDisabled = true;
	        campaignUpdates.postUpdate({ body_html: scope.newUpdate.bodyHtml }).then(function (response) {
	          scope.showSpinner = scope.ckeditorPostDisabled = updatePreview.isDisabled = false;
	          var newUpdate = response.data;
	          newUpdate.body_html = $sce.trustAsHtml(newUpdate.body_html);
	          scope.updates = [newUpdate].concat(scope.updates);
	          scope.newUpdate.bodyHtml = '';
	          flash.addMessage('info', i18n.t('successful_announcement_message'));
	        }, function (response) {
	          scope.showSpinner = scope.ckeditorPostDisabled = false;
	          flash.addMessage('error', response.data.error);
	        });
	      };
	
	      scope.deleteUpdate = function (update) {
	        if ($window.confirm(i18n.t('deleting_update_cant_be_undone') + '\n' + i18n.t('are_you_sure_you_want_to_continue'))) {
	          campaignUpdates.deleteUpdate(update).then(function (response) {
	            flash.addMessage('info', i18n.t('delete_success'));
	            scope.updates = _.without(scope.updates, update);
	          }, function (response) {
	            flash.addMessage('error', response.data.error);
	          });
	        }
	      };
	
	      scope.showMore = function () {
	        campaignUpdates.showMore(scope.pagination.next).then(function (result) {
	          var newUpdates = result.data.response;
	          newUpdates.forEach(function (update) {
	            update.body_html = $sce.trustAsHtml(update.body_html);
	          });
	          scope.updates = scope.updates.concat(newUpdates);
	          scope.pagination = result.data.pagination;
	        });
	      };
	    }
	  };
	}

/***/ },
/* 89 */
/***/ function(module, exports) {

	module.exports = "<div ng-if=\"editable\" class=\"i-musty-background i-tab-form\" ng-form name=\"postUpdateForm\">\n  <h2>{{::i18n.t('post_a_new_update')}}</h2>\n  <textarea ckeditor id=\"postUpdateInput\" ng-model=\"newUpdate.bodyHtml\"></textarea>\n  <div class=\"i-button-row\">\n    <span class=\"i-counter\"><span ng-class=\"{ 'boldError': ckeditorTooLong }\">{{newUpdate.bodyHtml | htmlCharCounter:MAX_UPDATE_LENGTH}}</span></span>\n\n    <div desktop-update-preview class=\"updatePreview\" body-html=\"newUpdate.bodyHtml\"></div>\n    <button class=\"i-cta-1 i-cta-1--postUpdate\" ng-click=\"postUpdate()\" ng-disabled=\"ckeditorPostDisabled\">\n      <span ng-if=\"showSpinner\" class=\"fa fa-spinner fa-spin\"></span>\n      <span ng-if=\"!showSpinner\">{{::i18n.t('post_update')}}</span>\n    </button>\n  </div>\n</div>\n\n<div ng-repeat=\"update in updates\" class=\"activityUpdate\">\n  <a ng-if=\"editable\" class=\"activityUpdate-delete\" href=\"\" ng-click=\"deleteUpdate(update)\"><svg><use xlink:href=\"#icon-icon-close\"></use></svg></a>\n  <h2 class=\"activityUpdate-timestamp\">{{update.timestamp}}</h2>\n  <div class=\"ugcContent\" ng-bind-html=\"update.body_html\"></div>\n  <div class=\"i-image-media i-profile-image-media\">\n    <img ng-src=\"{{update.account_avatar_url}}\"/>\n    <a ng-href=\"{{update.account_profile_url}}\">{{update.account_name}}</a>\n  </div>\n</div>\n\n<div ng-if=\"pagination.next\" class=\"pull-right i-show-more\">\n  <a href=\"\" ng-click=\"showMore()\">{{::i18n.t('show_more')}}</a>\n</div>\n";

/***/ },
/* 90 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	desktopUpdatePreviewDirective.$inject = ["i18n", "updatePreview", "$modal", "$rootScope"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = desktopUpdatePreviewDirective;
	/*@ngInject*/
	
	function desktopUpdatePreviewDirective(i18n, updatePreview, $modal, $rootScope) {
	  return {
	    scope: {
	      bodyHtml: '='
	    },
	    template: __webpack_require__(91),
	    restrict: 'A',
	    link: function link(scope, element) {
	      scope.i18n = i18n;
	      scope.updatePreview = updatePreview;
	
	      scope.showPreviewAndTestModal = function () {
	        updatePreview.getPreview({ bodyHtml: scope.bodyHtml }).then(function (response) {
	          $modal({
	            template: __webpack_require__(92),
	            controller: 'UpdatePreviewModal'
	          });
	        });
	      };
	    }
	  };
	}

/***/ },
/* 91 */
/***/ function(module, exports) {

	module.exports = "<button\n  class=\"i-cta-2 i-cta-2-grey i-cta-2--altTextGrey\"\n  ng-disabled=\"updatePreview.isDisabled\"\n  ng-click=\"showPreviewAndTestModal()\">\n  {{::i18n.t('preview_and_test.label')}}\n</button>\n\n\n";

/***/ },
/* 92 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal i-modal previewAndTestModal\">\n  <div class=\"modal-dialog\">\n    <div class=\"modal-content\">\n      <a class=\"modal-close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"cancelPreview()\" svg-icon icon=\"icon-icon-close\"></svg-icon></a>\n      <div class=\"previewAndTestModal-header\">\n        {{::i18n.t('preview_and_test.label')}}\n      </div>\n      <div ng-if=\"updatePreview.isInitial() || updatePreview.isWorking()\" class=\"previewAndTestModal-email\">\n        <div class=\"i-block-label\">{{::i18n.t('preview_and_test.send_a_test_email')}}\n        </div>\n        <input type=\"text\" ng-model=\"updatePreview.email\" class=\"i-text-field i-text-field--50px\" placeholder=\"{{::i18n.t('preview_and_test.enter_email_address')}}\" />\n        <div class=\"i-button-row\">\n          <button class=\"i-cta-1\" ng-click=\"sendTest()\" ng-disabled=\"updatePreview.isWorking() || updatePreview.email.length === 0\">\n            {{updatePreview.isWorking() ? i18n.t('preview_and_test.sending') : i18n.t('preview_and_test.send_test')}}\n          </button>\n        </div>\n      </div>\n      <div class=\"previewAndTestModal-complete\" ng-if=\"updatePreview.isComplete()\">\n        <img class=\"previewAndTestModal-complete--image\" ng-src=\"{{updatePreview.confirmationImagePath}}\"/>\n        <div class=\"previewAndTestModal-complete--email\">\n          {{::i18n.t('preview_and_test.email_sent', { email: updatePreview.email })}}\n        </div>\n        <a class=\"previewAndTestModal-complete--again\" ng-click=\"resetPreviewState()\">\n          {{::i18n.t('preview_and_test.send_another')}}\n        </a>\n      </div>\n      <div class=\"previewAndTestModal-preview\">\n        <div class=\"previewAndTestModal-preview--container\">\n          <div class=\"previewAndTestModal-preview--bar\">\n          </div>\n          <div class=\"previewAndTestModal-preview--header\">\n            {{::i18n.t('preview_and_test.html_preview')}}\n          </div>\n        </div>\n        <div class=\"previewAndTestModal-preview--body\" ng-bind-html=\"updatePreview.trustedHtml\">\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n\n";

/***/ },
/* 93 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	earlyContributeDirective.$inject = ["i18n", "$filter", "gon"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = earlyContributeDirective;
	/*@ngInject*/
	
	function earlyContributeDirective(i18n, $filter, gon) {
	  return {
	    template: __webpack_require__(94),
	    scope: {
	      baseContributePath: '@',
	      currencySymbol: '@'
	    },
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.placeholderText = scope.currencySymbol + "5, " + scope.currencySymbol + "10, " + scope.currencySymbol + "100";
	
	      var userAmountChanged = function userAmountChanged(userAmount) {
	        if (userAmount) {
	          scope.contributeMessage = i18n.t('campaign_page_contribute.contribute') + ' ' + scope.currencySymbol + $filter('number')(userAmount, 0);
	          scope.contributeHref = scope.baseContributePath + '?nonperk_amt=' + userAmount;
	        } else {
	          scope.contributeMessage = i18n.t('contribute_now');
	          scope.contributeHref = scope.baseContributePath;
	          if (!gon.pay_flow_split_test) {
	            scope.contributeHref += '?nonperk_amt=100';
	          }
	        }
	      };
	
	      scope.contribution = { userAmount: null };
	      userAmountChanged(scope.contribution.userAmount);
	      scope.changeUserAmount = function () {
	        userAmountChanged(scope.contribution.userAmount);
	      };
	    }
	  };
	}

/***/ },
/* 94 */
/***/ function(module, exports) {

	module.exports = "<div ng-form=\"earlyContribute\">\n  <span class=\"earlyContribute-title\">{{ ::i18n.t('campaign_page_contribute.your_contribution') }}</span>\n  <input type=\"number\" class=\"earlyContribute-input\" name=\"userAmountInput\" ng-model=\"contribution.userAmount\"\n         ng-change=\"changeUserAmount()\" min=\"1\" max=\"1000000\" pattern=\"^\\d*$\"\n         placeholder=\"{{placeholderText}}\" class=\"i-text-field\" />\n\n  <div class=\"earlyContribute-error\" ng-if=\"earlyContribute.userAmountInput.$error.number\">{{::i18n.t('campaign_page_contribute.nonperk_input_error')}}</div>\n  <div class=\"earlyContribute-error\" ng-if=\"earlyContribute.userAmountInput.$error.min\">{{::i18n.t('campaign_page_contribute.nonperk_input_error')}}</div>\n  <div class=\"earlyContribute-error\" ng-if=\"earlyContribute.userAmountInput.$error.max\">{{::i18n.t('campaign_page_contribute.nonperk_input_error')}}</div>\n  <div class=\"earlyContribute-error\" ng-if=\"earlyContribute.userAmountInput.$error.pattern\">{{::i18n.t('campaign_page_contribute.nonperk_input_error')}}</div>\n  <!-- TODO EVENTS: id=paiz7 fixtype=ga-event-dir+event-dir category=unknown category-new=TBD action=campaign_page action-new=TBD label=contribute.button trigger=click dom=a name=contribute_button vars=page-location+tags subsystem=generosity . think ga-action and ga-label are invalid -->\n  <a ng-href=\"{{contributeHref}}\" class=\"i-cta-1 i-contribute-button\"\n     ng-class=\"{'i-cta1--disabled': !earlyContribute.$valid}\"\n     contribute-button-ga-tracking\n     ga-action=\"campaign_page\"\n     ga-label=\"contribute button\"\n     event-on=\"click\"\n     event-name=\"contribute_button\"\n     event-page-location=\"campaign_page\"\n     event-tags=\"{'action': 'click', 'object': 'button'}\">{{contributeMessage}}</a>\n</div>\n";

/***/ },
/* 95 */
/***/ function(module, exports) {

	"use strict";
	
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = storyTabCacheProvider;
	/*@ngInject*/
	
	function storyTabCacheProvider() {
	  var cachedHtml;
	  this.cacheHtml = function (element) {
	    cachedHtml = element.html();
	  };
	
	  this.cachedHtml = function () {
	    return cachedHtml;
	  };
	
	  this.$get = function () {
	    return this;
	  };
	}

/***/ },
/* 96 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	addYourDonationDirective.$inject = ["gogoEvents", "i18n", "gon", "generosityFundraiser", "$sce"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = addYourDonationDirective;
	/*@ngInject*/
	
	function addYourDonationDirective(gogoEvents, i18n, gon, generosityFundraiser, $sce) {
	  return {
	    scope: {
	      addYourDonationText: '@'
	    },
	    template: __webpack_require__(97),
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.fundraiser = generosityFundraiser;
	      scope.contributeNowUrl = gon.urls.contribute_now_url;
	
	      var prohibitedDiv = $('<div><a></a></div>');
	      var prohibitedLink = prohibitedDiv.find('a');
	      prohibitedLink.text(i18n.t('contains_prohibited_content'));
	      prohibitedLink.attr('target', '_blank');
	      prohibitedLink.attr('href', '/about/terms'); // about_terms_path
	
	      scope.prohibitedContentWarningHtml = $sce.trustAsHtml(i18n.t('generosity.prohibited_content', {
	        contains_prohibited_content_url: prohibitedDiv.html()
	      }));
	    }
	  };
	}

/***/ },
/* 97 */
/***/ function(module, exports) {

	module.exports = "<div class=\"addYourDonation\" ng-if=\"!fundraiser.hasEnded\">\n  <!-- TODO EVENTS: id=eu4oe fixtype=event-dir name=click_donate category-new=TBD vars=page-location trigger=click dom=a subsystem=generosity . review -->\n  <a ng-href=\"{{::contributeNowUrl}}\"\n    class=\"primary-cta\"\n    event-on=\"click\"\n    event-name=\"click_donate\"\n    event-page-location=\"below_donations\">{{::addYourDonationText}}</a>\n\n  <div class=\"fundraiser-prohibited hidden-xs\">\n    <span ng-bind-html=\"prohibitedContentWarningHtml\"></span>\n    <a href=\"{{fundraiser.prohibitedUrl}}\" target=\"_blank\" title=\"{{::i18n.t('violates_indiegogo_terms_of_use')}}\">{{::i18n.t('let_us_know')}}</a>\n  </div>\n</div>\n";

/***/ },
/* 98 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	generosityDonationsDirective.$inject = ["generosityFundraiser", "i18n", "$sce"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = generosityDonationsDirective;
	/*@ngInject*/
	
	function generosityDonationsDirective(generosityFundraiser, i18n, $sce) {
	  return {
	    scope: {},
	    template: __webpack_require__(99),
	    link: function link(scope) {
	
	      var SHOW_MORE_AMOUNT = 5;
	      var DONATIONS_BUFFER_AMOUNT = 10;
	
	      scope.compressedMobile = true;
	      scope.fundraiser = generosityFundraiser;
	      scope.numDonationsShown = SHOW_MORE_AMOUNT;
	      scope.i18n = i18n;
	
	      scope.showMore = function () {
	        if (scope.numDonationsShown + DONATIONS_BUFFER_AMOUNT > generosityFundraiser.donations.length && generosityFundraiser.donations.length < generosityFundraiser.donationsCount) {
	          generosityFundraiser.fetchMoreDonations();
	        }
	        scope.numDonationsShown = scope.numDonationsShown + SHOW_MORE_AMOUNT;
	      };
	
	      scope.toggleMobile = function () {
	        scope.compressedMobile = !scope.compressedMobile;
	      };
	    }
	  };
	}

/***/ },
/* 99 */
/***/ function(module, exports) {

	module.exports = "<div class=\"donations-header\" ng-click=\"toggleMobile()\">\n  <span class=\"fundraiser-lined-header\">{{::i18n.t(\"generosity.donations\")}} {{fundraiser.donationsCount | number}}</span>\n  <span class=\"donations-header-action visible-xs\" ng-if=\"compressedMobile\">+</span>\n  <span class=\"donations-header-action visible-xs\" ng-if=\"!compressedMobile\">-</span>\n</div>\n<div class=\"donations-container\" ng-class=\"{'hidden-xs': compressedMobile}\">\n  <div ng-repeat=\"donation in fundraiser.donations | limitTo: numDonationsShown\" class=\"donation\">\n    <img ng-src=\"{{donation.photo_url}}\" class=\"donation-photo\" ng-if=\"donation.photo_url\" />\n    <span class=\"donation-photo missingAvatar\" ng-if=\"!donation.photo_url\"></span>\n    <div class=\"donation-details\">\n      <div class=\"donation-desc donation-amount\">{{donation.amount}}</div>\n      <div class=\"donation-desc\">{{donation.name}}</div>\n      <div class=\"donation-comment\" ng-if=\"donation.comment\">{{donation.comment}}</div>\n    </div>\n  </div>\n  <div ng-if=\"numDonationsShown < fundraiser.donationsCount\" class=\"donations-showMore\">\n    <a href=\"\" class=\"secondary-cta--light\" ng-click=\"showMore()\">{{::i18n.t(\"show_more\")}}</a>\n  </div>\n</div>\n";

/***/ },
/* 100 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	generosityFundraiserMainDirective.$inject = ["generosityFundraiser", "gogoEvents", "i18n", "$sce", "gon"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = generosityFundraiserMainDirective;
	/*@ngInject*/
	
	function generosityFundraiserMainDirective(generosityFundraiser, gogoEvents, i18n, $sce, gon) {
	  return {
	    scope: {
	      fundraiserPhase: '@'
	    },
	    template: __webpack_require__(101),
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.fundraiser = generosityFundraiser;
	      scope.twitterShareUrl = gon.urls.twitter_share_url;
	      scope.isTeamMember = gon.current_user && gon.current_user.is_team_member;
	      scope.emailMailToUrl = gon.urls.email_mailto_url;
	
	      // TODO EVENTS: id=thau0 fixtype=captureEvent name=visit_fundraiser category-new=TBD label=TBD subsystem=generosity . review
	      gogoEvents.captureEvent('visit_fundraiser');
	      generosityFundraiser.refresh().then(function () {
	        scope.showDonations = generosityFundraiser.donationsCount > 0;
	        if (scope.showDonations) {
	          scope.addYourDonationText = i18n.t('generosity.contribution_flow.add_your_donation');
	        } else {
	          scope.addYourDonationText = i18n.t('generosity.be_the_first_to_donate');
	        }
	      });
	    }
	  };
	}

/***/ },
/* 101 */
/***/ function(module, exports) {

	module.exports = "<div class=\"row\" ng-if=\"fundraiser.loaded\">\n  <div class=\"col-xs-12 col-sm-12 col-md-8 col-lg-8\">\n    <div class=\"fundraiserLgDesktopTrim\">\n      <div class=\"hidden-xs\" ng-if=\"fundraiser.canPostUpdate\">\n        <div class=\"postUpdate\" generosity-post-update></div>\n      </div>\n      <div class=\"storyAndUpdates\">\n        <div class=\"story\" generosity-story></div>\n        <div class=\"updates\" generosity-updates ng-if=\"fundraiser.updates.length > 0\"></div>\n      </div>\n    </div>\n\n    <div class=\"shareThisStory hidden-xs hidden-sm\">\n      <div class=\"shareThisStory-header\">{{::i18n.t('share_this_story')}}</div>\n\n      <div class=\"shareThisStory-buttons\">\n        <!-- TODO EVENTS: id=ru5ni fixtype=event-dir subsystem=generosity name=click_fb_share category-new=TBD vars=page-location trigger=click dom=div . review -->\n        <div generosity-fb-share event-on=\"click\" event-name=\"click_fb_share\" event-page-location=\"fundraiser_page\" class=\"small-cta shareThisStory-button shareThisStory-button--facebook\"></div>\n        <!-- TODO EVENTS: id=au5ae fixtype=event-dir subsystem=generosity name=click_tw_share category-new=TBD vars=page-location trigger=click dom=a . review -->\n        <a event-on=\"click\" event-name=\"click_tw_share\" event-page-location=\"fundraiser_page\" ng-href=\"{{::twitterShareUrl}}\" class=\"small-cta shareThisStory-button shareThisStory-button--twitter\">\n          <svg-icon icon=\"icon-icon-twitter\"></svg-icon><span>{{::i18n.t('twitter')}}</span>\n        </a>\n        <!-- TODO EVENTS: id=su2la fixtype=event-dir subsystem=generosity name=click_send_email_mailto category-new=TBD vars=page-location trigger=click dom=a . review -->\n        <a event-on=\"click\" event-name=\"click_send_email_mailto\" event-page-location=\"fundraiser_page\" ng-href=\"{{::emailMailToUrl}}\" target=\"_blank\" class=\"small-ghost-cta--light shareThisStory-button shareThisStory-button--email\" ng-if=\"!isTeamMember\">\n          <svg-icon icon=\"icon-icon-mail\"></svg-icon><span>{{::i18n.t('email')}}</span>\n        </a>\n        <!-- TODO EVENTS: id=mee1t fixtype=event-dir subsystem=generosity name=click_send_email_importer category-new=TBD vars=page-location trigger=click dom=a . review -->\n        <a event-on=\"click\" event-name=\"click_send_email_importer\" event-page-location=\"fundraiser_page\" href=\"\" email-importer email-from=\"from_supporter\" class=\"small-ghost-cta--light shareThisStory-button shareThisStory-button--email\" ng-if=\"isTeamMember\">\n          <svg-icon icon=\"icon-icon-mail\"></svg-icon><span>{{::i18n.t('email')}}</span>\n        </a>\n      </div>\n    </div>\n  </div>\n\n  <div class=\"col-xs-12 col-sm-12 col-md-4 col-lg-4\">\n    <div class=\"perks\" generosity-perks ng-if=\"fundraiser.perks.length > 0\"></div>\n    <div add-your-donation class=\"visible-md visible-lg\" add-your-donation-text=\"{{::addYourDonationText}}\" ng-if=\"fundraiser.perks.length > 0\"></div>\n    <div class=\"donations\" generosity-donations ng-show=\"showDonations\"></div>\n    <div add-your-donation class=\"visible-md visible-lg\" add-your-donation-text=\"{{::addYourDonationText}}\" ng-if=\"fundraiser.perks.length === 0\"></div>\n  </div>\n</div>\n";

/***/ },
/* 102 */
/***/ function(module, exports) {

	"use strict";
	
	generosityFundraiserService.$inject = ["gon", "$http", "$sce", "i18n"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = generosityFundraiserService;
	/*@ngInject*/
	
	function generosityFundraiserService(gon, $http, $sce, i18n) {
	  var service = {
	    loaded: false,
	    donations: [],
	    donationsCount: 0,
	    updates: []
	  };
	  var donationsPage = 1;
	
	  function refreshServiceUpdates(fundraiserJson) {
	    service.updates = fundraiserJson.updates;
	    _.each(service.updates, function (update) {
	      update.body_html = $sce.trustAsHtml(update.body_html);
	    });
	  }
	
	  service.refresh = function () {
	    return $http.get(gon.urls.fundraiser_json, { params: { locale: i18n.locale } }).then(function (response) {
	      var json = response.data.fundraiser;
	      service.donations = json.donations;
	      service.descriptionHtml = json.description_html;
	      service.donationsCount = json.donations_count;
	      service.canPostUpdate = json.can_post_update;
	      service.prohibitedUrl = json.prohibited_url;
	      service.hasEnded = json.has_ended;
	      service.perks = json.perks;
	      service.currencyIsoNum = json.currency_iso_num;
	      service.loaded = true;
	      refreshServiceUpdates(json);
	    });
	  };
	
	  service.fetchMoreDonations = function () {
	    ++donationsPage;
	    return $http.get(gon.urls.fundraiser_json, { params: { locale: i18n.locale, donations_page: donationsPage } }).then(function (response) {
	      service.donations = service.donations.concat(response.data.fundraiser.donations);
	      service.donationsCount = response.data.fundraiser.donations_count;
	    });
	  };
	
	  service.deleteUpdate = function (update) {
	    return $http.delete(update.delete_path).then(function (response) {
	      refreshServiceUpdates(response.data.fundraiser);
	    });
	  };
	
	  service.postUpdate = function (bodyHtml) {
	    return $http.post(gon.urls.fundraiser_new_update, {
	      body_html: bodyHtml
	    }).then(function (response) {
	      refreshServiceUpdates(response.data.fundraiser);
	    });
	  };
	
	  return service;
	}

/***/ },
/* 103 */
/***/ function(module, exports) {

	"use strict";
	
	generosityStoryTruncationService.$inject = ["gon", "browser"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = generosityStoryTruncationService;
	/*@ngInject*/
	
	function generosityStoryTruncationService(gon, browser) {
	  function truncationLength() {
	    return browser.isMobile() ? 395 : 525;
	  }
	
	  var service = {
	    truncationForTextLength: function truncationForTextLength(textLength) {
	      service.truncated = textLength >= truncationLength();
	    },
	    endTruncation: function endTruncation() {
	      service.truncated = false;
	    }
	  };
	
	  return service;
	}

/***/ },
/* 104 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	generosityPerksDirective.$inject = ["generosityFundraiser", "i18n", "$filter"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = generosityPerksDirective;
	/*@ngInject*/
	
	function generosityPerksDirective(generosityFundraiser, i18n, $filter) {
	  return {
	    scope: {},
	    template: __webpack_require__(105),
	    link: function link(scope) {
	      scope.perks = generosityFundraiser.perks;
	      scope.i18n = i18n;
	      scope.currencyIsoNum = generosityFundraiser.currencyIsoNum;
	      scope.deliveryDate = function (dateString) {
	        var date = new Date(dateString);
	        return $filter('date')(date, 'MMMM yyyy');
	      };
	    }
	  };
	}

/***/ },
/* 105 */
/***/ function(module, exports) {

	module.exports = "<span class=\"fundraiser-lined-header\">{{::i18n.t(\"donation_levels\")}}</span>\n\n<a ng-href=\"{{perk.contribute_path}}\" class=\"perk\" ng-repeat=\"perk in perks\" ng-class=\"{'perk-disabled': !perk.available}\">\n  <div class=\"perk-header\">\n    <span class=\"perk-amount\">{{::perk.amount | iggCurrency:currencyIsoNum:'noIso'}}</span>\n    <span class=\"perk-label\">{{::perk.label}}</span>\n  </div>\n  <div class=\"perk-description\">{{::perk.description}}</div>\n  <div class=\"perk-claimed\" ng-if=\"!perk.number_available\">{{::i18n.t('x_claimed', {number_claimed: perk.number_claimed, count: perk.number_claimed})}}</div>\n  <div class=\"perk-claimed\" ng-if=\"perk.number_available\">{{::i18n.t('x_out_of_y_claimed', {x: perk.number_claimed, y: perk.number_available, count: perk.number_claimed})}}</div>\n  <div class=\"perk-deliveryDate\" ng-if=\"perk.estimated_delivery_date\">{{::i18n.t('estimated_delivery_date', {estimated_delivery_date: deliveryDate(perk.estimated_delivery_date)})}} </div>\n</a>\n";

/***/ },
/* 106 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	generosityPostUpdateDirective.$inject = ["generosityFundraiser", "i18n", "stripTags", "updatePreview"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = generosityPostUpdateDirective;
	/*@ngInject*/
	
	function generosityPostUpdateDirective(generosityFundraiser, i18n, stripTags, updatePreview) {
	  return {
	    restrict: 'A',
	    scope: {},
	    template: __webpack_require__(107),
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.showSpinner = false;
	      scope.serverError = null;
	      scope.newUpdate = { bodyHtml: '' };
	      scope.disablePost = true;
	
	      var MIN_UPDATE_LENGTH = 2;
	      scope.MAX_UPDATE_LENGTH = 1500;
	
	      scope.$watch('newUpdate.bodyHtml', function (newVal, oldVal) {
	        var stripped = stripTags(newVal);
	        scope.serverError = null;
	        scope.disablePost = updatePreview.isDisabled = stripped.length > scope.MAX_UPDATE_LENGTH || stripped.length < MIN_UPDATE_LENGTH;
	        scope.ckeditorTooLong = stripped.length > scope.MAX_UPDATE_LENGTH;
	      });
	
	      scope.postUpdate = function () {
	        if (scope.disablePost) {
	          return;
	        }
	        scope.showSpinner = true;
	        generosityFundraiser.postUpdate(scope.newUpdate.bodyHtml).then(function () {
	          scope.showSpinner = false;
	          scope.$broadcast('postUpdateFinished');
	        }, function (response) {
	          scope.showSpinner = false;
	          scope.serverError = response.data.error;
	        });
	      };
	    }
	  };
	}

/***/ },
/* 107 */
/***/ function(module, exports) {

	module.exports = "<div class=\"fundraiser-lined-header\">{{::i18n.t(\"post_an_update\")}}</div>\n<form class=\"postUpdateForm\" novalidate>\n  <textarea ckeditor id=\"postUpdateInput\" ng-model=\"newUpdate.bodyHtml\"></textarea>\n  <div class=\"postUpdateForm-under\">\n    <button class=\"small-cta postUpdate-btn\" ng-click=\"postUpdate()\" ng-disabled=\"disablePost\">\n      <span ng-if=\"showSpinner\" class=\"fa fa-spinner fa-spin\"></span>\n      <span ng-if=\"!showSpinner\">{{::i18n.t('post_update')}}</span>\n    </button>\n    <div generosity-update-preview class=\"updatePreview\" body-html=\"newUpdate.bodyHtml\"></div>\n    <span class=\"postUpdate-error\" ng-if=\"newUpdate.bodyHtml.length > 1500\">{{::i18n.t(\"generosity.dashboard.updates_must_be_less_than\")}}</span>\n    <span class=\"postUpdate-error\" ng-if=\"serverError\">{{serverError}}</span>\n  </div>\n</form>\n";

/***/ },
/* 108 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	generosityStoryDirective.$inject = ["i18n", "$sce", "generosityFundraiser", "generosityStoryTruncation"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = generosityStoryDirective;
	/*@ngInject*/
	
	function generosityStoryDirective(i18n, $sce, generosityFundraiser, generosityStoryTruncation) {
	  return {
	    restrict: 'A',
	    scope: {},
	    template: __webpack_require__(109),
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.fundraiser = generosityFundraiser;
	      scope.storyTruncation = generosityStoryTruncation;
	      scope.$watch('fundraiser.descriptionHtml', function (descriptionHtml) {
	        if (typeof descriptionHtml !== 'undefined') {
	          scope.storyTruncation.truncationForTextLength(descriptionHtml.length);
	          scope.campaignStoryHtml = $sce.trustAsHtml(descriptionHtml);
	        }
	      });
	    }
	  };
	}

/***/ },
/* 109 */
/***/ function(module, exports) {

	module.exports = "<div class=\"fundraiser-lined-header\">{{::i18n.t('our_story')}}</div>\n<div class=\"story-content\">\n  <div class=\"story-bodySection\">\n    <div class=\"story-body\" ng-bind-html=\"campaignStoryHtml\" ng-class=\"{'story-body--truncated':storyTruncation.truncated, 'story-body--truncated--split':storyTruncation.truncated}\"></div>\n    <div class=\"story-truncateFade\" ng-if=\"storyTruncation.truncated\"></div>\n  </div>\n  <div class=\"story-showMoreSection\">\n    <a class=\"story-showMore secondary-cta--light\" ng-if=\"storyTruncation.truncated\" href='' ng-click=\"storyTruncation.endTruncation()\">{{::i18n.t(\"read_more\")}}</a>\n  </div>\n</div>\n";

/***/ },
/* 110 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	generosityUpdatesDirective.$inject = ["generosityFundraiser", "i18n", "$sce", "$modal"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = generosityUpdatesDirective;
	/*@ngInject*/
	
	function generosityUpdatesDirective(generosityFundraiser, i18n, $sce, $modal) {
	  return {
	    restrict: 'A',
	    scope: {},
	    template: __webpack_require__(111),
	    link: function link(scope) {
	      scope.numShown = 1;
	      scope.compressedMobile = true;
	      scope.i18n = i18n;
	      scope.fundraiser = generosityFundraiser;
	
	      scope.showMore = function () {
	        scope.numShown = scope.fundraiser.updates.length;
	      };
	
	      scope.toggleMobile = function () {
	        scope.numShown = scope.fundraiser.updates.length;
	        scope.compressedMobile = !scope.compressedMobile;
	      };
	
	      scope.showDeleteConfirmation = function (update) {
	        var deleteModal = null;
	        var modalScope = scope.$new();
	        modalScope.confirmDelete = function () {
	          generosityFundraiser.deleteUpdate(update).then(function () {
	            deleteModal.hide();
	          });
	        };
	
	        deleteModal = $modal({
	          scope: modalScope,
	          template: __webpack_require__(112)
	        });
	      };
	    }
	  };
	}

/***/ },
/* 111 */
/***/ function(module, exports) {

	module.exports = "<div class=\"donations-header\" ng-click=\"toggleMobile()\">\n  <span class=\"fundraiser-lined-header\">{{::i18n.t(\"generosity.updates\")}} {{fundraiser.updates.length | number}}</span>\n  <span class=\"donations-header-action visible-xs\" ng-if=\"compressedMobile\">+</span>\n  <span class=\"donations-header-action visible-xs\" ng-if=\"!compressedMobile\">-</span>\n</div>\n\n<div class=\"updates-container\" ng-class=\"{'hidden-xs': compressedMobile}\">\n  <div ng-repeat=\"update in fundraiser.updates | limitTo:numShown\" class=\"update\">\n    <div class=\"update-header\">\n      <div class=\"update-timestamp\">{{update.timestamp}}</div>\n      <a ng-if=\"update.delete_path\" href=\"\" class=\"update-delete-link\" ng-click=\"showDeleteConfirmation(update)\">{{::i18n.t('delete_update')}}</a>\n    </div>\n    <div class=\"update-body\" ng-bind-html=\"update.body_html\"></div>\n  </div>\n  <div class=\"donations-showMore\">\n    <a ng-if=\"numShown < fundraiser.updates.length\" href=\"\" class=\"secondary-cta--light\" ng-click=\"showMore()\">{{::i18n.t(\"generosity.see_all_updates\")}}</a>\n  </div>\n</div>\n";

/***/ },
/* 112 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal\">\n  <div class=\"modal-dialog lifeModal-dialog\">\n    <div class=\"modal-content lifeModal-content lifeModal-content--shady\">\n      <a class=\"lifeModal-close\" ng-click=\"$hide()\"><svg-icon icon=\"icon-icon-close\"></svg-icon></a>\n      <div class=\"lifeModal-container\">\n        <div class=\"lifeModal-headerText\">{{::i18n.t('deleting_update_cant_be_undone')}}</div>\n        <div class=\"lifeModal-bodyText\">{{::i18n.t('are_you_sure_you_want_to_continue')}}</div>\n        <div class=\"lifeModal-buttons\">\n          <a class=\"lifeModal-button lifeModal-button--cancel\" ng-click=\"$hide()\">{{::i18n.t(\"noway\") }}</a>\n          <a class=\"lifeModal-button pc-cta\" ng-click=\"confirmDelete()\">{{::i18n.t(\"yessir\")}}</a>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 113 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	generosityUpdatePreviewDirective.$inject = ["i18n", "updatePreview", "$modal", "$rootScope"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = generosityUpdatePreviewDirective;
	/*@ngInject*/
	
	function generosityUpdatePreviewDirective(i18n, updatePreview, $modal, $rootScope) {
	  return {
	    scope: {
	      bodyHtml: '='
	    },
	    template: __webpack_require__(114),
	    restrict: 'A',
	    link: function link(scope, element) {
	      scope.i18n = i18n;
	      scope.updatePreview = updatePreview;
	
	      scope.showPreviewAndTestModal = function () {
	        updatePreview.getPreview({ bodyHtml: scope.bodyHtml }).then(function (response) {
	          $modal({
	            template: __webpack_require__(115),
	            controller: 'UpdatePreviewModal'
	          });
	        });
	      };
	    }
	  };
	}

/***/ },
/* 114 */
/***/ function(module, exports) {

	module.exports = "<button\n  class=\"small-ghost-cta--light\"\n  ng-disabled=\"updatePreview.isDisabled\"\n  ng-click=\"showPreviewAndTestModal()\">\n  {{::i18n.t('preview_and_test.label')}}\n</button>\n\n";

/***/ },
/* 115 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal i-modal previewAndTestModal\">\n  <div class=\"modal-dialog lifeModal-dialog\">\n    <div class=\"modal-content lifeModal-content\">\n      <a class=\"lifeModal-close\" data-dismiss=\"modal\" aria-hidden=\"true\" ng-click=\"$hide()\"><svg-icon icon=\"icon-icon-close\"></svg-icon></a>\n      <div class=\"previewAndTestModal-header\">\n        {{::i18n.t('preview_and_test.label')}}\n      </div>\n      <div ng-if=\"updatePreview.isInitial() || updatePreview.isWorking()\" class=\"previewAndTestModal-email\">\n        <div class=\"i-block-label\">{{::i18n.t('preview_and_test.send_a_test_email')}}\n        </div>\n        <input type=\"text\" ng-model=\"updatePreview.email\" class=\"i-text-field i-text-field--50px\" placeholder=\"{{::i18n.t('preview_and_test.enter_email_address')}}\" />\n        <div class=\"i-button-row\">\n          <button class=\"i-cta-1\" ng-click=\"sendTest()\" ng-disabled=\"updatePreview.isWorking() || updatePreview.email.length === 0\">\n            {{updatePreview.isWorking() ? i18n.t('preview_and_test.sending') : i18n.t('preview_and_test.send_test')}}\n          </button>\n        </div>\n      </div>\n      <div class=\"previewAndTestModal-complete\" ng-if=\"updatePreview.isComplete()\">\n        <img class=\"previewAndTestModal-complete--image\" ng-src=\"{{updatePreview.confirmationImagePath}}\"/>\n        <div class=\"previewAndTestModal-complete--email\">\n          {{::i18n.t('preview_and_test.email_sent', { email: updatePreview.email })}}\n        </div>\n        <a class=\"previewAndTestModal-complete--again\" ng-click=\"resetPreviewState()\">\n          {{::i18n.t('preview_and_test.send_another')}}\n        </a>\n      </div>\n      <div class=\"previewAndTestModal-preview\">\n        <div class=\"previewAndTestModal-preview--container\">\n          <div class=\"previewAndTestModal-preview--bar\">\n          </div>\n          <div class=\"previewAndTestModal-preview--header\">\n            {{::i18n.t('preview_and_test.html_preview')}}\n          </div>\n        </div>\n        <div class=\"previewAndTestModal-preview--body\" ng-bind-html=\"updatePreview.trustedHtml\">\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n\n\n";

/***/ },
/* 116 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	campaignLoginDirective.$inject = ["campaign", "$state", "i18n"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = campaignLoginDirective;
	/*@ngInject*/
	
	function campaignLoginDirective(campaign, $state, i18n) {
	  return {
	    restrict: 'A',
	    scope: {
	      path: '='
	    },
	    transclude: false,
	    replace: false,
	    template: __webpack_require__(117),
	    link: function link(scope, element, attrs, nullController, transclude) {
	      scope.campaign = campaign;
	      scope.i18n = i18n;
	
	      scope.hideModal = function () {
	        $(element).addClass("i-hidden");
	      };
	
	      element.bind('click', function (e) {
	        if (e.target !== this) {
	          return;
	        }
	        scope.hideModal();
	      });
	    }
	  };
	}

/***/ },
/* 117 */
/***/ function(module, exports) {

	module.exports = "<div class=\"i-login-modal\">\n  <a href=\"\" class=\"modal-close\" ng-click=\"hideModal()\"><svg><use xlink:href=\"#icon-icon-close\"></use></svg></a>\n  <h3 class=\"facebook-login-title\">{{::i18n.t(\"follow_this_campaign\")}}</h3>\n  <p class=\"facebook-login-subtitle\">{{::i18n.t(\"mobile.keep_track_of_this_campaign\")}}</p>\n  <!-- TODO EVENTS: id=shoo3 fixtype=ga-event-dir category=Mobile.Web.Campaign.Page action=Login.from.Follow.Modal subsystem=accounts trigger=click dom=a name-new=TBD . review -->\n  <a href=\"{{path}}\"\n     class=\"facebook-login-btn ui-btn\"\n     ga-event-on=\"click\"\n     ga-event-category=\"Mobile Web Campaign Page\"\n     ga-event-action=\"Login from Follow Modal\">\n    <svg><use xlink:href=\"#icon-icon-facebook\"></use></svg>\n    <span>{{::i18n.t(\"log_in_with_facebook\")}}</span>\n  </a>\n  <p class=\"facebook-login-permissions\">{{::i18n.t(\"mobile.never_post_without_fb_permission\")}}</p>\n</div>\n";

/***/ },
/* 118 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = campaignMainDirective;
	/*@ngInject*/
	
	function campaignMainDirective() {
	  return {
	    restrict: 'E',
	    scope: {},
	    template: __webpack_require__(119)
	  };
	}

/***/ },
/* 119 */
/***/ function(module, exports) {

	module.exports = "<fb-tracking-pixel></fb-tracking-pixel>\n\n<campaign-pitchmedia></campaign-pitchmedia>\n<div class=\"campaignPrimarySection\">\n  <div class=\"row\"><campaign-header></campaign-header></div>\n  <div class=\"row\"><campaign-tagline-story></campaign-tagline-story></div>\n  <div ng-if=\"!campaign.isInDemand()\" class=\"row\"><campaign-goal></campaign-goal></div>\n  <div ng-if=\"campaign.isInDemand()\" class=\"row\"><pre-order-funding-info></pre-order-funding-info></div>\n  <div ng-if=\"!campaign.isInDemand() || !campaign.perks_available\" class=\"row\"><campaign-contribute></campaign-contribute></div>\n</div>\n\n<div class=\"i-campaignTrustTeaser\" campaign-trust-teaser></div>\n\n\n<div\n  ng-if=\"perks.length > 0 && campaign.isInDemand() && !campaign.is_pre_order_campaign\"\n  class=\"i-perks-header i-campaign-section-header i-campaign-section-header--slim\">\n</div>\n\n<div\n  ng-if=\"campaign.is_pre_order_campaign\"\n  class=\"i-campaign-section-header preOrderPerks-header\">\n  {{::i18n.t('perks')}}\n</div>\n\n<div class=\"i-campaign-perks\" id=\"perks\" campaign-perks></div>\n";

/***/ },
/* 120 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	campaignStoryDirective.$inject = ["campaign", "i18n", "gon"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = campaignStoryDirective;
	/*@ngInject*/
	
	function campaignStoryDirective(campaign, i18n, gon) {
	  return {
	    restrict: 'A',
	    scope: {},
	    transclude: false,
	    replace: false,
	    template: __webpack_require__(121),
	    link: function link(scope) {
	      scope.campaign = campaign;
	      scope.i18n = i18n;
	      scope.campaignContributionPath = gon.urls.campaign_contribution_path;
	
	      scope.showContributeSection = function () {
	        return campaign.nonprofit || campaign.partner_name || campaign.state() === campaign.states.draft || campaign.state() === campaign.states.published || campaign.state() === campaign.states.inDemand;
	      };
	
	      scope.showContributeButton = function () {
	        return !campaign.funding_invalid_yet_live && (campaign.state() === campaign.states.published || campaign.state() === campaign.states.inDemand);
	      };
	    }
	  };
	}

/***/ },
/* 121 */
/***/ function(module, exports) {

	module.exports = "<!-- TODO EVENTS: id=aing9 fixtype=ga-event-dir trigger=click dom=section category=Mobile.Web.Campaign.Page action=Tap.Story.Back.Button label=Top subsystem=campaign-page name-new=TBD . review -->\n<section class=\"i-campaignStory-header\"\n         ui-sref=\"main\"\n         ga-event-on=\"click\"\n         ga-event-category=\"Mobile Web Campaign Page\"\n         ga-event-action=\"Tap Story Back Button\"\n         ga-event-label=\"Top\"\n         style=\"background-image: url({{campaign.image_types.medium}})\">\n  <div class=\"i-campaignStory-headerOverlay\">\n    <svg><use xlink:href=\"#left-caret\"></use></svg>\n    <span>{{campaign.title}}</span>\n  </div>\n</section>\n\n<!-- don't show this section if it has nothing inside so things look nice -->\n<!-- TODO: remove showContributeSection due to new styling -->\n<section\n  class=\"i-campaignStory-contributeSection\"\n  ng-if=\"showContributeSection()\">\n\n  <!-- TODO EVENTS: id=ohqu5 fixtype=ga-event-dir subsystem=campaign-page category-new=Mobile.Web.Campaign.Page name-new=TBD dom=collapsable . ga-category and ga-action likely useless -->\n  <collapsable title=\"{{i18n.t('verified_nonprofit')}}\"\n               icon=\"icon-icon-charity\"\n               has-content=\"{{!!campaign.nonprofit_campaign_page_description}}\"\n               ng-if=\"campaign.nonprofit\"\n               ga-category=\"Mobile Web Campaign Page\"\n               ga-action=\"Expand Non-Profit\">{{campaign.nonprofit_campaign_page_description}}\n  </collapsable>\n\n  <!-- TODO EVENTS: id=hai2j fixtype=ga-event-dir subsystem=campaign-page category-new=Mobile.Web.Campaign.Page name-new=TBD dom=collapsable . ga-category and ga-action likely useless -->\n  <collapsable title=\"{{campaign.partner_name}}\"\n               image-url=\"{{campaign.partner_image_url}}\"\n               has-content=\"{{!!campaign.partner_campaign_page_description}}\"\n               ng-if=\"campaign.partner_name\"\n               ga-category=\"Mobile Web Campaign Page\"\n               ga-action=\"Expand Sponsorship\">{{campaign.partner_campaign_page_description}}\n  </collapsable>\n\n  <!-- TODO EVENTS: id=xee6u fixtype=ga-event-dir trigger=click dom=div category=Mobile.Web.Campaign.Page action=Tap.Contribute.Now.Button label=Read.Story.Top subsystem=campaign-page name-new=TBD . review -->\n  <div class=\"i-campaignStory-contributeButton-container\" ng-if=\"showContributeButton()\">\n    <a\n      class=\"i-campaignStory-contributeButton i-cta-1\"\n      href=\"{{campaignContributionPath}}\"\n      ga-event-on=\"click\"\n      ga-event-category=\"Mobile Web Campaign Page\"\n      ga-event-action=\"Tap Contribute Now Button\"\n      ga-event-label=\"Read Story Top\">\n      {{i18n.t(\"contribute_now\")}}\n    </a>\n  </div>\n\n  <div\n    ng-if=\"campaign.state() === campaign.states.draft\"\n    class=\"i-campaignStory-contributeButton i-cta-1\"\n    disabled>\n    {{::i18n.t(\"contribute_now\")}}\n  </div>\n</section>\n\n<section class=\"i-campaign-webview\">\n  <campaign-description class=\"i-campaignStory-description i-campaign-description\"></campaign-description>\n</section>\n\n<hr class=\"i-separator--campaignPage\">\n\n<!-- TODO EVENTS: id=dae4r fixtype=ga-event-dir trigger=click category=Mobile.Web.Campaign.Page action=Tap.Story.Back.Button label=Bottom subsystem=campaign-page dom=section name-new=TBD . review -->\n<section class=\"i-campaignStory-footer\">\n  <a class=\"i-campaignStory-footer-back\"\n     ui-sref=\"main\"\n     ga-event-on=\"click\"\n     ga-event-category=\"Mobile Web Campaign Page\"\n     ga-event-action=\"Tap Story Back Button\"\n     ga-event-label=\"Bottom\">\n    <svg class=\"i-campaignStory-footer-backArrow\"><use xlink:href=\"#left-caret\"></use></svg>\n    <span class=\"i-campaignStory-footer-title\">{{campaign.title}}</span>\n  </a>\n\n  <!-- TODO EVENTS: id=ip9yo fixtype=ga-event-dir trigger=click dom=a category=Mobile.Web.Campaign.Page action=Tap.Contribute.Now.Button label=Read.Story.Bottom subsystem=campaign-page name-new=TBD . review -->\n  <a\n    ng-if=\"showContributeButton()\"\n    class=\"i-campaignStory-contributeButton i-cta-1\"\n    href=\"{{campaignContributionPath}}\"\n    ga-event-on=\"click\"\n    ga-event-category=\"Mobile Web Campaign Page\"\n    ga-event-action=\"Tap Contribute Now Button\"\n    ga-event-label=\"Read Story Bottom\">\n    {{::i18n.t(\"contribute_now\")}}\n  </a>\n\n  <div\n    ng-if=\"campaign.state() === campaign.states.draft\"\n    class=\"i-campaignStory-contributeButton i-cta-1\"\n    disabled>\n    {{::i18n.t(\"contribute_now\")}}\n  </div>\n</section>\n";

/***/ },
/* 122 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";
	
	collapsableDirective.$inject = ["$compile"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = collapsableDirective;
	/*@ngInject*/
	
	function collapsableDirective($compile) {
	  return {
	    restrict: 'E',
	    scope: {
	      imageUrl: "@",
	      title: "@",
	      subtitle: "@",
	      collapsed: "@",
	      icon: '@',
	      hasContent: "@",
	      gaCategory: "@",
	      gaEvent: "@"
	    },
	    transclude: true,
	    template: __webpack_require__(123),
	    link: function link(scope) {
	      scope.hasExpandableContent = scope.hasContent === 'true';
	      scope.showCollapseControl = scope.hasExpandableContent;
	      if (scope.icon) {
	        scope.iconRef = '#' + scope.icon;
	      }
	
	      var itemCollapsed = true;
	      if (scope.collapsed) {
	        itemCollapsed = scope.collapsed === 'true';
	      }
	
	      scope.itemOpen = scope.hasExpandableContent && !itemCollapsed;
	
	      scope.toggleItemOpen = function () {
	        scope.itemOpen = !scope.itemOpen;
	      };
	    }
	  };
	}

/***/ },
/* 123 */
/***/ function(module, exports) {

	module.exports = "<div class=\"i-collapsable\">\n  <div class=\"i-collapsable-sidebar\" ng-if=\"imageUrl || icon\">\n    <img class=\"i-collapsable-image\" ng-src=\"{{imageUrl}}\" ng-if=\"imageUrl\">\n    <svg class=\"i-collapsable-glyph\" ng-if=\"icon && !imageUrl\"><use xlink:href=\"{{iconRef}}\"></use></svg>\n  </div>\n  <div class=\"i-collapsable-caret\" ng-if=\"showCollapseControl\" ng-click=\"toggleItemOpen()\">\n    <svg ng-if=\"!itemOpen\"><use xlink:href=\"#down-caret\"></use></svg>\n    <svg ng-if=\"itemOpen\"><use xlink:href=\"#up-caret\"></use></svg>\n  </div>\n  <div class=\"i-collapsable-content\">\n    <!-- TODO EVENTS: id=bu0ox fixtype=ga-event-dir category=gaCategory category-new=TBD action=gaAction action-new=TBD name-new=TBD subsystem=campaign-page . looks like category and action bugs -->\n    <div class=\"i-collapsable-header\"\n         ng-click=\"toggleItemOpen()\"\n         analytics-on=\"click\"\n         analytics-name=\"mobile_web_campaign_page_collapsable_header_toggle\"\n         analytics-category=\"gaCategory\"\n         analytics-event=\"ToggleCollapsibleHeader\">\n\n      <div class=\"i-collapsable-title\" ng-if=\"title\">{{title}}</div>\n      <div class=\"i-collapsable-subtitle\" ng-if=\"subtitle\">{{subtitle}}</div>\n    </div>\n\n    <div\n      class=\"i-collapsable-expanded\"\n      ng-if=\"hasExpandableContent\"\n      ng-show=\"itemOpen\"\n      ng-transclude>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 124 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";
	
	emailImporterDirective.$inject = ["i18n", "$modal", "emailImporter", "flash", "browser", "$timeout", "gon", "$http"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = emailImporterDirective;
	/*@ngInject*/
	
	function emailImporterDirective(i18n, $modal, emailImporter, flash, browser, $timeout, gon, $http) {
	  return {
	    scope: {
	      postEmailCallback: "&",
	      emailFrom: "@",
	      emailImporterClick: '&'
	    },
	    replace: true,
	    template: __webpack_require__(125),
	    transclude: true,
	    link: function link(scope, element, attrs) {
	      var CONTACT_OFFSET = 92;
	      var VIEW_OFFSET = 185;
	      var VALID_EMAIL = /.*@.*\..{2,}/;
	      var currentAccount = _(gon.current_account).clone() || {};
	      var postEmailCallback = scope.postEmailCallback;
	      var fundraiserRecipient = gon.fundraiser && gon.fundraiser.fundraiser_recipient;
	      var fundraiserTitle = gon.fundraiser && gon.fundraiser.title;
	      var emailFrom = scope.emailFrom || 'from_supporter';
	      var onGenerosity = gon.domain === 'generosity';
	      var yahooProvider;
	      var googleProvider;
	
	      scope.onGenerosity = onGenerosity;
	
	      if (onGenerosity) {
	        yahooProvider = 'yahoo_generosity';
	        googleProvider = 'gmail_generosity';
	      } else {
	        yahooProvider = 'yahoo';
	        googleProvider = 'gmail';
	      }
	
	      function changeSelectedStatus(contact, newContactStatus) {
	        if (contact.isSelected !== newContactStatus) {
	          contact.isSelected = newContactStatus;
	          if (contact.isSelected) {
	            scope.totalSelected += 1;
	          } else {
	            scope.totalSelected -= 1;
	          }
	        }
	
	        var contactLi = findContactLi(contact);
	        contactLi.toggleClass('ng-hide', !scope.showContact(contact));
	        updateContactSelectionLook(contact);
	      }
	
	      function updateContactSelectionLook(contact) {
	        var contactLi = findContactLi(contact);
	        var checkbox = contactLi.find('div.pull-right');
	        checkbox.toggleClass('pc-checked-checkbox', contact.isSelected);
	        checkbox.toggleClass('pc-unchecked-checkbox', !contact.isSelected);
	      }
	
	      function updateContactListVisibility() {
	        scope.contactList.forEach(function (contact) {
	          var contactLi = findContactLi(contact);
	          contactLi.toggleClass('ng-hide', !scope.showContact(contact));
	        });
	      }
	
	      scope.i18n = i18n;
	      scope.contact = {};
	      scope.gmailImported = false;
	      scope.yahooImported = false;
	      scope.isComposing = false;
	      scope.totalSelected = 0;
	      scope.showSelectedContacts = false;
	
	      scope.ableToCompose = function () {
	        return scope.contactList.length > 0 && scope.totalSelected > 0 && scope.remainingCount() > 0;
	      };
	
	      scope.onImporterClick = function () {
	        if (attrs.emailImporterClick) {
	          scope.emailImporterClick();
	        } else {
	          scope.openModal();
	        }
	      };
	
	      scope.message = {
	        subject: i18n.pt('email_import.' + emailFrom + '.email_subject', { project_title: fundraiserTitle, full_name: currentAccount.full_name })
	      };
	
	      var i18nOptions, key;
	      if (!!fundraiserRecipient && onGenerosity) {
	        i18nOptions = {
	          project_title: fundraiserTitle,
	          beneficiary: fundraiserRecipient,
	          organizer_name: currentAccount.full_name
	        };
	
	        key = '.email_message_with_beneficiary';
	
	        scope.message.body = i18n.pt('email_import.' + emailFrom + key, i18nOptions);
	      } else {
	        i18nOptions = {
	          project_title: fundraiserTitle,
	          organizer_name: currentAccount.full_name
	        };
	
	        key = '.email_message';
	
	        scope.message.body = i18n.pt('email_import.' + emailFrom + key, i18nOptions);
	      }
	
	      var selectedContacts = function selectedContacts() {
	        return scope.contactList.filter(function (contact) {
	          return contact.isSelected;
	        });
	      };
	
	      var selectedContactsIds = function selectedContactsIds() {
	        return selectedContacts().map(function (contact) {
	          return contact.id;
	        });
	      };
	
	      var findContactLi = function findContactLi(contact) {
	        return modal.$element.find(".emailImporter-contactList-contact#email-contact-" + contact.id);
	      };
	
	      var viewHeight = function viewHeight() {
	        return Math.max(browser.height() * 0.9 - 600, 200);
	      };
	
	      scope.contactListHeight = function () {
	        if (scope.showSelectedContacts) {
	          var msgHeight = modal.$element.find('.emailImporter-importContacts-selectedMessage').height();
	          return viewHeight() - msgHeight - 42 + 'px';
	        } else {
	          return viewHeight() + 'px';
	        }
	      };
	
	      scope.emailChanged = function () {
	        updateContactListVisibility();
	      };
	
	      scope.showContact = function (contactItem) {
	        if (scope.showSelectedContacts && !contactItem.isSelected) {
	          return false;
	        }
	        if (scope.contact.email) {
	          if (contactItem.email.toLowerCase().indexOf(scope.contact.email.toLowerCase()) === -1) {
	            return false;
	          }
	        }
	        return true;
	      };
	
	      var modal;
	      scope.openModal = function () {
	        if (gon.current_account) {
	          if (modal) {
	            modal.show();
	          } else {
	            $http.get(gon.urls.email_contacts).then(function (response) {
	              var json = response.data;
	              scope.contactList = json.email_contacts || [];
	              var contactsData = json.email_contacts_data || {};
	              scope.remainingCount = function () {
	                return contactsData.remaining - scope.totalSelected;
	              };
	              scope.emailLimitReachedMsg = i18n.t('email_import.limit_reached', {
	                daily_limit: contactsData.max
	              });
	              scope.remainingMessage = function () {
	                return i18n.t('email_import.emails_remaining', { remaining: scope.remainingCount(), daily_limit: contactsData.max });
	              };
	
	              modal = $modal({ scope: scope, template: __webpack_require__(126) });
	            });
	          }
	        } else {
	          browser.redirectTo(gon.urls.email_login_url);
	        }
	      };
	
	      scope.validEmail = function () {
	        return scope.contact.email && scope.contact.email.match(VALID_EMAIL);
	      };
	
	      scope.onlyShowSelectedContacts = function () {
	        scope.showSelectedContacts = true;
	        updateContactListVisibility();
	      };
	
	      scope.showAllContacts = function () {
	        scope.showSelectedContacts = false;
	        updateContactListVisibility();
	      };
	
	      scope.toggleSelection = function (event) {
	        var contactId = $(event.target).closest('li').attr('id').replace('email-contact-', '');
	        var contact = _.findWhere(scope.contactList, { id: +contactId });
	        changeSelectedStatus(contact, !contact.isSelected);
	      };
	
	      scope.addContact = function () {
	        emailImporter.createContact({ email: scope.contact.email }).then(function (contact) {
	          if (contact) {
	            scope.contactList.push(contact);
	
	            $timeout(function () {
	              updateContactListVisibility();
	              changeSelectedStatus(contact, true);
	
	              var contactLi = findContactLi(contact);
	
	              if (contactLi.position()) {
	                var contactPosition = contactLi.position().top - CONTACT_OFFSET;
	                var contactList = modal.$element.find('.emailImporter-importContacts-contactList');
	                contactList.animate({ scrollTop: contactPosition });
	              }
	            });
	          }
	        });
	
	        scope.contact.email = '';
	      };
	
	      scope.allContactsSelected = function () {
	        return scope.totalSelected === scope.contactList.length && scope.contactList.length > 0;
	      };
	
	      scope.sendMessages = function (message) {
	        emailImporter.sendBulkMessages(message, selectedContactsIds()).then(function () {
	          flash.addMessage('notice', i18n.t('email_import.successful_send'));
	          modal.hide();
	          scope.isComposing = false;
	
	          if (postEmailCallback) {
	            postEmailCallback();
	          }
	        });
	      };
	
	      scope.selectAllContacts = function (newContactStatus) {
	        if (newContactStatus) {
	          scope.showSelectedContacts = false;
	        }
	        scope.contactList.forEach(function (contact) {
	          changeSelectedStatus(contact, newContactStatus);
	        });
	      };
	
	      scope.messageFieldHeight = function () {
	        return viewHeight() + VIEW_OFFSET + 'px';
	      };
	
	      scope.toggleCompose = function () {
	        scope.isComposing = !scope.isComposing;
	      };
	
	      scope.importGmailContacts = function () {
	        emailImporter.importContacts(googleProvider).then(function (contacts) {
	          scope.contactList = contacts.concat(scope.contactList);
	          scope.gmailImported = true;
	        });
	      };
	
	      scope.importYahooContacts = function () {
	        emailImporter.importContacts(yahooProvider).then(function (contacts) {
	          scope.contactList = contacts.concat(scope.contactList);
	          scope.yahooImported = true;
	        });
	      };
	
	      browser.onLoad(function () {
	        if (gon.show_email_importer && gon.current_account) {
	          scope.openModal();
	        }
	      });
	
	      scope.$on('emailImporter.launch', function () {
	        scope.openModal();
	      });
	    }
	  };
	}

/***/ },
/* 125 */
/***/ function(module, exports) {

	module.exports = "<a href=\"\" ng-click=\"onImporterClick()\" ng-transclude></a>\n";

/***/ },
/* 126 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal modal--emailImporter\">\n  <div class=\"modal-dialog modal-dialog--emailImporter\">\n    <div class=\"modal-content modal-content--emailImporter\">\n      <a class=\"modal-close emailImporter-close\" ng-click=\"$hide()\" aria-hidden=\"true\">\n        <svg-icon icon=\"icon-icon-close\"></svg-icon>\n      </a>\n      <h1 class=\"emailImporter-title\">{{::i18n.pt('email_import.share_this_campaign')}}</h1>\n\n      <div class=\"emailImporter-importView\" ng-hide=\"isComposing\">\n        <div class=\"i-musty-background emailImporter-importContacts\">\n          <p class=\"emailImporter-importContacts-heading\">{{::i18n.t('email_import.import_contacts')}}</p>\n          <p class=\"emailImporter-importContacts-subheading\">{{::i18n.t('email_import.add_existing')}}</p>\n\n          <div class=\"emailImporter-importContacts-emails\">\n            <div class=\"emailImporter-provider\" ng-click=\"importGmailContacts()\" ng-class=\"{imported: gmailImported}\">\n              <div class=\"emailImporter-provider-icon emailImporter-provider-icon--gmail\"></div>\n              <span class=\"emailImporter-provider-name\">Gmail</span>\n              <div ng-if=\"gmailImported\" class=\"emailImporter-provider-checkmark\"></div>\n            </div>\n            <div class=\"emailImporter-provider\" ng-click=\"importYahooContacts()\" ng-class=\"{imported: yahooImported}\">\n              <div class=\"emailImporter-provider-icon emailImporter-provider-icon--yahoo\"></div>\n              <span class=\"emailImporter-provider-name\">Yahoo!</span>\n              <div ng-if=\"yahooImported\" class=\"emailImporter-provider-checkmark\"></div>\n            </div>\n          </div>\n        </div>\n\n        <div class=\"i-musty-background emailImporter-contactList\">\n          <form ng-submit=\"addContact()\" class=\"emailImporter-addContact\">\n            <input type=\"text\" class=\"i-text-field emailImporter-addContact-inputField\" placeholder=\"Enter an email\" ng-model=\"contact.email\" ng-change=\"emailChanged()\" />\n            <input type=\"submit\" class=\"i-cta-1 i-cta-1--grey emailImporter-addContact-button\" ng-disabled=\"!validEmail()\" value=\"{{::i18n.t('email_import.button_add')}}\" />\n          </form>\n\n          <div class=\"emailImporter-importContacts-selectedMessage\" ng-if=\"showSelectedContacts\">\n            {{i18n.t('email_import.selected_recipient_count', {selected_count: totalSelected})}} — <a href=\"\" ng-click=\"showAllContacts()\">{{i18n.t('email_import.total_recipient_count', {total_count: contactList.length})}}</a>\n          </div>\n\n          <div class=\"emailImporter-importContacts-contactList\" ng-style=\"{height: contactListHeight(), lineHeight: contactListHeight()}\" ng-click=\"toggleSelection($event)\">\n            <div ng-if=\"contactList.length === 0\" class=\"emailImporter-noContacts\">{{::i18n.t('email_import.no_contacts')}}</div>\n            <ul>\n              <li id=\"{{::'email-contact-' + contactItem.id}}\" class=\"emailImporter-contactList-contact\" ng-repeat=\"contactItem in contactList | orderBy:'email' track by contactItem.id\"><span>{{::contactItem.email}}</span><div class=\"pull-right pc-unchecked-checkbox\"></div></li>\n            </ul>\n          </div>\n\n          <div class=\"emailImporter-importContacts-recipients\">\n            {{::i18n.t('email_import.recipients')}} (<a href=\"\" ng-click=\"onlyShowSelectedContacts()\">{{totalSelected}}</a>)\n          </div>\n          <div ng-if=\"!allContactsSelected()\" class=\"emailImporter-importContacts-selectAll\" ng-click=\"selectAllContacts(true)\">\n            <span>{{::i18n.t('email_import.select_all')}}</span>\n            <div class=\"pull-right pc-unchecked-checkbox\"></div>\n          </div>\n          <div ng-if=\"allContactsSelected()\" class=\"emailImporter-importContacts-selectAll\" ng-click=\"selectAllContacts(false)\">\n            <span>{{::i18n.t('email_import.select_all')}}</span>\n            <div class=\"pull-right pc-checked-checkbox\"></div>\n          </div>\n        </div>\n      </div>\n\n      <div class=\"emailImporter-messageComposeView i-musty-background\" ng-show=\"isComposing\">\n        <p class=\"emailImporter-composeLabel\">{{::i18n.t('email_import.email_subject')}}</p>\n        <input type=\"text\" class=\"i-text-field emailImporter-subjectField\" ng-model=\"message.subject\"/>\n        <p class=\"emailImporter-composeLabel\">{{::i18n.t('message_label')}}</p>\n        <textarea class=\"emailImporter-messageField\" ng-model=\"message.body\" ng-style=\"{height: messageFieldHeight()}\"></textarea>\n      </div>\n\n      <div class=\"emailImporter-linkMessage\" ng-show=\"isComposing\">{{::i18n.t('email_import.campaign_link_message')}}</div>\n\n      <div class=\"emailImporter-actions\" ng-if=\"!isComposing\">\n          <div class=\"emailImporter-actions-remainingArea\">\n            <div class=\"emailImporter-actions-remainingError\" ng-if=\"remainingCount() <= 0\">\n              <span>{{::emailLimitReachedMsg}}</span>\n            </div>\n            <div class=\"emailImporter-actions-remainingWarning\" ng-if=\"remainingCount() < 250 && remainingCount() > 0\">{{remainingMessage()}}</div>\n          </div>\n        <button class=\"emailImporter-actions-button i-cta i-cta-1\" ng-click=\"toggleCompose()\" ng-disabled=\"!ableToCompose()\">{{::i18n.t('email_import.button_compose')}}</button>\n      </div>\n      <div class=\"emailImporter-actions\" ng-if=\"isComposing\">\n        <!-- TODO EVENTS: id=aido2 fixtype=event-dir subsystem=share trigger=click dom=button name=click_send_email_importer category-new=TBD label=TBD . review -->\n        <button class=\"emailImporter-actions-button i-cta-1 emailImporter-sendMessagesBtn\" ng-click=\"sendMessages(message)\" ng-disabled=\"!message.subject || !message.body\"\n                event-on=\"click\" event-name=\"click_send_email_importer\">{{::i18n.t('email_import.button_send')}}</button>\n        <button class=\"emailImporter-actions-button i-cta-1 i-cta-1--grey emailImporter-backBtn\" ng-click=\"toggleCompose()\" >{{::i18n.t('email_import.button_back')}}</button>\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 127 */
/***/ function(module, exports) {

	'use strict';
	
	emailImporterDirective.$inject = ["$http", "$window", "browser", "$q", "gon"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = emailImporterDirective;
	/*@ngInject*/
	
	function emailImporterDirective($http, $window, browser, $q, gon) {
	  var service = {};
	
	  service.createContact = function (contact) {
	    var data = { source_type: 'user_entered', email: contact.email };
	
	    return $http.post(gon.urls.contact_create_url, { contact: data }).then(function (response) {
	      return response.data;
	    });
	  };
	
	  service.sendBulkMessages = function (message, contactIds) {
	    var email = {
	      project_id: gon.fundraiser.id,
	      subject: message.subject,
	      message: message.body,
	      email_contact_ids: contactIds
	    };
	    return $http.post(gon.urls.bulk_message_url, { email: email });
	  };
	
	  service.importContacts = function (provider) {
	    var deferred = $q.defer();
	    $window.addContacts = function (contacts) {
	      deferred.resolve(contacts);
	    };
	
	    browser.openWindow('/contacts/' + provider, provider, { width: 800, height: 600 });
	    return deferred.promise;
	  };
	
	  return service;
	}

/***/ },
/* 128 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	shareWizardDirective.$inject = ["browser", "$timeout", "i18n", "fb", "$state", "twitter", "gogoEvents", "gon", "todoItems", "$http", "fbAutopost", "flash"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = shareWizardDirective;
	/*@ngInject*/
	
	function shareWizardDirective(browser, $timeout, i18n, fb, $state, twitter, gogoEvents, gon, todoItems, $http, fbAutopost, flash) {
	  return {
	    scope: {
	      disableAutopost: '=?'
	    },
	    template: __webpack_require__(129),
	    link: function link(scope, element) {
	      var currentAccount = _.clone(gon.current_account);
	      var eventMap = {
	        "facebook": "share_wizard_fb",
	        "facebook-2": "share_wizard_fb_2",
	        "twitter": "share_wizard_tw",
	        "email": "share_wizard_email"
	      };
	
	      var eventPage = function eventPage() {
	        return eventMap[$state.current.name];
	      };
	
	      var defaultEventProperties = _.clone(gon.default_event_properties);
	
	      scope.eventTags = function () {
	        return _.merge({ page: eventPage() }, defaultEventProperties);
	      };
	
	      scope.i18n = i18n;
	      scope.urls = gon.urls;
	      scope.fundraiser = gon.fundraiser;
	      scope.facebookShared = false;
	      scope.twitterShared = false;
	      scope.twitterShareUrl = gon.urls.twitter_share_url;
	      scope.fbAutopost = fbAutopost;
	
	      var autopostCapable = !scope.disableAutopost;
	      scope.autopostCapable = autopostCapable;
	      scope.autopostCheckbox = autopostCapable;
	
	      scope.autopostChecked = currentAccount.facebook_can_wall_post;
	
	      scope.domain = gon.domain;
	
	      scope.facebookShareText = i18n.pt('share_wizard.support_by_sharing_on_facebook', { title: gon.fundraiser.title });
	      scope.twitterShareText = i18n.pt('share_wizard.twitter_blurb', { fundraiser_url: gon.urls.fundraiser_short_link, fundraiser_title: gon.fundraiser.title });
	      scope.waysToHelp = i18n.pt('share_wizard.email_mock.ways_to_help');
	
	      twitter.onTweet(function () {
	        scope.twitterShared = true;
	        todoItems.markCompleted('twitter_share');
	        scope.goTo('email');
	      });
	
	      scope.shareFacebook = function () {
	        if (scope.autopostCheckbox && !currentAccount.facebook_can_wall_post) {
	          browser.redirectTo(gon.urls.facebook_authorize_url);
	        } else {
	          // TODO EVENTS: id=iey7o fixtype=fb-share subsystem=share . review
	          fb.share(scope.urls.facebook_share_url, { account_id: currentAccount.account_id }).then(function () {
	            if (autopostCapable) {
	              fbAutopost.setPostingActive(scope.autopostCheckbox).then(function () {
	                if (fbAutopost.postingActive) {
	                  // TODO EVENTS: id=ah4ha fixtype=captureEvent name=automatic_fb_post_share_wizard category-new=TBD subsystem=share . review
	                  gogoEvents.captureEvent('automatic_fb_post_share_wizard');
	                }
	                markCompletedAndMoveOn();
	              });
	            } else {
	              markCompletedAndMoveOn();
	            }
	          }).catch(function () {
	            if ($state.current.name == 'facebook-2') {
	              scope.goTo('twitter');
	            } else {
	              scope.goTo('facebook-2');
	            }
	          });
	        }
	
	        function markCompletedAndMoveOn() {
	          todoItems.markCompleted('facebook_share');
	          scope.goTo('twitter');
	          scope.facebookShared = true;
	        }
	      };
	
	      scope.toggleAutoFbPost = function () {
	        if (currentAccount.facebook_can_wall_post) {
	          scope.autopostCheckbox = !scope.autopostCheckbox;
	          scope.autopostChecked = !scope.autopostChecked;
	          fbAutopost.setPostingActive(scope.autopostCheckbox).then(function () {
	            var flashMessage = fbAutopost.postingActive ? i18n.pt('share_wizard.great_well_post_your_fundraiser_to_facebook') : i18n.pt('share_wizard.successfully_opted_out_of_autopost');
	            flash.addMessage('notice', flashMessage);
	            if (fbAutopost.postingActive) {
	              // TODO EVENTS: id=ah4hb fixtype=captureEvent name=automatic_fb_post_share_wizard category-new=TBD subsystem=share . review
	              gogoEvents.captureEvent('automatic_fb_post_share_wizard');
	            }
	          });
	        } else {
	          browser.redirectTo(gon.urls.facebook_authorize_url);
	        }
	      };
	
	      scope.emailCallback = function () {
	        todoItems.markCompleted('email_share');
	        $timeout(function () {
	          scope.goToPostShare();
	        }, 2000);
	      };
	
	      scope.captureEvent = function (event_name) {
	        gogoEvents.captureEvent(event_name, scope.eventTags());
	      };
	
	      scope.goTo = function (state) {
	        $state.go(state);
	      };
	
	      scope.goToPostShare = function () {
	        browser.redirectTo(scope.urls.post_share_url);
	      };
	
	      scope.openEmailImporter = function () {
	        var emailImporterBtn = element.find('.js-emailImporter');
	
	        $timeout(function () {
	          emailImporterBtn.click();
	        });
	      };
	
	      browser.onLoad(function () {
	        // TODO EVENTS: id=aith8 fixtype=infra subsystem=share category-new=TBD name=share_wizard_start . review
	        scope.captureEvent('share_wizard_start');
	      });
	    }
	  };
	}

/***/ },
/* 129 */
/***/ function(module, exports) {

	module.exports = "<div ui-view></div>\n";

/***/ },
/* 130 */
/***/ function(module, exports) {

	'use strict';
	
	backToTopDirective.$inject = ["browser"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = backToTopDirective;
	/*@ngInject*/
	
	function backToTopDirective(browser) {
	  return {
	    restrict: 'A',
	    scope: {},
	    replace: true,
	    template: '<a ng-transclude href="" ng-click="scrollToTop()"></a>',
	    transclude: true,
	    link: function link(scope) {
	      scope.scrollToTop = function () {
	        browser.scrollToTop();
	      };
	    }
	  };
	}

/***/ },
/* 131 */
/***/ function(module, exports) {

	"use strict";
	
	campaignOwnerService.$inject = ["$http", "gon"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = campaignOwnerService;
	/*@ngInject*/
	
	function campaignOwnerService($http, gon) {
	  var campaignOwner = gon.campaign_owner;
	
	  campaignOwner.sendMessage = function (message, grecaptcha_response) {
	    return $http.post(gon.urls.contact_owner, { comment: { text: message }, grecaptcha: grecaptcha_response });
	  };
	
	  return campaignOwner;
	}

/***/ },
/* 132 */
/***/ function(module, exports) {

	'use strict';
	
	fbAutopostService.$inject = ["$http", "gon", "gogoEvents"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = fbAutopostService;
	/*@ngInject*/
	
	function fbAutopostService($http, gon, gogoEvents) {
	  var automaticFbPostUrl = gon.urls.automatic_facebook_post_url;
	
	  function updateServiceFromAutopostJson(autopostJson) {
	    service.postingActive = autopostJson.posting_active;
	    service.frequency = autopostJson.frequency;
	    service.nextPostDate = autopostJson.next_post_date;
	    service.automatedMessage = autopostJson.automated_message;
	  }
	
	  function setPostingActive(postingActiveValue) {
	    makeSnapshot();
	    service.snapshot.postingActive = postingActiveValue;
	    return saveSnapshot();
	  }
	
	  function makeSnapshot() {
	    service.snapshot = _.pick(service, 'postingActive', 'frequency', 'automatedMessage');
	  }
	
	  function saveSnapshot() {
	    return $http.put(automaticFbPostUrl, {
	      automatic_facebook_post: {
	        posting_active: service.snapshot.postingActive,
	        frequency: service.snapshot.frequency,
	        automated_message: service.snapshot.automatedMessage
	      }
	    }).then(function (response) {
	      updateServiceFromAutopostJson(response.data || {});
	    });
	  }
	
	  var service = {
	    makeSnapshot: makeSnapshot,
	    saveSnapshot: saveSnapshot,
	    setPostingActive: setPostingActive
	  };
	  updateServiceFromAutopostJson(gon.fb_autopost || {});
	  makeSnapshot();
	  return service;
	}

/***/ },
/* 133 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	generosityFbShareDirective.$inject = ["$http", "i18n", "fb", "gon"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = generosityFbShareDirective;
	/*@ngInject*/
	
	function generosityFbShareDirective($http, i18n, fb, gon) {
	  return {
	    template: __webpack_require__(134),
	    scope: {},
	    transclude: true,
	    link: function link(scope, element, attrs, controller, transclude) {
	      scope.i18n = i18n;
	      scope.fb = fb;
	      fb.fetchShareCount();
	
	      scope.shareFacebook = function () {
	        // TODO EVENTS: id=di4ei fixtype=fb-share vars=account_id category-new=TBD subsystem=share . review
	        if (_.isUndefined(gon.current_account)) {
	          fb.share(gon.urls.fundraiser_url, {});
	        } else {
	          var currentAccount = gon.current_account;
	          fb.share(gon.urls.fundraiser_url, { account_id: currentAccount.account_id }).then(function () {
	            var isFundraiserOwner = currentAccount.account_id === gon.campaign_owner.id;
	            if (isFundraiserOwner && gon.urls.schedule_next_post_date_url) {
	              $http.put(gon.urls.schedule_next_post_date_url);
	            }
	          });
	        }
	      };
	    }
	  };
	}

/***/ },
/* 134 */
/***/ function(module, exports) {

	module.exports = "<div ng-click=\"shareFacebook()\">\n  <svg-icon icon=\"icon-icon-facebook\"></svg-icon>\n  <span>{{::i18n.t('facebook')}}</span>\n  <span class=\"shareThisStory-button-shareCount\" ng-if=\"fb.shareCount !== null\">{{(fb.shareCount || 0) | abbrevNumFmt}}</span>\n</div>\n";

/***/ },
/* 135 */
/***/ function(module, exports) {

	"use strict";
	
	pcCampaignService.$inject = ["$http", "$sce", "i18n", "gon"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = pcCampaignService;
	/*@ngInject*/
	
	function pcCampaignService($http, $sce, i18n, gon) {
	  var campaignJson;
	  var donationsPage = 2;
	  var changeCallbacks = [];
	  var service = {
	    setCampaignJson: function setCampaignJson(newCampaignJson) {
	      campaignJson = newCampaignJson;
	      donationsPage = 2;
	      _.each(campaignJson.updates, function (update) {
	        update.body_html = $sce.trustAsHtml(update.body_html);
	      });
	      for (var i = 0; i < changeCallbacks.length; ++i) {
	        changeCallbacks[i]();
	      }
	    },
	    onChange: function onChange(func) {
	      changeCallbacks.push(func);
	    },
	    descriptionHtml: function descriptionHtml() {
	      return campaignJson.description_html;
	    },
	    updates: function updates() {
	      return campaignJson.updates;
	    },
	    donations: function donations() {
	      return campaignJson.donations;
	    },
	    donationsCount: function donationsCount() {
	      return campaignJson.donations_count;
	    },
	    hasDeadline: function hasDeadline() {
	      return campaignJson.has_deadline;
	    },
	    json: function json() {
	      return campaignJson;
	    },
	    fetchDonations: function fetchDonations() {
	      return $http.get(gon.urls.fundraiser_json, {
	        params: {
	          locale: i18n.locale,
	          donations_page: donationsPage++
	        }
	      }).then(function (response) {
	        campaignJson.donations = campaignJson.donations.concat(response.data.fundraiser.donations);
	        campaignJson.donationsCount = response.data.fundraiser.donations_count;
	      });
	    },
	    deleteUpdate: function deleteUpdate(update) {
	      return $http.delete(update.delete_path).then(function (response) {
	        service.setCampaignJson(response.data.fundraiser);
	      });
	    },
	    refresh: function refresh() {
	      return $http.get(gon.urls.fundraiser_json, { params: { locale: i18n.locale } }).then(function (response) {
	        service.setCampaignJson(response.data.fundraiser);
	      });
	    }
	  };
	
	  return service;
	}

/***/ },
/* 136 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	pcContactDirective.$inject = ["pcCampaign", "i18n", "campaignOwner", "flash", "$sce", "gon", "$modal", "vcRecaptchaService"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = pcContactDirective;
	/*@ngInject*/
	
	function pcContactDirective(pcCampaign, i18n, campaignOwner, flash, $sce, gon, $modal, vcRecaptchaService) {
	  return {
	    restrict: 'A',
	    template: __webpack_require__(137),
	    scope: {
	      owner: "@pcContactOwner"
	    },
	    link: function link(scope) {
	      var isLoggedIn = !!gon.current_account;
	      var recaptchaId = null;
	      var recaptchaSuccess = false;
	
	      scope.i18n = i18n;
	      scope.message = { text: '' };
	      scope.loginPath = gon.urls.login_url;
	      scope.$sce = $sce;
	      scope.grecaptchaSiteKey = gon.grecaptcha_site_key;
	
	      var contactOwnerModal = null;
	      scope.contactOwner = function () {
	        if (isLoggedIn) {
	          contactOwnerModal = $modal({
	            template: __webpack_require__(138),
	            scope: scope
	          });
	        } else {
	          $modal({
	            template: __webpack_require__(139),
	            scope: scope
	          });
	        }
	      };
	
	      scope.onRecaptchaReady = function (widgetId) {
	        recaptchaId = widgetId;
	      };
	
	      scope.onRecaptchaSuccess = function () {
	        recaptchaSuccess = true;
	      };
	
	      scope.isButtonDisabled = function (text) {
	        return !(text.length > 0 && recaptchaId !== null && recaptchaSuccess);
	      };
	
	      scope.sendMessage = function (message) {
	        var reCaptchaResponse = vcRecaptchaService.getResponse(recaptchaId);
	        campaignOwner.sendMessage(message, reCaptchaResponse).then(function () {
	          contactOwnerModal.hide();
	          scope.message.text = '';
	          flash.addMessage('notice', i18n.t("generosity.your_message_was_sent", { x: campaignOwner.name }));
	        }, function () {
	          contactOwnerModal.hide();
	          flash.addMessage('error', i18n.t('something_went_wrong'));
	        });
	      };
	    }
	  };
	}

/***/ },
/* 137 */
/***/ function(module, exports) {

	module.exports = "<a href=\"\" class=\"i-aqua-link\" ng-click=\"contactOwner()\">\n  <span class=\"pc-text\">{{::i18n.t(\"contact\")}}</span>\n</a>\n";

/***/ },
/* 138 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal\">\n  <div class=\"modal-dialog lifeModal-dialog\">\n    <div class=\"modal-content lifeModal-content lifeModal-content--shady\">\n      <a class=\"lifeModal-close\" ng-click=\"$hide()\"><svg-icon icon=\"icon-icon-close\"></svg-icon></a>\n      <div class=\"lifeModal-container\">\n        <div class=\"lifeModal-headerText\">{{::i18n.t(\"contact_campaign_owner\", {campaign_owner: owner}) }}</div>\n        <div class=\"lifeModal-bodyText\"\n             ng-bind-html=\"$sce.trustAsHtml(i18n.t('generosity.contact_modal_description', {owner_name: owner}))\"></div>\n        <textarea class=\"i-text-area contactModal-textarea\" ng-model=\"message.text\" maxlength=\"500\"></textarea>\n        <div class=\"contactModal-footer\">\n          <div class=\"contactModal-charCounter\">{{message.text | charCounter:500}}</div>\n          <div class=\"lifeModal-buttons contactModal-buttons\">\n            <div class=\"g-recaptcha\" vc-recaptcha key=\"grecaptchaSiteKey\"\n                 on-create=\"setReCaptchaReady(widgetId)\"\n                 on-success=\"setReCaptchaResponse()\"></div>\n            <a class=\"lifeModal-button pc-cta\" ng-disabled=\"isButtonDisabled(message.text)\"\n               ng-click=\"sendMessage(message.text)\">{{::i18n.t(\"send_message\")}}</a>\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 139 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal\">\n  <div class=\"modal-dialog lifeModal-dialog\">\n    <div class=\"modal-content lifeModal-content lifeModal-content--shady\">\n      <a class=\"lifeModal-close\" ng-click=\"$hide()\"><svg-icon icon=\"icon-icon-close\"></svg-icon></a>\n      <div class=\"lifeModal-container\">\n        <div class=\"lifeModal-headerText\">{{::i18n.t(\"login_required\") }}</div>\n        <div class=\"lifeModal-buttons\">\n          <a href=\"\" class=\"lifeModal-button lifeModal-button--cancel\" ng-click=\"$hide()\">{{::i18n.t(\"cancel\")}}</a>\n          <a ng-href=\"{{ loginPath }}\" class=\"lifeModal-button pc-cta\">{{::i18n.t(\"generosity.proceed_to_login\") }}</a>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 140 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";
	
	pcFbShareDirective.$inject = ["$http", "i18n", "fb", "gon"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = pcFbShareDirective;
	/*@ngInject*/
	
	function pcFbShareDirective($http, i18n, fb, gon) {
	  return {
	    template: __webpack_require__(141),
	    scope: {},
	    transclude: true,
	    link: function link(scope, element, attrs, controller, transclude) {
	      transclude(function (clone) {
	        scope.buttonText = clone.filter(".pc-social-text").text();
	      });
	
	      scope.i18n = i18n;
	      scope.fb = fb;
	      fb.fetchShareCount();
	
	      scope.shareFacebook = function () {
	        var options = gon.current_account ? { account_id: gon.current_account.account_id } : {};
	        // TODO EVENTS: id=we8th fixtype=fb-share subsystem=share . review
	        fb.share(gon.urls.fundraiser_url, options).then(function () {
	          var account = gon.current_account || {};
	          var isFundraiserOwner = account.account_id === gon.campaign_owner.id;
	          if (isFundraiserOwner && gon.urls.schedule_next_post_date_url) {
	            $http.put(gon.urls.schedule_next_post_date_url);
	          }
	        });
	      };
	    }
	  };
	}

/***/ },
/* 141 */
/***/ function(module, exports) {

	module.exports = "<div ng-click=\"shareFacebook()\">\n  <span class=\"pc-social-text\">{{buttonText}}</span>\n  <span class=\"pc-social-number\" ng-if=\"fb.shareCount !== null\">{{fb.shareCount | abbrevNumFmt}}</span>\n</div>\n";

/***/ },
/* 142 */
/***/ function(module, exports, __webpack_require__) {

	"use strict";
	
	publishButtonDirective.$inject = ["browser", "$http", "$timeout", "$modal", "i18n", "flash"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = publishButtonDirective;
	/*@ngInject*/
	
	function publishButtonDirective(browser, $http, $timeout, $modal, i18n, flash) {
	  return {
	    restrict: 'A',
	    scope: {
	      actionHref: "@publishButtonActionHref",
	      finalHref: "@publishButtonFinalHref",
	      genHost: "=publishButtonGenHost"
	    },
	    template: '<a ng-transclude ng-href="" ng-click="publish()"></a>',
	    transclude: true,
	    replace: true,
	    link: function link(scope) {
	      scope.i18n = i18n;
	
	      scope.publish = function () {
	        $http.put(scope.actionHref).then(function () {
	          if (scope.finalHref) {
	            var modalTemplate;
	            if (scope.genhost) {
	              modalTemplate = __webpack_require__(143);
	            } else {
	              modalTemplate = __webpack_require__(144);
	            }
	
	            $modal({ scope: scope, template: modalTemplate });
	
	            $timeout(function () {
	              browser.redirectTo(scope.finalHref);
	            }, 2000);
	          } else {
	            browser.refreshPage();
	          }
	        }, function (response) {
	          if (response.data && response.data.error) {
	            var errorStruct = response.data.error;
	            if (errorStruct.key && errorStruct.url) {
	              var contactUsLink = '<a href="' + errorStruct.url + '"><strong>' + i18n.t('contact_us').toLowerCase() + "</strong></a>";
	              var message = i18n.t(errorStruct.key, { contact_us_as_link: contactUsLink });
	              flash.addMessage('error', message, { html: true });
	            }
	          }
	        });
	      };
	    }
	  };
	}

/***/ },
/* 143 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal pc-live-modal\">\n  <div class=\"modal-dialog\">\n    <svg-icon icon=\"icon-icon-checkmark\"></svg-icon>\n    <div class=\"pc-live-modal-text\">{{::i18n.t('generosity.your_fundraiser_is_live_bang')}}</div>\n  </div>\n</div>\n";

/***/ },
/* 144 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal i-live-modal\">\n  <div class=\"modal-dialog\">\n    <div class=\"i-live-modal-airplane\"></div>\n    <div class=\"i-live-modal-text\">{{::i18n.t('simple_preview.your_campaign_is_live')}}</div>\n  </div>\n</div>\n";

/***/ },
/* 145 */
/***/ function(module, exports) {

	'use strict';
	
	todoItemsService.$inject = ["$http", "gon", "i18n"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = todoItemsService;
	/*@ngInject*/
	
	function todoItemsService($http, gon, i18n) {
	  var service = {};
	  var todoItems = {};
	
	  var notYetCompletedText = {
	    facebook_share: i18n.t('generosity.fundraiser_dashboard.not_posted_on_facebook'),
	    twitter_share: i18n.t('generosity.fundraiser_dashboard.not_posted_on_twitter'),
	    email_share: i18n.t('generosity.fundraiser_dashboard.not_sent_email'),
	    promotion_program: null,
	    offline_fundraiser: null
	  };
	
	  var urls = {
	    facebook_share: gon.urls.todo_items_facebook_share_url,
	    twitter_share: gon.urls.todo_items_twitter_share_url,
	    email_share: gon.urls.todo_items_email_share_url,
	    promotion_program: gon.urls.todo_items_promotion_program_url,
	    offline_fundraiser: gon.urls.todo_items_offline_fundraiser_url
	  };
	
	  var storeTodoItem = function storeTodoItem(itemName, todoData) {
	    if (_.isUndefined(todoItems[itemName])) {
	      todoItems[itemName] = {};
	    }
	
	    if (_.isUndefined(todoData)) {
	      todoItems[itemName].completedRecently = false;
	      todoItems[itemName].lastCompletedText = notYetCompletedText[itemName];
	    } else {
	      todoItems[itemName].completedRecently = todoData.completed_recently;
	      todoItems[itemName].lastCompletedText = todoData.last_completed_text;
	    }
	  };
	
	  service.markCompleted = function (itemName) {
	    return $http.put(urls[itemName], {}).then(function (response) {
	      storeTodoItem(itemName, response.data[itemName]);
	    });
	  };
	
	  service.get = function () {
	    return todoItems;
	  };
	
	  _.each(['facebook_share', 'twitter_share', 'email_share', 'promotion_program', 'offline_fundraiser'], function (itemName) {
	    var gonData = gon.fundraiser.todo_items || {};
	    var todoData = gonData[itemName];
	    storeTodoItem(itemName, todoData);
	  });
	
	  return service;
	}

/***/ },
/* 146 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	generosityDashboardFundsDisbursement.$inject = ["i18n", "generosityFundsDisbursement", "$modal"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = generosityDashboardFundsDisbursement;
	/* @ngInject */
	function generosityDashboardFundsDisbursement(i18n, generosityFundsDisbursement, $modal) {
	  return {
	    scope: {},
	    restrict: 'A',
	    template: __webpack_require__(147),
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.disbursementService = generosityFundsDisbursement.load();
	
	      scope.showHistory = function () {
	        $modal({
	          template: __webpack_require__(148),
	          scope: scope
	        });
	      };
	    }
	  };
	}

/***/ },
/* 147 */
/***/ function(module, exports) {

	module.exports = "<div class=\"generosityFunds-title pc-dashboard-section-title\">{{::i18n.t('generosity.dashboard.funds.funds_disbursement')}}</div>\n<div ng-if=\"disbursementService.isLoaded\" class=\"generosityFunds-disbursements\">\n  <div class=\"disbursements-nextDisbursement\" ng-if=\"disbursementService.data.nextDisbursement.amount > 0\">\n    <div class=\"nextDisbursement-date\">{{::i18n.t('generosity.dashboard.funds.next_disbursement')}} ({{disbursementService.data.nextDisbursement.date | weekOf}})</div>\n    <div class=\"nextDisbursement-amount\">{{disbursementService.data.nextDisbursement.amount | iggCurrency : disbursementService.data.currencyIsoNum : 'noIso,cents'}}</div>\n  </div>\n\n  <div class=\"disbursements-alreadyDisbursed\">\n    <div class=\"alreadyDisbursed-label\">{{::i18n.t('generosity.dashboard.funds.already_disbursed')}}</div>\n    <a href=\"\" class=\"alreadyDisbursed-historyLink\" ng-if=\"disbursementService.data.history.length > 0\" ng-click=\"showHistory()\">{{::i18n.t('generosity.dashboard.funds.view_disbursements_history')}}</a>\n    <div class=\"alreadyDisbursed-amount\">{{disbursementService.data.alreadyDisbursed | iggCurrency : disbursementService.data.currencyIsoNum : 'noIso,cents'}}</div>\n  </div>\n</div>\n";

/***/ },
/* 148 */
/***/ function(module, exports) {

	module.exports = "<div class=\"modal\">\n  <div class=\"modal-dialog lifeModal-dialog lifeModal-dialog--wider\">\n    <div class=\"modal-content lifeModal-content lifeModal-content--shady\">\n      <a class=\"lifeModal-close\" ng-click=\"$hide()\"><svg-icon icon=\"icon-icon-close\"></svg-icon></a>\n      <div class=\"lifeModal-container\">\n        <div class=\"lifeModal-headerText\">{{::i18n.t('generosity.dashboard.funds.disbursements_history')}}</div>\n        <div class=\"disburseHistory\">\n          <div class=\"disburseHistory-header hidden-xs\">\n            <div class=\"disburseHistory-date\">{{::i18n.t('generosity.dashboard.funds.date_disbursed')}}</div>\n            <div class=\"disburseHistory-payment hidden-xs\">{{::i18n.t('generosity.dashboard.funds.payment_method')}}</div>\n            <div class=\"disburseHistory-amount\">{{::i18n.t('generosity.dashboard.funds.amount')}}</div>\n          </div>\n          <div class=\"disburseHistory-item\" ng-repeat=\"disbursement in disbursementService.data.history\">\n            <div class=\"disburseHistory-date\">{{::disbursement.date | date: 'mediumDate'}}</div>\n            <div class=\"disburseHistory-payment hidden-xs\">{{::disbursement.paymentMethod}}</div>\n            <div class=\"disburseHistory-amount\">{{::disbursement.amount | iggCurrency:disbursementService.data.currencyIsoNum:'noIso,cents'}}</div>\n          </div>\n        </div>\n        <div class=\"disburseHistory-disclaimer\">{{::i18n.t('generosity.dashboard.funds.disclaimer')}}</div>\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 149 */
/***/ function(module, exports) {

	"use strict";
	
	generosityFundsDisbursement.$inject = ["$http", "gon", "camelCaser"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = generosityFundsDisbursement;
	/*@ngInject*/
	
	function generosityFundsDisbursement($http, gon, camelCaser) {
	  var service = {
	    isLoaded: false
	  };
	
	  service.load = function () {
	    $http.get(gon.urls.disbursement_info).then(function (response) {
	      service.data = camelCaser.camelCase(response.data.disbursement_info);
	      service.isLoaded = true;
	    });
	
	    return this;
	  };
	
	  return service;
	}

/***/ },
/* 150 */
/***/ function(module, exports) {

	"use strict";
	
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = camelCaser;
	/*@ngInject*/
	
	function camelCaser() {
	  // This service camelCases the keys in a data-structure.
	  //
	  // CAUTION: Please look at the tests and note that it does not go
	  // much deeper than 1 level. You will need to add tests for your
	  // use-case.
	
	  var service = {};
	  service.camelCase = function (data) {
	    return camelizeSubObjectKeys(camelizeObjectKeys(data));
	  };
	
	  return service;
	
	  function camelizeObjectKeys(data) {
	    return _.mapKeys(data, function (__, key) {
	      return _.camelCase(key);
	    });
	  }
	
	  function camelizeElementKeys(collection) {
	    return _.map(collection, function (element) {
	      return camelizeObjectKeys(element);
	    });
	  }
	
	  function camelizeSubObjectKeys(data) {
	    return _.mapValues(data, function (value) {
	      if (_.isArray(value)) {
	        return camelizeElementKeys(value);
	      } else if (_.isObject(value)) {
	        return camelizeObjectKeys(value);
	      } else {
	        return value;
	      }
	    });
	  }
	}

/***/ },
/* 151 */
/***/ function(module, exports) {

	'use strict';
	
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = RefundDisplayFactory;
	/* @ngInject */
	function RefundDisplayFactory() {
	  function RefundDisplay(contribution) {
	    this.contribution = contribution;
	  }
	
	  RefundDisplay.prototype.displayAsRefunded = function () {
	    return _.include(['refunded', 'chargeback_lost', 'off_platform_refunded'], this.contribution.status);
	  };
	
	  return RefundDisplay;
	}

/***/ },
/* 152 */
/***/ function(module, exports) {

	'use strict';
	
	contributionsApi.$inject = ["$http", "$interpolate", "$httpParamSerializer"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = contributionsApi;
	/* @ngInject */
	function contributionsApi($http, $interpolate, $httpParamSerializer) {
	  var urls = { index: null, indexCsv: null, show: null };
	
	  function validInteger(id) {
	    return !angular.isUndefined(id) && typeof id === 'number' && id > 0;
	  }
	
	  function requireUrl(key) {
	    if (!urls[key]) {
	      throw new Error(key + ' url is not defined');
	    }
	  }
	
	  return {
	    setUrls: function setUrls(newUrls) {
	      urls = newUrls;
	    },
	
	    getUrls: function getUrls() {
	      return urls;
	    },
	
	    getContributions: function getContributions(params) {
	      requireUrl('index');
	
	      params = params || {};
	
	      if (angular.isUndefined(params.page)) {
	        params.page = 1;
	      }
	
	      return $http.get(urls.index, { params: params });
	    },
	
	    getContribution: function getContribution(id) {
	      requireUrl('show');
	
	      var numericId = parseInt(id);
	      if (validInteger(numericId)) {
	        var url = $interpolate(urls.show)({ id: numericId });
	        return $http.get(url);
	      } else {
	        throw new Error('Invalid Pledge ID');
	      }
	    },
	
	    refundContribution: function refundContribution(id) {
	      requireUrl('refund');
	
	      var numericId = parseInt(id);
	      if (validInteger(numericId)) {
	        var url = $interpolate(urls.refund)({ id: numericId });
	        return $http.post(url);
	      } else {
	        throw new Error('Invalid Pledge ID');
	      }
	    },
	
	    markRefunded: function markRefunded(id) {
	      requireUrl('markRefunded');
	      var numericId = parseInt(id);
	      if (validInteger(numericId)) {
	        var url = $interpolate(urls.markRefunded)({ id: numericId });
	        return $http.post(url);
	      } else {
	        throw new Error('Invalid Pledge ID');
	      }
	    },
	
	    exportCsv: function exportCsv(params) {
	      // angular doesn't transform POST params using form-urlencoded properly, so transformation is needed
	      return $http({
	        method: 'POST',
	        url: urls.export,
	        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
	        data: $httpParamSerializer(params)
	      });
	    }
	  };
	}

/***/ },
/* 153 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	orderState.$inject = ["i18n"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = orderState;
	/* @ngInject */
	function orderState(i18n) {
	  var ORDER_STATES = ['pending', 'awaiting_confirmation', 'confirmed', 'in_fulfillment', 'fulfilled', 'refunded'];
	
	  return {
	    restrict: 'A',
	    replace: true,
	    scope: {
	      contribution: "="
	    },
	    template: __webpack_require__(154),
	    link: function link(scope, element) {
	      scope.i18n = i18n;
	
	      scope.orderStatusLabel = function (contribution) {
	        if (contribution.status === 'chargeback_on_hold') {
	          return i18n.t('contribution_details.chargeback_on_hold');
	        } else if (contribution.status === 'off_platform_refunded') {
	          return i18n.t('contribution_details.off_platform_refunded');
	        } else if (_.include(ORDER_STATES, contribution.order.state)) {
	          return i18n.t('contribution_details.order_states.' + contribution.order.state);
	        } else {
	          return "";
	        }
	      };
	    }
	  };
	}

/***/ },
/* 154 */
/***/ function(module, exports) {

	module.exports = "<div ng-bind=\"orderStatusLabel(contribution)\"></div>\n";

/***/ },
/* 155 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	paymentMethod.$inject = ["i18n"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = paymentMethod;
	/* @ngInject */
	
	function paymentMethod(i18n) {
	  return {
	    restrict: 'A',
	    replace: true,
	    scope: {
	      contribution: '='
	    },
	    template: __webpack_require__(156),
	    link: function link(scope) {
	      scope.i18n = i18n;
	    }
	  };
	}

/***/ },
/* 156 */
/***/ function(module, exports) {

	module.exports = "<div ng-bind=\"::i18n.t('contribution_details.payment_methods.' + contribution.payment_method)\"></div>\n\n";

/***/ },
/* 157 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	lineItems.$inject = ["i18n", "RefundDisplayFactory"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = lineItems;
	/* @ngInject */
	function lineItems(i18n, RefundDisplayFactory) {
	  return {
	    restrict: 'A',
	    replace: false,
	    scope: {
	      contribution: "="
	    },
	    template: __webpack_require__(158),
	    link: function link(scope) {
	      scope.i18n = i18n;
	      scope.lineItemLabel = function (lineItem) {
	        if (lineItem.key === 'perk') {
	          return scope.contribution.perk.label;
	        } else if (lineItem.key === 'contribution') {
	          return i18n.t('command_center.donation');
	        } else if (lineItem.key === 'additional') {
	          return i18n.t('contribution_flow.additional_gift');
	        } else if (lineItem.key === 'shipping') {
	          return i18n.t('contribution_flow.shipping');
	        }
	      };
	
	      scope.displayAsRefunded = function () {
	        var refundDisplay = new RefundDisplayFactory(scope.contribution);
	        return refundDisplay.displayAsRefunded();
	      };
	    }
	  };
	}

/***/ },
/* 158 */
/***/ function(module, exports) {

	module.exports = "<div class=\"contributionItems\">\n  <div ng-repeat=\"lineItem in contribution.line_items\" class=\"contributionItems-item\">\n    <div class=\"contributionItems-name\">{{lineItemLabel(lineItem)}}</div>\n    <div class=\"contributionItems-amount\" ng-if=\"lineItem.amount\">{{lineItem.amount | iggCurrency:contribution.currency.iso_num}}</div>\n    <div class=\"contributionItems-amount contributionItems-amount--empty\" ng-if=\"!lineItem.amount\">&ndash;</div>\n  </div>\n</div>\n\n<div class=\"contributionItems-separator\"></div>\n\n<div class=\"contributionItems\">\n  <div ng-if=\"displayAsRefunded()\" class=\"contributionItems-item\">\n    <div class=\"contributionItems-name\">\n      <span class=\"i-annotation-pill i-pill-european-butter\">{{i18n.t('contribution_details.refunded')}}</span>\n    </div>\n    <div class=\"contributionItems-amount contributionItems-amount--linethrough\">\n      {{contribution.amount | iggCurrency:contribution.currency.iso_num}}\n    </div>\n  </div>\n\n  <div ng-if=\"contribution.status === 'on_hold' || contribution.status === 'chargeback_on_hold'\" class=\"contributionItems-item\">\n    <div class=\"contributionItems-name\">\n      <span class=\"i-annotation-pill i-pill-pending\">{{i18n.t('contribution_details.on_hold')}}</span>\n    </div>\n  </div>\n\n  <div class=\"contributionItems-item\" ng-class=\"(contribution.status === 'on_hold' || contribution.status === 'chargeback_on_hold') ? '' : 'contributionItems-item--bold'\">\n    <div class=\"contributionItems-name\">{{i18n.t('total')}}</div>\n    <div class=\"contributionItems-amount\">\n      {{(displayAsRefunded() ? 0 : contribution.amount) | iggCurrency:contribution.currency.iso_num}}\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 159 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	
	exports.default = function (angular) {
	  angular.module('discovery', ['utils']).directive('ngTranscludeReplace', _ngTranscludeReplaceDirective2.default).directive('bindHtmlCompile', _bindHtmlCompileDirective2.default).directive('discoveryTab', _discoveryTabDirective2.default).directive('discoveryTabs', _discoveryTabsDirective2.default).directive('carousel', _carouselDirective2.default).directive('projectCardDiscoveryWww', _projectCardDiscoveryWwwDirective2.default).directive('projectCardDiscoveryPlaceholder', _projectCardDiscoveryPlaceholderDirective2.default);
	};
	
	var _carouselDirective = __webpack_require__(160);
	
	var _carouselDirective2 = _interopRequireDefault(_carouselDirective);
	
	var _discoveryTabDirective = __webpack_require__(162);
	
	var _discoveryTabDirective2 = _interopRequireDefault(_discoveryTabDirective);
	
	var _discoveryTabsDirective = __webpack_require__(164);
	
	var _discoveryTabsDirective2 = _interopRequireDefault(_discoveryTabsDirective);
	
	var _bindHtmlCompileDirective = __webpack_require__(166);
	
	var _bindHtmlCompileDirective2 = _interopRequireDefault(_bindHtmlCompileDirective);
	
	var _projectCardDiscoveryWwwDirective = __webpack_require__(167);
	
	var _projectCardDiscoveryWwwDirective2 = _interopRequireDefault(_projectCardDiscoveryWwwDirective);
	
	var _projectCardDiscoveryPlaceholderDirective = __webpack_require__(169);
	
	var _projectCardDiscoveryPlaceholderDirective2 = _interopRequireDefault(_projectCardDiscoveryPlaceholderDirective);
	
	var _ngTranscludeReplaceDirective = __webpack_require__(171);
	
	var _ngTranscludeReplaceDirective2 = _interopRequireDefault(_ngTranscludeReplaceDirective);
	
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/***/ },
/* 160 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	carousel.$inject = ["i18n", "$sce", "$filter", "$timeout", "browser"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = carousel;
	/*@ngInject*/
	function carousel(i18n, $sce, $filter, $timeout, browser) {
	  return {
	    template: __webpack_require__(161),
	    scope: {
	      window: '=',
	      objects: '=',
	      visible: '@',
	      name: '@'
	    },
	    transclude: true,
	    restrict: 'E',
	    link: function link(scope, element, attrs, ctrl, transclude) {
	      scope.showArrows = false;
	
	      scope.$watch('objects', function () {
	        if (!scope.objects) return;
	        var visible = scope.visible || 4;
	        scope.window = scope.objects.slice(0, visible);
	        scope.showArrows = scope.objects.length > visible;
	      });
	
	      scope.rotateCarousel = function (increment) {
	        function arrayRotate(array, n) {
	          // take n from the end, put it on the front
	          return array.slice(n, array.length).concat(array.slice(0, n));
	        }
	        this.objects = arrayRotate(this.objects, increment);
	      };
	    }
	  };
	}

/***/ },
/* 161 */
/***/ function(module, exports) {

	module.exports = "<!-- TODO EVENTS: id=ooko5 fixtype=ga-event-dir category=carousel subsystem=homepage action=arrow_left action-new=Arrow.Left label=dynamic name-new=TBD subsystem=homepage trigger=click dom=label . -->\n<label class=\"i-carousel-arrow left black\"\n  ng-click=\"rotateCarousel(-3)\" ng-show=\"showArrows\"\n  ga-event-on=\"click\" ga-event-category=\"carousel\" ga-event-action=\"arrow_left\" ga-event-label=\"{{name}}\">\n  <svg><use xlink:href=\"#left-chevron\"></use></svg>\n</label>\n<ng-transclude-replace></ng-transclude-replace>\n<!-- TODO EVENTS: id=ua3ve fixtype=ga-event-dir category=carousel subsystem=homepage action=arrow_right action-new=Arrow.Right label=dynamic name-new=TBD subsystem=homepage trigger=click dom=label . -->\n<label class=\"i-carousel-arrow right black\"\n  ng-click=\"rotateCarousel(3)\" ng-show=\"showArrows\"\n  ga-event-on=\"click\" ga-event-category=\"carousel\" ga-event-action=\"arrow_right\" ga-event-label=\"{{name}}\">\n  <svg><use xlink:href=\"#right-chevron\"></use></svg>\n</label>\n";

/***/ },
/* 162 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	
	exports.default = function (i18n, $sce) {
	  return {
	    require: '^discoveryTabs',
	    transclude: true,
	    template: __webpack_require__(163),
	    scope: {
	      'discoveryKey': '@'
	    },
	    replace: true,
	    link: function link($scope, element, attrs, discoveryCtrl, transclude) {
	      $scope.discovery = discoveryCtrl;
	      $scope.discoveryKey = attrs.discoveryKey;
	      $scope.discovery.addTab($scope.discoveryKey);
	      $scope.$watch('discovery.selectedTabKey', function (key) {
	        $scope.selectedTabKey = key;
	      });
	      $scope.i18n = i18n;
	    }
	  };
	};

/***/ },
/* 163 */
/***/ function(module, exports) {

	module.exports = "<a ng-click=\"discovery.touchTab(discoveryKey)\" class=\"discoveryTab\" ng-class=\"{'discoveryTab--selected': selectedTabKey == discoveryKey}\">\n  <ng-transclude></ng-transclude>\n  <svg class=\"dropdownIcon\" ng-if=\"selectedTabKey == discoveryKey\"><use xlink:href=\"#down-caret\"></use></svg>\n</a>\n";

/***/ },
/* 164 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	discoveryTabs.$inject = ["$injector", "i18n", "browser", "gogoEvents", "$cookies", "ga"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = discoveryTabs;
	/*@ngInject*/
	function discoveryTabs($injector, i18n, browser, gogoEvents, $cookies, ga) {
	
	  function displayDiscoveryTabsContainer() {
	    var discoveryTabsContainer = document.getElementById("homeSection-discoveryTabContainer");
	    if (discoveryTabsContainer) {
	      discoveryTabsContainer.style.display = 'block';
	    }
	  }
	
	  return {
	    scope: {
	      discoveryProvider: '@',
	      trackName: '@',
	      showProgress: '@',
	      variantClass: '@'
	    },
	    template: __webpack_require__(165),
	    transclude: true,
	    controllerAs: 'discovery',
	    controller: function controller($scope) {
	      var self = this;
	      $scope.tabs = [];
	      $scope.discovery = self;
	      displayDiscoveryTabsContainer();
	
	      self.selectedTabKey = null;
	      self.selectedTabViewMoreLink = "";
	      self.switchingMode = false;
	      self.addTab = function (key) {
	        $scope.tabs.push(key);
	      };
	
	      $scope.trackProjectClick = function (projectScope) {
	        // TODO EVENTS: id=ieh8r subsystem=explore fixtype=ga+captureEvent name=discoveryCardClick name-new=TBD category=dynamic action=discoveryCard action-new=Discovery.Card label=dynamic vars=project_id+tab . merge ga+captureEvent to .track(), rename
	        ga('send', 'event', $scope.trackName, 'discoveryCard', projectScope.$index);
	        gogoEvents.captureEvent('discoveryCardClick', {
	          project_id: projectScope.campaign.id,
	          tab: self.selectedTabKey
	        });
	      };
	
	      $scope.projectPath = function (campaign) {
	        return campaign.url + '/' + $scope.selectedTabIggref;
	      };
	
	      $scope.$watchCollection('tabs', function () {
	        if ($scope.tabs.length === 0 || self.selectedTabKey) return;
	        var defaultTab = $cookies.get(selectedTabPersistenceKey()) || $scope.tabs[0];
	        self.selectedTabKey = defaultTab;
	      });
	
	      function selectedTabPersistenceKey() {
	        return $scope.trackName + ':selectedTabKey';
	      }
	
	      function switchTab(newKey) {
	        self.selectedTabKey = newKey;
	        $cookies.put(selectedTabPersistenceKey(), self.selectedTabKey);
	      }
	
	      self.touchTab = function (newKey) {
	        //if we are not on mobile, just change tabs
	        if (browser.isTabletPlus()) {
	          switchTab(newKey);
	        } else {
	          if (self.switchingMode) {
	            switchTab(newKey);
	            self.switchingMode = false;
	          } else {
	            self.switchingMode = true;
	          }
	        }
	
	        // TODO EVENTS: id=ahl9w subsystem=explore fixtype=ga+captureEvent name=discoveryTabClick category=discoveryTab action=dynamic label=dynamic vars=tab+category . move ga() to .track()
	        ga('send', 'event', 'discoveryTab', $scope.trackName, self.selectedTabKey);
	
	        gogoEvents.captureEvent('discoveryTabClick', {
	          tab: self.selectedTabKey,
	          category: $scope.trackName
	        });
	
	        // for `see-all' link
	        if (newKey[0].toUpperCase() == newKey[0]) {
	          self.selectedTabViewMoreLink = "/" + newKey.toLowerCase();
	        } else if (newKey == 'trending_near_you') {
	          self.selectedTabViewMoreLink = '#/browse/regional';
	        } else if (newKey == 'trending_near_project_region') {
	          self.selectedTabViewMoreLink = "?filter_city=" + gon.campaign.city.split(' ').join('+') + "&filter_country=CTRY" + gon.campaign.country_code_alpha_2;
	        } else {
	          self.selectedTabViewMoreLink = '';
	        }
	      };
	
	      self.discoveryTabsIggrefs = {
	        picks_for_you: 'hmjy',
	        trending_near_you: 'hmrg',
	        trending_near_project_region: 'hmpr',
	        trending_by_category: 'hmct',
	        Technology: 'hmtc',
	        Film: 'hmfm'
	      };
	
	      $scope.campaigns = [];
	      if (browser.isDesktopPlus()) {
	        $scope.visibleCampaignsCount = 4;
	      } else if (browser.isDesktop()) {
	        $scope.visibleCampaignsCount = 4;
	      } else if (browser.isTabletPlus()) {
	        $scope.visibleCampaignsCount = 3;
	      } else if (browser.isMobilePortrait()) {
	        $scope.visibleCampaignsCount = 6;
	      } else {
	        $scope.visibleCampaignsCount = 2;
	      }
	
	      $scope.$watch(function () {
	        return self.selectedTabKey;
	      }, function () {
	        if (!self.selectedTabKey) return;
	        self.selectedTabKey = self.selectedTabKey;
	        self.campaignProvider.getCampaigns(self.selectedTabKey, {
	          indemand: false
	        }).then(function (campaigns) {
	          $scope.campaigns = campaigns;
	        });
	        $scope.selectedTabIggref = self.discoveryTabsIggrefs[self.selectedTabKey] || 'hmoc';
	        $scope.selectedTabKey = self.selectedTabKey;
	      });
	
	      self.campaignProvider = $injector.get($scope.discoveryProvider);
	    }
	  };
	}

/***/ },
/* 165 */
/***/ function(module, exports) {

	module.exports = "<div class=\"container container--mobileFullWidth\">\n  <div ng-class=\"['discoveryTabs', variantClass, discovery.switchingMode ? 'discoveryTabs--switchingMode' : null]\">\n    <ng-transclude-replace></ng-transclude-replace>\n  </div>\n</div>\n<carousel objects=\"campaigns\" window=\"visibleCampaigns\" visible=\"{{visibleCampaignsCount}}\" name=\"discoveryTabs\">\n<div class=\"container\">\n  <ul class=\"row\">\n    <li class=\"discoveryProject\" ng-repeat=\"campaign in visibleCampaigns\" ng-animate=\"'animate'\">\n      <div>\n        <div class=\"project-card-with-friend-list\">\n          <div project-card-discovery-www campaign=\"campaign\" on-track=\"trackProjectClick(this)\" project-path=\"projectPath(campaign)\" index=\"rowIndex * campaignRow.length + $index\" class=\"i-project-card\"></div>\n          <div fb-friends-footer campaign=\"campaign\"></div>\n        </div>\n      </div>\n    </li>\n  </ul>\n</div>\n</carousel>\n";

/***/ },
/* 166 */
/***/ function(module, exports) {

	'use strict';
	
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	
	exports.default = function ($compile) {
	  return {
	    restrict: 'A',
	    link: function link($scope, element, attrs) {
	      $scope.$watch(attrs.bindHtmlCompile, function (value) {
	        element.html(value);
	        $compile(element.contents())($scope);
	      });
	    }
	  };
	};

/***/ },
/* 167 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	projectCardDiscoveryWwww.$inject = ["i18n", "projectCard", "$timeout", "$http", "browser", "gogoEvents", "ga", "$window"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = projectCardDiscoveryWwww;
	/*@ngInject*/
	function projectCardDiscoveryWwww(i18n, projectCard, $timeout, $http, browser, gogoEvents, ga, $window) {
	  return {
	    template: __webpack_require__(168),
	    scope: {
	      index: '=index',
	      campaign: '=campaign',
	      iggref: '=iggref',
	      searchTerm: '=searchTerm',
	      position: '=position',
	      onTrack: '&',
	      projectPath: '&'
	    },
	    link: function link(scope, element, attrs) {
	      scope.i18n = i18n;
	      $timeout(function () {
	        projectCard.ellipsizeProjectCardTagline(element);
	      });
	
	      scope.projectUrl = null;
	      scope.$watch('campaign', function () {
	        if (attrs.projectPath) {
	          scope.projectUrl = scope.projectPath(scope.campaign);
	        } else {
	          scope.projectUrl = scope.iggref ? scope.campaign.url.concat('/', scope.iggref) : scope.campaign.url;
	        }
	      });
	
	      scope.clickCategory = function ($event) {
	        igg.externalService(function () {
	          // TODO EVENTS: id=ied6w subsystem=project-cards fixtype=bare-ga category=discoveryCard category-new=Discovery.Card action-new=Click.Category action=clickCategory label=dynamic . move ga() to .track()
	          ga('send', 'event', 'discoveryCard', 'clickCategory', scope.campaign.category_name);
	        });
	
	        $window.location.href = scope.campaign.category_url;
	        $event.stopPropagation();
	      };
	
	      scope.clickProject = function ($event) {
	        if (attrs.onTrack) {
	          scope.onTrack();
	        }
	
	        if ($event.metaKey || $event.ctrlKey) {
	          browser.openTab(scope.projectUrl);
	        } else {
	          browser.redirectTo(scope.projectUrl);
	        }
	
	        $event.preventDefault();
	      };
	    }
	  };
	}

/***/ },
/* 168 */
/***/ function(module, exports) {

	module.exports = "<a ng-href=\"{{projectUrl}}\" ng-click=\"clickProject($event)\" class=\"discoveryCard\">\n  <div class=\"discoveryCard-imageWrapper\">\n    <div class=\"discoveryCard-image\" ng-style=\"{'background-image': 'url(' + campaign.igg_image_url +')'}\">\n      <div class=\"discoveryCard-partner\" ng-if=\"campaign.partner_name\"> &mdash; {{::i18n.t('with')}} {{::campaign.partner_name}}</div>\n    </div>\n  </div>\n  <div class=\"discoveryCard-meta\">\n    <div class=\"discoveryCard-metaLead\">\n      <div class=\"discoveryCard-category\" ng-if=\"::campaign.category_name !== ''\" ng-click=\"clickCategory($event)\">\n        {{::campaign.category_name}}\n      </div>\n      <div class=\"discoveryCard-category\" ng-if=\"::campaign.category_name == ''\">\n        {{::i18n.t('no_category')}}\n      </div>\n      <div class=\"discoveryCard-title\" clamp=\"2\">{{::campaign.title}}</div>\n      <div class=\"discoveryCard-tagline\">{{::campaign.tagline | truncate:110}}</div>\n    </div>\n    <div class=\"discoveryCard-metaFinal\">\n      <span class=\"discoveryCard-balance\">{{::campaign.balance}}</span>&nbsp;\n      <span class=\"discoveryCard-currencyCode\">{{::campaign.currency_code}}</span>\n      <div class=\"discoveryCard-progress\">\n        <div class=\"discoveryCard-progressComplete\" ng-style=\"{width: (campaign.nearest_five_percent) + '%'}\"></div>\n      </div>\n      <div class=\"discoveryCard-progressLabels\">\n        <div class=\"discoveryCard-cta\" ng-if=\"::campaign.in_forever_funding\">{{::i18n.t('in_demand_label')}}</div>\n        <div class=\"discoveryCard-percent\" ng-if=\"::!campaign.in_forever_funding\">{{::campaign.collected_percentage }}</div>\n        <div class=\"discoveryCard-timeleft\" ng-if=\"::!campaign.in_forever_funding\">{{::campaign.amt_time_left }}</div>\n      </div>\n    </div>\n  </div>\n</a>\n";

/***/ },
/* 169 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	
	exports.default = function () {
	  return {
	    template: __webpack_require__(170),
	    link: function link(scope) {
	      scope.campaign = {
	        title: '███ ██████████████',
	        tagline: '█████ ███████████ ████████ ██████████████████ ██████',
	        balance: '██',
	        currency_code: '█',
	        nearest_five_percent: 80,
	        collected_percentage: '██',
	        amt_time_left: '███ ██ █'
	      };
	    }
	  };
	};

/***/ },
/* 170 */
/***/ function(module, exports) {

	module.exports = "<project-card-discovery-www campaign=\"campaign\" class=\"discoveryCard--placeholder\"/>\n";

/***/ },
/* 171 */
/***/ function(module, exports) {

	'use strict';
	
	ngTranscludeReplace.$inject = ["$log"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = ngTranscludeReplace;
	/*@ngInject*/
	function ngTranscludeReplace($log) {
	  return {
	    terminal: true,
	    restrict: 'EA',
	    link: function link($scope, $element, $attr, ctrl, transclude) {
	      if (!transclude) {
	        $log.error('orphan', 'Illegal use of ngTranscludeReplace directive in the template! ' + 'No parent directive that requires a transclusion found. ');
	        return;
	      }
	      transclude(function (clone) {
	        if (clone.length) {
	          $element.replaceWith(clone);
	        } else {
	          $element.remove();
	        }
	      });
	    }
	  };
	}

/***/ },
/* 172 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';
	
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	
	exports.default = function (angular) {
	  angular.module('indiegogo.components.updatePreview', ['utils']).factory('updatePreview', _updatePreviewService2.default).controller('UpdatePreviewModal', _updatePreviewModalController2.default);
	};
	
	var _updatePreviewService = __webpack_require__(173);
	
	var _updatePreviewService2 = _interopRequireDefault(_updatePreviewService);
	
	var _updatePreviewModalController = __webpack_require__(174);
	
	var _updatePreviewModalController2 = _interopRequireDefault(_updatePreviewModalController);
	
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/***/ },
/* 173 */
/***/ function(module, exports) {

	'use strict';
	
	updatePreviewService.$inject = ["$http", "gon", "$sce", "$q", "$analytics"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = updatePreviewService;
	/*@ngInject*/
	
	function updatePreviewService($http, gon, $sce, $q, $analytics) {
	  var previewUrl = gon.urls.preview_update;
	  var sendPreviewUrl = gon.urls.send_preview;
	  var confirmationImagePath = gon.email_confirmation_image_path;
	  var previewStates = { initial: 'initial', working: 'working', complete: 'complete' };
	
	  function trackEvent(gaCategory, gaName, thetaName) {
	    var thetaOptions = {};
	    if (gon.campaign && gon.campaign.id) {
	      thetaOptions.project_id = gon.campaign.id;
	    }
	    if (gon.current_user && gon.current_user.id) {
	      thetaOptions.account_id = gon.current_user.id;
	    }
	
	    $analytics.eventTrack(gaName, _.merge({
	      name: thetaName,
	      category: gaCategory
	    }, thetaOptions));
	  }
	
	  function getPreview(update) {
	    var deferred = $q.defer();
	
	    if (this.isDisabled) {
	      return deferred.promise;
	    }
	
	    var _this = this;
	    var encodedBody = encodeURIComponent(update.bodyHtml);
	    var url = previewUrl + '?announcement[body_html]=' + encodedBody;
	
	    $http.get(url).then(function (response) {
	      _this.previewHtml = response.data.response.body_html;
	      _this.trustedHtml = $sce.trustAsHtml(_this.previewHtml);
	      deferred.resolve(response);
	    });
	
	    return deferred.promise;
	  }
	
	  function sendPreviewEmail() {
	    this.currentPreviewState = previewStates.working;
	    var _this = this;
	
	    $http.post(sendPreviewUrl, {
	      announcement: {
	        email: this.email,
	        body_html: this.previewHtml
	      }
	    }).then(function (response) {
	      _this.currentPreviewState = previewStates.complete;
	    });
	  }
	
	  function isInitial() {
	    return this.currentPreviewState === previewStates.initial;
	  }
	
	  function isWorking() {
	    return this.currentPreviewState === previewStates.working;
	  }
	
	  function isComplete() {
	    return this.currentPreviewState === previewStates.complete;
	  }
	
	  return {
	    /* properties */
	    isDisabled: true,
	    confirmationImagePath: confirmationImagePath,
	    trustedHtml: '',
	    email: '',
	    previewStates: previewStates,
	    currentPreviewState: previewStates.initial,
	
	    /* functions */
	    trackEvent: trackEvent,
	    getPreview: getPreview,
	    sendPreviewEmail: sendPreviewEmail,
	    isInitial: isInitial,
	    isWorking: isWorking,
	    isComplete: isComplete
	  };
	}

/***/ },
/* 174 */
/***/ function(module, exports) {

	'use strict';
	
	UpdatePreviewModalController.$inject = ["$scope", "$timeout", "updatePreview", "i18n"];
	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = UpdatePreviewModalController;
	/* @ngInject */
	function UpdatePreviewModalController($scope, $timeout, updatePreview, i18n) {
	  $scope.i18n = i18n;
	  $scope.updatePreview = updatePreview;
	
	  $scope.resetPreviewState = function () {
	    updatePreview.currentPreviewState = updatePreview.previewStates.initial;
	  };
	
	  $scope.sendTest = function () {
	    // TODO EVENTS: id=eightballtbd
	    updatePreview.trackEvent('Update Preview Modal', 'Send Test', 'update_preview_modal_send_test_click');
	    updatePreview.sendPreviewEmail();
	  };
	
	  $scope.cancelPreview = function () {
	    // TODO EVENTS: id=eightballtbd
	    updatePreview.trackEvent('Update Preview Modal', 'Close Window', 'update_preview_modal_close_click');
	    $scope.$hide();
	    $timeout(function () {
	      $scope.resetPreviewState();
	    }, 500);
	  };
	}

/***/ },
/* 175 */
/***/ function(module, exports, __webpack_require__) {

	/*** IMPORTS FROM imports-loader ***/
	var Pusher = __webpack_require__(63);
	
	'use strict';
	
	angular.module('pusher-angular', [])
	
	.factory('$pusher', ['$rootScope', '$channel', '$connection',
	  function ($rootScope, $channel, $connection) {
	
	    function PusherAngular (pusherClient) {
	      if (!(this instanceof PusherAngular)) {
	        return new PusherAngular(pusherClient);
	      }
	
	      this._assertValidClient(pusherClient);
	      this.client = pusherClient;
	      this.connection = $connection(pusherClient.connection, pusherClient);
	      this.channels = {};
	    }
	
	    PusherAngular.prototype = {
	      /**
	       * Subscribe the client to the specified channelName and returns the channel object.
	       * {@link https://pusher.com/docs/client_api_guide/client_public_channels#subscribe}
	       *
	       * @param {String} channelName name of the channel
	       * @returns {Object} channel object
	       */
	      subscribe: function (channelName) {
	        var channel = $channel(this.client.subscribe(channelName), this);
	        this.channels[channelName] = channel;
	        return channel;
	      },
	
	      /**
	       * Unsubscribes the client from the specified channel
	       * {@link https://pusher.com/docs/client_api_guide/client_public_channels#unsubscribe}
	       *
	       * @param {String} channelName name of the channel
	       */
	      unsubscribe: function (channelName) {
	        if (this.client.channel(channelName)) {
	          this.client.unsubscribe(channelName);
	          if (this.channels[channelName]) { delete this.channels[channelName]; }
	        }
	      },
	
	      /**
	       * Binds to global events on the pusher client. You can attach behaviour to these events
	       * regardless of the channel the event is broadcast to.
	       *
	       * @param {String} eventName name of the event you want to bind to
	       * @param {Function|undefined} callback callback that you want called upon the event occurring
	       */
	      bind: function (eventName, callback) {
	        this.client.bind(eventName, function (data) {
	          callback(data);
	          $rootScope.$digest();
	        });
	      },
	
	      /**
	       * Binds to all of the global client messages.
	       *
	       * @param {Function|undefined} callback callback that you want called upon a message being received
	       */
	      bind_all: function (callback) {
	        this.client.bind_all(function (eventName, data) {
	          callback(eventName, data);
	          $rootScope.$digest();
	        });
	      },
	
	      /**
	       * Unbinds from global events on the pusher client.
	       *
	       * @param {String} eventName name of the event you want to bind from
	       * @param {Function|undefined} callback callback that you want to unbind
	       */
	      unbind: function (eventName, callback) {
	        this.client.unbind(eventName, callback);
	      },
	
	      /**
	       * Disconnects the pusher client.
	       * {@link http://pusher.com/docs/client_api_guide/client_connect#disconnecting}
	       */
	      disconnect: function () {
	        this.client.disconnect();
	      },
	
	      /**
	       * Returns a pusher channel object.
	       * {@link https://pusher.com/docs/client_api_guide/client_channels#access}
	       *
	       * @param {String} channelName name of the channel
	       * @returns {Array} channel object
	       */
	      channel: function (channelName) {
	        return this.channels[channelName];
	      },
	
	      /**
	       * Returns a an array of the channels that the client is subscribed to.
	       * {@link https://pusher.com/docs/client_api_guide/client_channels#access}
	       *
	       * @returns {Array} array of subscribed channels
	       */
	      allChannels: function () {
	        return this.channels;
	      },
	
	      /**
	       * Asserts that the $pusher object is being initialised with valid pusherClient.
	       * Throws an error if pusherClient is invalid.
	       *
	       * @param {Object} pusherClient members object from base pusher channel object
	       */
	      _assertValidClient: function (pusherClient) {
	        if (!angular.isObject(pusherClient) ||
	            !angular.isObject(pusherClient.connection) ||
	            typeof(pusherClient.channel) !== 'function') {
	          throw new Error('Invalid Pusher client object');
	        }
	      }
	    };
	
	    return PusherAngular;
	  }
	])
	
	.factory('$channel', ['$rootScope', '$members',
	  function ($rootScope, $members) {
	
	    function checkPresenceOrPrivateChannel (channelName) {
	      if (channelName.indexOf('presence-') == -1 && channelName.indexOf('private-') == -1) {
	        throw new Error('Presence or private channel required');
	      }
	    }
	
	    function $channel (baseChannel, $pusherClient) {
	      if (!(this instanceof $channel)) {
	        return new $channel(baseChannel, $pusherClient);
	      }
	
	      this._assertValidChannel(baseChannel);
	      this.baseChannel = baseChannel;
	      this.client = $pusherClient;
	      this.name = baseChannel.name;
	
	      if (baseChannel.name.indexOf('presence') == -1) {
	        this.members = function () { throw new Error('Members object only exists for presence channels'); }
	      } else {
	        this.members = $members(baseChannel.members, baseChannel);
	      }
	    }
	
	    $channel.prototype = {
	      /**
	       * Binds to the given event name on the channel.
	       *
	       * @param {String} eventName name of the event you want to bind to
	       * @param {Function|undefined} callback callback that you want called upon the event occurring
	       */
	      bind: function (eventName, callback) {
	        this.baseChannel.bind(eventName, function (data) {
	          callback(data);
	          $rootScope.$digest();
	        });
	      },
	
	      /**
	       * Unbinds from the given event name on the channel.
	       *
	       * @param {String} eventName name of the event you want to bind from
	       * @param {Function|undefined} callback callback that you want to unbind
	       */
	      unbind: function (eventName, callback) {
	        this.baseChannel.unbind(eventName, callback);
	      },
	
	      /**
	       * Binds to all of the channel events.
	       *
	       * @param {Function|undefined} callback callback that you want called upon the event occurring
	       */
	      bind_all: function (callback) {
	        this.baseChannel.bind_all(function (eventName, data) {
	          callback(eventName, data);
	          $rootScope.$digest();
	        });
	      },
	
	      /**
	       * Triggers a client event.
	       * {@link https://pusher.com/docs/client_api_guide/client_events#trigger-events}
	       *
	       * @param {String} channelName name of the channel
	       * @param {String} eventName name of the event
	       * @param {Object} obj object that you wish to pass along with your client event
	       * @returns {}
	       */
	      trigger: function (eventName, obj) {
	        checkPresenceOrPrivateChannel(this.name);
	        if (eventName.indexOf('client-') == -1) { throw new Error('Event name requires \'client-\' prefix'); }
	        return this.baseChannel.trigger(eventName, obj);
	      },
	
	      /**
	       * Asserts that the $channel object is being initialised with valid baseChannel.
	       * Throws an error if baseChannel is invalid.
	       *
	       * @param {Object} baseChannel channel object from base pusher channel object
	       */
	      _assertValidChannel: function (baseChannel) {
	        if (!angular.isObject(baseChannel) ||
	            typeof(baseChannel.name) !== 'string') {
	          throw new Error('Invalid Pusher channel object');
	        }
	      }
	    };
	
	    return $channel;
	  }
	])
	
	.factory('$members', ['$rootScope',
	  function ($rootScope) {
	
	    function $members (baseMembers, baseChannel) {
	      if (!(this instanceof $members)) {
	        return new $members(baseMembers, baseChannel);
	      }
	      var self = this;
	
	      this._assertValidMembers(baseMembers);
	      this.baseMembers = baseMembers;
	      this.baseChannel = baseChannel;
	      this.me = {};
	      this.count = 0;
	      this.members = {};
	
	      baseChannel.bind('pusher:subscription_succeeded', function (members) {
	        self.me = members.me;
	        self.count = members.count;
	        self.members = members.members;
	        $rootScope.$digest();
	      });
	
	      baseChannel.bind('pusher:member_added', function (member) {
	        self.count++;
	        if (member.info) {
	          self.members[member.id.toString()] = member.info;
	        } else {
	          self.members[member.id.toString()] = null;
	        }
	        $rootScope.$digest();
	      });
	
	      baseChannel.bind('pusher:member_removed', function (member) {
	        self.count--;
	        delete self.members[member.id.toString()];
	        $rootScope.$digest();
	      });
	    }
	
	    $members.prototype = {
	     /**
	      * Returns member's info for given id. Resulting object containts two fields - id and info.
	      *
	      * @param {Number} id user's id
	      * @return {Object} member's info or null
	      */
	      get: function (id) {
	        return this.baseMembers.get(id);
	      },
	
	      /**
	       * Calls back for each member in unspecified order.
	       *
	       * @param {Function} callback callback function
	       */
	      each: function (callback) {
	        this.baseMembers.each(function (member) {
	          callback(member);
	          $rootScope.$digest();
	        });
	      },
	
	      /**
	       * Asserts that the $members object is being initialised with valid baseMembers.
	       * Throws an error if baseMembers is invalid.
	       *
	       * @param {Object} baseMembers members object from base pusher channel object
	       */
	      _assertValidMembers: function (baseMembers) {
	        if (!angular.isObject(baseMembers) ||
	            typeof(baseMembers.me) !== 'object') {
	          throw new Error('Invalid Pusher channel members object');
	        }
	      }
	    };
	
	    return $members;
	  }
	])
	
	.factory('$connection', ['$rootScope',
	  function ($rootScope) {
	
	    function $connection (baseConnection, baseClient) {
	      if (!(this instanceof $connection)) {
	        return new $connection(baseConnection, baseClient);
	      }
	
	      this._assertValidConnection(baseConnection);
	      this.baseConnection = baseConnection;
	      this.baseClient = baseClient;
	    }
	
	    $connection.prototype = {
	      /**
	       * Binds to the given event name on the connection.
	       *
	       * @param {String} eventName name of the event you want to bind to
	       * @param {Function|undefined} callback callback that you want called upon the event occurring
	       */
	      bind: function (eventName, callback) {
	        this.baseConnection.bind(eventName, function (data) {
	          callback(data);
	          $rootScope.$digest();
	        });
	      },
	
	      /**
	       * Binds to all of the global connection events.
	       *
	       * @param {Function|undefined} callback callback that you want called upon the event occurring
	       */
	      bind_all: function (callback) {
	        this.baseConnection.bind_all(function (eventName, data) {
	          callback(eventName, data);
	          $rootScope.$digest();
	        });
	      },
	
	      /**
	       * Asserts that the $connection object is being initialised with valid baseConnection.
	       * Throws an error if baseConnection is invalid.
	       *
	       * @param {Object} baseConnection connection object from base pusher object
	       */
	      _assertValidConnection: function (baseConnection) {
	        if (!angular.isObject(baseConnection)) {
	          throw new Error('Invalid Pusher connection object');
	        }
	      }
	    };
	
	    return $connection;
	  }
	]);
	


/***/ },
/* 176 */
/***/ function(module, exports) {

	module.exports = "<div class=\"pc-dashboard-header hidden-xs\">{{::i18n.t('generosity.fundraiser_dashboard.manage_your_fundraiser')}}</div>\n<div class=\"pc-dashboard-layout\">\n  <div class=\"pc-dashboard-rightRailCol\">\n    <div pc-dashboard-campaign-card class=\"pc-dashboard-rightRailCol-item\"></div>\n    <div pc-dashboard-fundraiser-link class=\"hidden-xs pc-dashboard-rightRailCol-item pc-dashboard-section pc-dashboard-section--simple\" title=\"{{::i18n.t('generosity.dashboard.your_fundraiser_link')}}\"></div>\n    <div pc-visit-stats class=\"pc-dashboard-visitStats pc-dashboard-rightRailCol-item\"></div>\n    <div pc-dashboard-end-fundraiser class=\"hidden-xs pc-dashboard-rightRailCol-item pc-dashboard-section pc-dashboard-section--simple\"></div>\n  </div>\n  <div class=\"pc-dashboard-mainCol\">\n    <div pc-dashboard-post-update class=\"pc-dashboard-section pc-dashboard-mainCol-item pc-dashboard-section--darker\"></div>\n    <div pc-todo-items class=\"pc-dashboard-section pc-dashboard-mainCol-item pc-dashboard-todoItems\"></div>\n    <div pc-automated-facebook-updates class=\"pc-dashboard-mainCol-item pc-dashboard-section\"></div>\n    <div pc-recent-donations ng-if=\"hasRecentDonations\" class=\"pc-dashboard-mainCol-item pc-dashboard-section\"></div>\n    <div pc-dashboard-end-fundraiser class=\"visible-xs pc-dashboard-mainCol-item pc-dashboard-section pc-dashboard-section--simple\"></div>\n  </div>\n</div>\n";

/***/ },
/* 177 */
/***/ function(module, exports) {

	module.exports = "<div life-funds></div>\n";

/***/ },
/* 178 */
/***/ function(module, exports) {

	module.exports = "<div ng-if=\"!stripePayoutActive\" class=\"container-xs\" life-funds-bank-info></div>\n<div ng-if=\"stripePayoutActive\" class=\"container-xs\" generosity-stripe-bank-form></div>\n";

/***/ },
/* 179 */
/***/ function(module, exports) {

	module.exports = "<div class=\"pc-dashboard-donations\" pc-dashboard-donations>\n</div>\n";

/***/ },
/* 180 */
/***/ function(module, exports) {

	module.exports = "<campaign-main class=\"i-campaign-main\">\n</campaign-main>\n";

/***/ },
/* 181 */
/***/ function(module, exports) {

	module.exports = "<div campaign-story class=\"i-campaign-story\"></div>\n";

/***/ },
/* 182 */
/***/ function(module, exports) {

	module.exports = "<div class=\"pc-shareWizard-container\">\n  <div class=\"pc-shareWizard-content container\">\n    <div class=\"pc-shareWizard-content-top\">\n      <img class=\"pc-shareWizard-content-top-image visible-xs\" ng-src=\"{{urls.fundraiser_image_url}}\">\n      <div class=\"pc-shareWizard-content-top-subtitle hidden-xs\">{{i18n.pt('share_wizard.lets_work_on_your_first_donation')}}</div>\n      <div class=\"pc-shareWizard-content-top-title\">{{i18n.pt('share_wizard.share_with_your_friends_on_facebook')}}</div>\n      <!-- TODO EVENTS: id=eeng5 fixtype=event-dir subsystem=share vars=tags+page-location name=click_fb_share category-new=TBD trigger=click dom=a . review -->\n      <a href=\"\" ng-click=\"shareFacebook()\" class=\"i-cta-1 i-cta-1--iconed i-cta-1--facebook i-shareWizard-btn i-shareWizard-btn-iconed visible-xs\"\n          event-on=\"click\" event-name=\"click_fb_share\" event-tags=\"{{eventTags()}}\" event-page-location=\"mobile_btn\">\n        <svg class=\"i-cta-1-icon\"><use xlink:href=\"#icon-icon-facebook\"></use></svg>\n        <span>{{::i18n.t('share_on_facebook')}}</span>\n      </a>\n      <!-- TODO EVENTS: id=is3ro fixtype=event-dir subsystem=share vars=tags name=share_wizard_skip category-new=TBD trigger=click dom=div . -->\n      <div class=\"pc-shareWizard-skip hidden-xs\" ng-click=\"goTo('facebook-2')\"\n           event-on=\"click\" event-name=\"share_wizard_skip\" event-tags=\"{{eventTags()}}\">\n        {{i18n.pt('share_wizard.skip')}}\n      </div>\n    </div>\n    <div class=\"pc-shareWizard-content-middle pc-shareWizard-shaded hidden-xs\">\n      <div class=\"pc-shareWizard-content-middle-container\">\n        <!-- TODO EVENTS: id=wu6na fixtype=event-dir subsystem=share vars=tags+page-location name=click_fb_share category-new=TBD trigger=click dom=div . review -->\n        <div class=\"pc-shareWizard-content-middle-socialContainer\" ng-click=\"shareFacebook()\"\n             event-on=\"click\" event-name=\"click_fb_share\" event-tags=\"{{eventTags()}}\" event-page-location=\"mock_content\">\n          <div class=\"pc-socialContainer-textField\">{{i18n.pt('share_wizard.say_something_about_this')}}</div>\n          <div class=\"pc-socialContainer-shareSummary\">\n            <img class=\"pc-socialContainer-shareSummary-image\" ng-src=\"{{urls.fundraiser_image_url}}\"/>\n            <div class=\"pc-socialContainer-shareSummary-content\">\n              <div class=\"pc-shareSummary-content-title\">{{fundraiser.title}}</div>\n              <div class=\"pc-shareSummary-content-blurb\">{{facebookShareText}}</div>\n              <div class=\"pc-shareSummary-content-link\">\n                <svg><use xlink:href=\"#icon-icon-link\"></use></svg>\n                <span>{{i18n.pt('share_wizard.url')}}</span>\n              </div>\n            </div>\n          </div>\n        </div>\n        <div class=\"pc-shareWizard-content-middle-autoFb\" ng-if=\"autopostCapable\">\n          <div class=\"pc-shareWizard-autoFb-checkbox\" ng-click=\"toggleAutoFbPost()\">\n            <svg-icon icon=\"icon-icon-check\" ng-if=\"autopostChecked\"></svg-icon>\n          </div>\n          <div class=\"pc-shareWizard-autoFb-text\">\n            <span>{{i18n.pt('share_wizard.automatically_post_to_facebook')}}</span>\n            <span igg-popover placement=\"top\">{{i18n.pt('share_wizard.auto_facebook_post_settings_change')}}</span>\n          </div>\n        </div>\n      </div>\n    </div>\n    <div class=\"pc-shareWizard-content-bottom\">\n      <div class=\"pc-shareWizard-content-bottom-left\">\n        <div class=\"pc-shareWizard-content-bottom-header\">{{i18n.pt('share_wizard.did_you_know')}}</div>\n        <div>{{i18n.pt('share_wizard.facebook_stats')}}</div>\n      </div>\n      <div class=\"pc-shareWizard-content-bottom-right hidden-xs\">\n        <!-- TODO EVENTS: id=ida3w fixtype=event-dir subsystem=share vars=tags+page-location name=click_fb_share category-new=TBD trigger=click dom=div . review -->\n        <div class=\"i-cta-1 i-cta-1--iconed i-cta-1--facebook i-shareWizard-btn i-shareWizard-btn-iconed\" ng-click=\"shareFacebook()\"\n             event-on=\"click\" event-name=\"click_fb_share\" event-tags=\"{{eventTags()}}\" event-page-location=\"bottom_btn\">\n          <svg class=\"i-cta-1-icon\"><use xlink:href=\"#icon-icon-facebook\"></use></svg>\n          <span>{{::i18n.t('share_on_facebook')}}</span>\n        </div>\n      </div>\n    </div>\n  </div>\n  <div class=\"visible-xs\">\n    <div class=\"pc-shareWizard-nav pc-shareWizard-nav--single\" ng-click=\"goTo('facebook-2')\">\n    <!-- TODO EVENTS: id=eiqu5 fixtype=event-dir subsystem=share vars=tags name=share_wizard_skip category-new=TBD trigger=click dom=div . review -->\n      <div event-on=\"click\" event-name=\"share_wizard_skip\" event-tags=\"{{eventTags()}}\">\n        {{i18n.pt('share_wizard.skip')}}\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 183 */
/***/ function(module, exports) {

	module.exports = "<div class=\"pc-shareWizard-container\">\n  <div class=\"pc-shareWizard-content container pc-shareWizard-facebook\">\n    <div class=\"pc-shareWizard-content-top\">\n      <div class=\"pc-shareWizard-content-top-subtitle hidden-xs\">{{i18n.pt('share_wizard.we_want_you_to_get_off_at_good_start')}}</div>\n      <div class=\"pc-shareWizard-content-top-title\">{{i18n.pt('share_wizard.sharing_on_fb_is_important')}}</div>\n    </div>\n    <div class=\"pc-shareWizard-content-middle pc-shareWizard-shaded\">\n      <div class=\"pc-content-middle-valueProp\">\n        <div class=\"pc-content-middle-valueProp-icon\">\n          <svg><use xlink:href=\"#icon-icon-check\"></use></svg>\n        </div>\n        <div class=\"pc-content-middle-valueProp-content\">\n          <div class=\"pc-content-middle-valueProp-title\">{{i18n.pt('share_wizard.facebook.value_prop_1.title')}}</div>\n          <div class=\"pc-content-middle-valueProp-subtitle\">{{i18n.pt('share_wizard.facebook.value_prop_1.subtitle')}}</div>\n        </div>\n      </div>\n      <div class=\"pc-content-middle-valueProp\">\n        <div class=\"pc-content-middle-valueProp-icon\">\n          <svg><use xlink:href=\"#icon-icon-check\"></use></svg>\n        </div>\n        <div class=\"pc-content-middle-valueProp-content\">\n          <div class=\"pc-content-middle-valueProp-title\">{{i18n.pt('share_wizard.facebook.value_prop_2.title')}}</div>\n          <div class=\"pc-content-middle-valueProp-subtitle\">{{i18n.pt('share_wizard.facebook.value_prop_2.subtitle')}}</div>\n        </div>\n      </div>\n      <div class=\"pc-content-middle-valueProp\">\n        <div class=\"pc-content-middle-valueProp-icon\">\n          <svg><use xlink:href=\"#icon-icon-check\"></use></svg>\n        </div>\n        <div class=\"pc-content-middle-valueProp-content\">\n          <div class=\"pc-content-middle-valueProp-title\">{{i18n.pt('share_wizard.facebook.value_prop_3.title')}}</div>\n          <div class=\"pc-content-middle-valueProp-subtitle\">{{i18n.pt('share_wizard.facebook.value_prop_3.subtitle')}}</div>\n        </div>\n      </div>\n    </div>\n    <div class=\"pc-shareWizard-content-bottom\">\n      <!-- TODO EVENTS: id=aux2f fixtype=event-dir subsystem=share category-new=TBD name=share_wizard_skip vars=tags . review -->\n      <div class=\"i-cta-1 i-shareWizard-btn i-shareWizard-btn-hollow\" ng-click=\"goTo('twitter')\"\n           event-on=\"click\" event-name=\"share_wizard_skip\" event-tags=\"{{eventTags()}}\">\n        {{i18n.pt('share_wizard.not_now')}}\n      </div>\n      <!-- TODO EVENTS: id=kiap4 fixtype=event-dir subsystem=share category-new=TBD name=click_fb_share vars=tags . review -->\n      <div class=\"i-cta-1 i-cta-1--iconed i-cta-1--facebook i-shareWizard-btn i-shareWizard-btn-iconed\" ng-click=\"shareFacebook()\"\n           event-on=\"click\" event-name=\"click_fb_share\" event-tags=\"{{eventTags()}}\">\n        <svg class=\"i-cta-1-icon\"><use xlink:href=\"#icon-icon-facebook\"></use></svg>\n        <span>{{::i18n.t('share_on_facebook')}}</span>\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 184 */
/***/ function(module, exports) {

	module.exports = "<div class=\"pc-shareWizard-container\">\n  <div class=\"pc-shareWizard-content container\">\n    <div class=\"pc-shareWizard-content-top\">\n      <img class=\"pc-shareWizard-content-top-image visible-xs\" ng-src=\"{{urls.fundraiser_image_url}}\">\n      <div class=\"pc-shareWizard-content-top-subtitle hidden-xs\" ng-if=\"facebookShared\">{{i18n.pt('share_wizard.facebook_post_hard_at_work')}}</div>\n      <div class=\"pc-shareWizard-content-top-subtitle hidden-xs\" ng-if=\"!facebookShared\">{{i18n.pt('share_wizard.you_can_post_to_facebook_later')}}</div>\n      <div class=\"pc-shareWizard-content-top-title\">{{i18n.pt('share_wizard.broaden_your_reach_on_twitter')}}</div>\n      <!-- TODO EVENTS: id=vie3o fixtype=event-dir subsystem=share trigger=click dom=a name=click_tw_share category-new=TBD vars=tags+page-location . review -->\n      <a ng-href=\"{{twitterShareUrl}}\" class=\"i-cta-1 i-cta-1--iconed i-cta-1--twitter i-shareWizard-btn i-shareWizard-btn-iconed visible-xs\"\n          event-on=\"click\" event-name=\"click_tw_share\" event-tags=\"{{eventTags()}}\" event-page-location=\"mobile_btn\">\n        <svg class=\"i-cta-1-icon\"><use xlink:href=\"#icon-icon-twitter\"></use></svg>\n        <span>{{::i18n.t('share_on_twitter')}}</span>\n      </a>\n      <!-- TODO EVENTS: id=eixo5 fixtype=event-dir subsystem=share trigger=click dom=div name=share_wizard_skip vars=tags category-new=TBD . review -->\n      <div class=\"pc-shareWizard-skip hidden-xs\" ng-click=\"goTo('email')\"\n          event-on=\"click\" event-name=\"share_wizard_skip\" event-tags=\"{{eventTags()}}\">\n        {{i18n.pt('share_wizard.skip')}}\n      </div>\n      <!-- TODO EVENTS: id=uath5 fixtype=event-dir subsystem=share trigger=click dom=div name=share_wizard_back vars=tags category-new=TBD . review -->\n      <div class=\"pc-shareWizard-back hidden-xs\" ng-click=\"goTo('facebook')\"\n          event-on=\"click\" event-name=\"share_wizard_back\" event-tags=\"{{eventTags()}}\">\n        <svg><use xlink:href=\"#icon-icon-leftarrow\"></use></svg>\n      </div>\n    </div>\n    <div class=\"pc-shareWizard-content-middle pc-shareWizard-shaded hidden-xs\">\n      <div class=\"pc-shareWizard-content-middle-container pc-shareWizard-content-middle-socialContainer pc-socialContainer-twitter\">\n        <!-- TODO EVENTS: id=jo9ju fixtype=event-dir subsystem=share trigger=click dom=a name=click_tw_share category-new=TBD vars=tags+page-location . review -->\n        <a ng-href=\"{{twitterShareUrl}}\" class=\"pc-socialContainer-shareSummary\"\n            event-on=\"click\" event-name=\"click_tw_share\" event-tags=\"{{eventTags()}}\" event-page-location=\"mock_content\">\n          <img class=\"pc-socialContainer-shareSummary-image\" ng-src=\"{{urls.fundraiser_image_url}}\"/>\n          <div class=\"pc-socialContainer-shareSummary-content\">\n            <div class=\"pc-shareSummary-content-blurb\">{{twitterShareText}}</div>\n            <div class=\"pc-shareSummary-content-link\">\n              {{urls.fundraiser_short_link}}\n            </div>\n          </div>\n        </a>\n      </div>\n    </div>\n    <div class=\"pc-shareWizard-content-bottom\">\n      <div class=\"pc-shareWizard-content-bottom-left\">\n        <div class=\"pc-shareWizard-content-bottom-header\">{{i18n.pt('share_wizard.did_you_know')}}</div>\n        <div>{{i18n.pt('share_wizard.you_dont_need_a_lot_of_twitter')}}</div>\n      </div>\n      <div class=\"pc-shareWizard-content-bottom-right hidden-xs\">\n        <!-- TODO EVENTS: id=yo9go fixtype=event-dir subsystem=share name=click_tw_share vars=tags+page-location trigger=click dom=a category-new=TBD . review -->\n        <a class=\"i-cta-1 i-cta-1--twitter i-cta-1--iconed i-shareWizard-btn i-shareWizard-btn-iconed\" ng-href=\"{{twitterShareUrl}}\"\n            event-on=\"click\" event-name=\"click_tw_share\" event-tags=\"{{eventTags()}}\" event-page-location=\"bottom_btn\">\n          <svg class=\"i-cta-1-icon\"><use xlink:href=\"#icon-icon-twitter\"></use></svg>\n          <span>{{::i18n.t('share_on_twitter')}}</span>\n        </a>\n      </div>\n    </div>\n  </div>\n  <div class=\"visible-xs\">\n    <div class=\"pc-shareWizard-nav\">\n      <!-- TODO EVENTS: id=aew9u fixtype=event-dir subsystem=share name=share_wizard_back vars=tags trigger=click dom=svg category-new=TBD . review -->\n      <svg ng-click=\"goTo('facebook')\"\n           event-on=\"click\" event-name=\"share_wizard_back\" event-tags=\"{{eventTags()}}\"><use xlink:href=\"#icon-icon-leftarrow\"></use></svg>\n      <!-- TODO EVENTS: id=aew9y fixtype=event-dir subsystem=share name=share_wizard_skip vars=tags trigger=click dom=div category-new=TBD . review -->\n      <div ng-click=\"goTo('email')\"\n           event-on=\"click\" event-name=\"share_wizard_skip\" event-tags=\"{{eventTags()}}\">\n        {{i18n.pt('share_wizard.skip')}}\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ },
/* 185 */
/***/ function(module, exports) {

	module.exports = "<div class=\"pc-shareWizard-container\">\n  <div class=\"pc-shareWizard-content container pc-shareWizard-email\">\n    <div class=\"pc-shareWizard-content-top\">\n      <img class=\"pc-shareWizard-content-top-image visible-xs\" ng-src=\"{{urls.fundraiser_image_url}}\">\n      <div ng-if=\"twitterShared\">\n        <div class=\"pc-shareWizard-content-top-subtitle hidden-xs\">{{i18n.pt('share_wizard.great_work_promote')}}</div>\n        <div class=\"pc-shareWizard-content-top-title\">{{i18n.pt('share_wizard.next_reach_out')}}</div>\n      </div>\n      <div ng-if=\"!twitterShared\">\n        <div class=\"pc-shareWizard-content-top-subtitle hidden-xs\">{{i18n.pt('share_wizard.one_last_step')}}</div>\n        <div class=\"pc-shareWizard-content-top-title\">{{i18n.pt('share_wizard.reach_out')}}</div>\n      </div>\n      <!-- TODO EVENTS: id=yi4ai fixtype=event-dir name=click_email_mailto category-new=TBD vars=tags trigger=click dom=a subsystem=campaign-page . review -->\n      <a href=\"{{urls.email_share_url}}\" target=\"_blank\" class=\"i-cta-1 i-shareWizard-btn visible-xs\"\n          event-on=\"click\" event-name=\"click_email_mailto\" event-tags=\"{{eventTags()}}\">\n        {{::i18n.t('share_via_email')}}\n      </a>\n      <!-- TODO EVENTS: id=iewi0 fixtype=event-dir name=share_wizard_skip category-new=TBD vars=tags trigger=click dom=div subsystem=campaign-page . review -->\n      <div class=\"pc-shareWizard-skip hidden-xs\" ng-click=\"goToPostShare()\"\n          event-on=\"click\" event-name=\"share_wizard_skip\" event-tags=\"{{eventTags()}}\">\n        {{i18n.pt('share_wizard.skip')}}\n      </div>\n      <!-- TODO EVENTS: id=noac4 fixtype=event-dir name=share_wizard_back category-new=TBD vars=tags trigger=click dom=div subsystem=campaign-page . review -->\n      <div class=\"pc-shareWizard-back hidden-xs\" ng-click=\"goTo('twitter')\"\n          event-on=\"click\" event-name=\"share_wizard_back\" event-tags=\"{{eventTags()}}\">\n        <svg><use xlink:href=\"#icon-icon-leftarrow\"></use></svg>\n      </div>\n    </div>\n    <div class=\"pc-shareWizard-content-middle pc-shareWizard-shaded hidden-xs\">\n      <div class=\"pc-shareWizard-content-middle-container pc-shareWizard-content-middle-socialContainer pc-socialContainer-email\" ng-click=\"openEmailImporter()\">\n        <div class=\"pc-socialContainer-shareSummary\">\n          <div class=\"pc-socialContainer-shareSummary-emailSubject\">\n            <span class=\"pc-emailSubject-tag\">{{::i18n.t('email_import.email_subject')}}: </span>\n            {{i18n.pt('email_import.from_owner.email_subject', {project_title: fundraiser.title})}}\n          </div>\n          <div class=\"pc-socialContainer-shareSummary-emailBody\">\n            <p>{{i18n.pt('share_wizard.email_mock.greeting')}}</p>\n            <p>\n              {{i18n.pt('share_wizard.email_mock.reaching_out', {fundraiser_title: fundraiser.title})}}\n              <span ng-if=\"!!fundraiser.beneficiary\">{{i18n.pt('share_wizard.email_mock.beneficiary', {beneficiary_name: fundraiser.beneficiary})}}</span>\n            </p>\n            <p>{{waysToHelp}}</p>\n          </div>\n        </div>\n      </div>\n    </div>\n    <div class=\"pc-shareWizard-content-bottom\">\n      <div class=\"pc-shareWizard-content-bottom-left\">\n        <div class=\"pc-shareWizard-content-bottom-header\">{{i18n.pt('share_wizard.did_you_know')}}</div>\n        <div>{{i18n.pt('share_wizard.fundraisers_shared_via_email')}}</div>\n      </div>\n      <div class=\"pc-shareWizard-content-bottom-right hidden-xs\" email-importer email-from=\"from_owner\" post-email-callback=\"emailCallback()\">\n        <!-- TODO EVENTS: id=ahng1 fixtype=event-dir name=click_email_importer category-new=TBD trigger=click dom=div vars=tags subsystem=campaign-page . review -->\n        <div class=\"i-cta-1 i-shareWizard-btn js-emailImporter\"\n             event-on=\"click\" event-name=\"click_email_importer\" event-tags=\"{{eventTags()}}\">\n          {{i18n.pt('share_wizard.choose_contacts')}}\n        </div>\n      </div>\n    </div>\n  </div>\n  <div class=\"visible-xs\">\n    <div class=\"pc-shareWizard-nav\">\n      <!-- TODO EVENTS: id=teed0 fixtype=event-dir name=share_wizard_back category-new=TBD vars=tags trigger=click dom=svg subsystem=campaign-page . review -->\n      <svg ng-click=\"goTo('twitter')\"\n           event-on=\"click\" event-name=\"share_wizard_back\" event-tags=\"{{eventTags()}}\"><use xlink:href=\"#icon-icon-leftarrow\"></use></svg>\n    <!-- TODO EVENTS: id=fah0s fixtype=event-dir name=share_wizard_skip category-new=TBD vars=tags trigger=click dom=div subsystem=campaign-page . review -->\n      <div ng-click=\"goToPostShare()\"\n           event-on=\"click\" event-name=\"share_wizard_skip\" event-tags=\"{{eventTags()}}\">\n        {{i18n.pt('share_wizard.skip')}}\n      </div>\n    </div>\n  </div>\n</div>\n";

/***/ }
/******/ ]);
//# sourceMappingURL=campaign-page.js.map
