<?xml version="1.0" encoding="UTF-8"?>
<javascript app="calendar">
 <file javascript_app="calendar" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.main.js" javascript_type="controller" javascript_version="103009" javascript_position="1000250"><![CDATA[/**
 * Invision Community
 * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
 *
 * ips.browse.main.js - Calendar main browsing controller
 *
 * Author: Rikki Tissier
 */
;( function($, _, undefined){
	"use strict";

	ips.controller.register('calendar.front.browse.main', {

		_ajaxObj: null,
		
		initialize: function () {
			this.on( 'click', '[data-action="changeView"]', this.changeView );
			this.on( window, 'statechange', this.stateChange );
			this.setup();
		},

		/**
		 * Controller setup method
		 *
		 * @returns {void}
		 */
		setup: function () {
			History.pushState( { controller: 'calendarView' }, document.title, window.location.href );	
		},

		/**
		 * Changes the calendar view dynamically
		 *
		 * @param 	{event} 	e 	Event object
		 * @returns {void}
		 */
		changeView: function (e) {
			e.preventDefault();

			// Load the url via ajax instead
			var self = this;
			var title = $( e.currentTarget ).attr('title');
			var url = $( e.currentTarget ).attr('href');

			History.pushState( { controller: 'calendarView' }, title, url );
		},

		/**
		 * Event handler for history state changes
		 *
		 * @param 	{event} 	e 	Event object
		 * @returns {void}
		 */
		stateChange: function () {
			var state = History.getState();

			if( _.isUndefined( state.data.controller ) || state.data.controller != 'calendarView' ) {
				return;
			}

			// Track page view
			ips.utils.analytics.trackPageView( state.url );

			this._updateView( state.url, state.title )
		},

		/**
		 * Loads a new view 
		 *
		 * @param 	{string} 	url 	URL to load
		 * @param 	{string} 	title 	New browser title
		 * @returns {void}
		 */
		_updateView: function (url, title) {
			var self = this;

			if( this._ajaxObj && _.isFunction( this._ajaxObj.abort ) ){
				this._ajaxObj.abort();
			}

			this._setLoading( true );

			this._ajaxObj = ips.getAjax()( url, {
				showLoading: true
			} )
				.done( function (response) {
					self.scope.html( response );

					$( document ).trigger( 'contentChange', [ self.scope ] );

					History.pushState( { controller: 'calendarView' }, title, url );
				})
				.always( function () {
					self._setLoading( false );
				});
		},

		/**
		 * Toggles the loading state on the view
		 *
		 * @param 	{boolean} 	state 		Enable the loading state?
		 * @returns {void}
		 */
		_setLoading: function (state) {
			if( state ){
				this.scope.animate( { opacity: 0.6 }, 'fast' );
			} else {
				this.scope.animate( { opacity: 1 }, 'fast' );
			}
		}
	});
}(jQuery, _));]]></file>
 <file javascript_app="calendar" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.monthView.js" javascript_type="controller" javascript_version="103009" javascript_position="1000250"><![CDATA[/**
 * Invision Community
 * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
 *
 * ips.browse.monthView.js - Month view controller
 *
 * Author: Rikki Tissier
 */
;( function($, _, undefined){
	"use strict";

	ips.controller.register('calendar.front.browse.monthView', {

		_emptyEvent: "<li class='cEvents_event cEvents_empty' data-eventid='0'><span></span></a></li>",

		initialize: function () {
			this.setup();
		},

		/**
		 * Setup method
		 *
		 * @returns 	{void}
		 */
		setup: function () {
			this._alignEvents();
		},


		_alignEvents: function () {
			// Lets start by getting all active days in the current calendar
			var days = this.scope.find('.cCalendar_date');
			var currentPositions = [];
			var self = this;

			_.each( days, function (day) {
				var day = $( day );
				var dayNumber = day.find('.cCalendar_dayNumber').text();
				var weekStart = false;

				if( day.closest('td').is('tr > td:first-child') ){
					weekStart = true;
				}

				// Get events for this day
				var events = day.find('.cEvents_ranged [data-eventID]');

				// If there's no events, we can skip this day
				if( !events.length ){
					currentPositions = [];
					return;
				}

				// Build a wrapper into which we'll move our events
				var wrapper = $("<ul/>").addClass('cEvents');
				var spaces = 0;
				
				// Now we loop over currentPositions (from the previous day), and try and arrange today's events
				// in the same order
				if( currentPositions.length ){
					var doneEvent = false;

					for( var i = 0; i < currentPositions.length; i++ ){	
						if( events.filter('[data-eventID="' + currentPositions[i] + '"]').length ){
							wrapper.append( events.filter('[data-eventID="' + currentPositions[i] + '"]') );
							doneEvent = true;
						} else {

							// If this is the first day of the week, we won't bother adding spacers unless we've already done an event today
							// This prevents lots of unnecessary spacers carrying over from the previous row
							if( !weekStart || doneEvent ){
								wrapper.append( self._emptyEvent );
								spaces++;
							}
						}
					}
				}

				var remainingEvents = day.find('.cEvents_ranged [data-eventID]');

				// If we have any remaining events, and there's gaps available, we can move those events into the gaps rather than
				// just putting them at the end
				if( spaces && remainingEvents.length ){
					var availableSpaces = wrapper.find('[data-eventID="0"]');

					// If we have a space and an event, move the event into that space
					for( var i = 0; i <= spaces; i++ ){
						if( remainingEvents[ i ] && availableSpaces[ i ] ){
							$( availableSpaces[ i ] ).replaceWith( $( remainingEvents[ i ] ) );
						}
					}

					// Update remaining events again
					remainingEvents = day.find('.cEvents_ranged [data-eventID]');
				}

				// Add in remaining events
				wrapper.append( remainingEvents );

				// Replace the existing wrapper with the new, correctly-ordered one
				day.find('.cEvents_ranged > .cEvents').replaceWith( wrapper );

				// Now we need to build a new currentPositions array for this day, so that the following
				// day can use it to do its thing
				currentPositions = [];

				_.each( day.find('.cEvents_ranged [data-eventID]'), function (event) {
					var eventID = parseInt( $( event ).attr('data-eventID') );

					if( eventID === 0 ){
						currentPositions.push('-');
					} else if( _.isNumber( eventID ) && !_.isNaN( eventID ) ){
						currentPositions.push( eventID );
					}
				});
			});

			// Now get all rows and cells to recalculate height
			_.each( this.scope.find('tr'), function (row) {

				// Don't bother if there's no birthdays in this row
				if( !$( row ).find('.cCalendar_birthdays').length ){
					return;
				}

				var cells = $( row ).find('td.cCalendar_date');
				var maxHeightCell = _.max( cells, function (cell) {
					return parseInt( $( cell ).height() );
				});

				if( !_.isElement( maxHeightCell ) ){
					return;
				}

				// Set the div height
				cells.find('> div').css({
					height: $( maxHeightCell ).height() + 20 + 'px'
				});
			});
		}
	});
}(jQuery, _));]]></file>
 <file javascript_app="calendar" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.dates.js" javascript_type="controller" javascript_version="103009" javascript_position="1000100"><![CDATA[/**
 * Invision Community
 * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
 *
 * ips.submit.dates.js - Helper for date selection enhancements
 *
 * Author: Rikki Tissier
 */
;( function($, _, undefined){
	"use strict";

	ips.controller.register('calendar.front.submit.dates', {

		initialize: function () {
			this._hasFocusedEventEnd = false;

			this.on( 'click', '[data-action="updateTimezone"]', this.updateTimezone );

			// Monitor focus in recurring event input fields and select appropriate radio button
			this.on( 'focus', 'input[name="repeat_end_occurrences"]', function(){ $('#event_repeat_end_afterx').prop('checked', true); } );
			this.on( 'focus', 'input[name="repeat_end_date"]', function(){ $('#event_repeat_end_ondate').prop('checked', true); } );
			
			this.on( 'change', 'input, select', this.checkForSummaryChange );
			this.on( 'change', '#check_single_day, #check_all_day', this.toggleFields );
			this.on( 'change', '#check_no_end_time', this.toggleEndtimeFields );
			this.on( 'click', '#elRecurRemove', this.disableRecurring );
			this.on( 'change', 'input[name="event_dates[start_date]"]', this.setEndDateOnStartChange );
			this.on( 'change', '#event_end_date', this.setHasFocusedEventOnEndChange );

			$( window ).on( 'resize', _.bind( this._resizeEndGrid, this ) );

			this.on( 'click', '[data-action="updateRepeat"]', this.finishRepeat );

			this._checkAndSetEventEndState();

			this.setup();
		},

		/**
		 * On page load check to see what the current state of the end date is. If its set lets just go ahead and ignore any start date changes
		 *
		 * @returns 	{void}
		 */
		_checkAndSetEventEndState: function() {
			var eventEndDate = $("#event_end_date");
			var date = eventEndDate.val();

			if (!this._hasFocusedEventEnd && this._isValidEndDate(date)) {
				this._hasFocusedEventEnd = true;
			}
		},

		/**
		 * Is the date passed in a valid date?
		 *
		 * @param		{date} 		date 	Date to check
		 * @returns 	{boolean}
		 */
		_isValidEndDate: function(date) {

			var tempDate = new Date(date);

			if(!isNaN(tempDate.getDate())) {
				return true;
			}

			return false;
		},

		/**
		 * If the end field has changed from input go ahead and ignore any start date changes
		 *
		 * @returns 	{void}
		 */
		setHasFocusedEventOnEndChange: function() {
			this._hasFocusedEventEnd = true;
		},

		/**
		 * Event handler, handles changes to the start date
		 *
		 * @returns 	{void}
		 */
		setEndDateOnStartChange: function() {
			var isSameDay = $("#check_single_day").is(":checked");
			var eventStartDate = $('input[name="event_dates[start_date]');
			var eventEndDate = $("#event_end_date");

			if(!isSameDay && !this._hasFocusedEventEnd) {
				if( ips.utils.time.supportsHTMLDate() ) {
					eventEndDate.val(eventStartDate.val());
				}
			}
		},

		/**
		 * Finish setting the options
		 *
		 * @returns 	{void}
		 */
		finishRepeat: function () {
			this._updateSummary();
			$('#elRecurEdit_menu').trigger('closeMenu');
		},

		/**
		 * Setup method
		 *
		 * @returns 	{void}
		 */
		setup: function () {
			this._updateSummary();
			this.toggleFields();
			this.updateTimezone();

			// Make Event End cell as big as Event Start cell
			this._resizeEndGrid();
		},

		/**
		 * Toggle the end time enabled/disabled status
		 *
		 * @param 		{event} 	e 		Event object
		 * @returns 	{void}
		 */
		 toggleEndtimeFields: function(e) {
		 	if( this.scope.find('#check_no_end_time').is(':checked') )
		 	{
		 		this.scope.find('#end_time').prop('disabled', true);
		 	}
		 	else
		 	{
		 		this.scope.find('#end_time').prop('disabled', false);
		 	}
		 },

		/**
		 * Manual toggle functionality for the Single/All Day checkboxes
		 *
		 * @param 		{event} 	e 		Event object
		 * @returns 	{void}
		 */
		toggleFields: function (e) {
			this.toggleEndtimeFields();

			var singleDay = this.scope.find('#check_single_day');
			var allDay = this.scope.find('#check_all_day');
			var self = this;

			var toggles = {
				start_time_wrap: true,
				end_time_wrap: true,
				event_end_date_wrap: true,
				elDateGrid_arrow: true,
				elDateGrid_end: true,
				end_date_controls: true
			};

			// Single day, not all day
			if( singleDay.is(':checked') && !allDay.is(':checked') ){
				toggles.event_end_date_wrap = false;
			// Single day, all day
			} else if( singleDay.is(':checked') && allDay.is(':checked') ){
				toggles.elDateGrid_arrow = false;
				toggles.elDateGrid_end = false;
				toggles.start_time_wrap = false;
			// Multiple days, all day
			} else if( !singleDay.is(':checked') && allDay.is(':checked') ){
				toggles.start_time_wrap = false;
				toggles.end_time_wrap = false;
				toggles.end_date_controls = false;
			}
			// Multiple days, not all day
			else
			{
				toggles.end_date_controls = false;
				this.scope.find('#end_time').prop('disabled', false);
			}

			// Hide appropriate elements
			_.each( toggles, function (val, key) {
				self.scope.find( '#' + key ).toggle( val );
			});

			// Manual check for ful;-width start date
			this.scope.find('#elDateGrid_start').toggleClass('ipsGrid_span5', this.scope.find('#elDateGrid_end').is(':visible') );
		},

		/**
		 * Monitor changes to the repeat options and update the summary
		 *
		 * @param 		{event} 	e 		Event object
		 * @param 		{object} 	data 	Event data object
		 * @returns 	{void}
		 */
		checkForSummaryChange: function (e) {
			if( $( e.currentTarget ).attr('name').startsWith('event_dates[') ){
				this._updateSummary();
			}
		},

		/**
		 * Updates the timezone value both in the hidden field and in the display to the end user
		 *
		 * @param 		{event} 	e 		Event object
		 * @returns 	{void}
		 */
		updateTimezone: function (e) {
			if( e ){
				e.preventDefault();
			}

			// Update displayed timezone
			this.scope.find('[data-role="timezone_display"]').text( $('#event_timezone option:selected').data('abbreviated') ).trigger('closeMenu');
		},

		/**
		 * Removes the Repeat summary and unchecks the Repeat checkbox
		 *
		 * @param 		{event} 	e 		Event object
		 * @param 		{object} 	data 	Event data object
		 * @returns 	{void}
		 */
		disableRecurring: function (e) {
			e.preventDefault();

			this.scope.find('#elRepeatCb').prop( 'checked', false  );
			this._updateSummary();
		},

		/**
		 * Finalize our recurring options
		 *
		 * @param 		{event} 	e 		Event object
		 * @param 		{object} 	data 	Event data object
		 * @returns 	{void}
		 */
		finishRepeatConfiguration: function (e, data) {
			e.preventDefault();

			// Copy the summary from the menu to the main display and close the menu
			this.scope.find('[data-role="recur_summary_final"]').text( this.scope.find('[data-role="recur_summary"]').text() );
			this.scope.find('#elRecurEdit').trigger('closeMenu');
		},

		/**
		 * Update the recurring string
		 *
		 * @param 		{event} 	e 		Event object
		 * @param 		{object} 	data 	Event data object
		 * @returns 	{void}
		 */
		_updateSummary: function () {
			var summary = this.scope.find('[data-role="recurringSummary"]');

			// Update repeating text
			if( this.scope.find('#elRepeatCb').is(':checked') ){
				summary.text( this._getSummary() );
				this.scope.find('#elRepeatRow_hidden').hide();
				this.scope.find('#elRepeatRow_shown').show();
			} else {
				summary.html( "<em class='ipsType_light'>" + ips.getString('doesnt_repeat') + "</em>" );
				this.scope.find('#elRepeatRow_hidden').show();
				this.scope.find('#elRepeatRow_shown').hide();
			}

			// Update the dates
			this.scope.find('[data-role="dateSummary"]').html( this._dateSummary() );
		},

		/**
		 * Builds a summary of the selected dates/times
		 *
		 * @returns 	{string}
		 */
		_dateSummary: function () {
			// Build start date
			var startDate = ips.utils.time.getDateFromInput( this.scope.find('input[name="event_dates[start_date]"]') );
			var singleDay = this.scope.find('#check_single_day');
			var allDay = this.scope.find('#check_all_day');

			// If there's no start time, then abandon showing any summary for now
			if( !ips.utils.time.isValidDateObj( startDate ) || startDate.getFullYear() < 1900 ) {
				return '';
			}		

			ips.utils.time.removeTimezone( startDate );

			var startDateString = ips.utils.time.localeDateString( startDate, { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric', timeZone: 'UTC' } );
			var startTime = this._getTime( this.scope.find('input[name="event_dates[start_time]"]').val() );
			var endTime = this._getTime( this.scope.find('input[name="event_dates[end_time]"]').val() );
			var endDate = ips.utils.time.getDateFromInput( this.scope.find('input[name="event_dates[end_date]"]') );
			var endDateString = '';

			// If we have a valid end date...
			if( !singleDay.is(':checked') && ips.utils.time.isValidDateObj( endDate ) ){
				ips.utils.time.removeTimezone( endDate );
				endDateString = ips.utils.time.localeDateString( endDate, { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric', timeZone: 'UTC' } );
			}

			// Now build strings
			var finalString = '';

			if( singleDay.is(':checked') && !allDay.is(':checked') ){
				if( this.scope.find('#check_no_end_time').is(':checked') )
				{
					finalString = ips.getString( 'single_not_allday_noendtime', { startDate: startDateString, startTime: startTime } );
				}
				else
				{
					finalString = ips.getString( 'single_not_allday', { startDate: startDateString, startTime: startTime, endTime: endTime } );
				}
			} else if ( ( !singleDay.is(':checked') && !allDay.is(':checked') ) && endDateString && startTime && endTime ) {
				finalString = ips.getString( 'not_single_not_allday', { startDate: startDateString, endDate: endDateString, startTime: startTime, endTime: endTime } );
			} else if( !singleDay.is(':checked') && allDay.is(':checked') && endDateString ) {
				finalString = ips.getString( 'not_single_allday', { startDate: startDateString, endDate: endDateString } );
			} else {
				finalString = ips.getString( 'single_allday', { startDate: startDateString } );
			}

			return finalString;
		},

		/**
		 * Returns the given time, or a placeholder string if empty
		 *
		 * @param 		{string} 	time 		Time string
		 * @returns 	{string}
		 */
		_getTime: function (time) {
			if( !time ){
				return "<em class='ipsType_light ipsType_unbold ipsFaded'>" + ips.getString('select_time') + "</em>";
			}

			return time;
		},

		/**
		 * Returns the summary string for recurring events
		 *
		 * @returns 	{string}
		 */
		_getSummary: function () {
			var type = this.scope.find('#elSelect_event_repeats').val();
			var intervalString = '';
			var endString = '';

			// Build the 'interval' string
			switch( type ){
				case 'daily':
				case 'monthly':
				case 'yearly':
					intervalString = this._buildString( type );
				break;
				case 'weekly':
					intervalString = this._buildWeekly();
				break;
			}

			// Build the 'end after' string
			if( this.scope.find('#event_repeat_end_afterx').is(':checked') ){
				var occurrences = parseInt( this.scope.find('input[name="event_dates[repeat_end_occurrences]"]').val() );

				if( _.isNumber( occurrences ) && !_.isNaN( occurrences ) ){
					endString = ips.pluralize( ips.getString( 'x_times' ), occurrences );				
				}
			} else if( this.scope.find('#event_repeat_end_ondate').is(':checked') ){
				var dateObj = ips.utils.time.getDateFromInput( this.scope.find('input[name="event_dates[repeat_end_date]"]') );

				if( ips.utils.time.isValidDateObj( dateObj ) && dateObj.getFullYear() > 1900 ){ // > 1900 just so it doesn't start updating on year 19 etc.
					endString = ips.getString('until', { date: ips.utils.time.localeDateString( dateObj, { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric' } ) } );
				}
			}

			// Put it together
			if( endString ){
				return ips.getString( 'with_end', { interval: intervalString, endAfter: endString } );
			} else {
				return intervalString;
			}
		},

		/**
		 * Builds a summary string for daily, monthly and yearly repeats
		 *
		 * @param 		{string} 	type 	The type of repeat
		 * @returns 	{string}
		 */
		_buildString: function ( type ) {
			var val = parseInt( this.scope.find('#elSelect_event_repeat_freq').val() ) || 1;
			return ips.pluralize( ips.getString( 'every_x', { period: ips.pluralize( ips.getString( 'x_' + type ), val ) } ), val );
		},

		/**
		 * Builds a summary string for weekly repeats
		 *
		 * @returns 	{string}
		 */
		_buildWeekly: function () {
			var selectedDays = this.scope.find('[data-iCal]:checked');
			var val = parseInt( this.scope.find('#elSelect_event_repeat_freq').val() ) || 1;
			var weekString = '';

			weekString = ips.pluralize( ips.getString( 'x_weekly' ), val );

			// If no days are selected, we can bypass and finish now
			if( !selectedDays.length ){
				return weekString;
			}

			// Get full days
			var fullDays = _.map( selectedDays, function (day, key) {
				return ips.getString( $( day ).attr('data-iCal') );
			});

			// Build string
			var dayString = '';

			if( fullDays.length === 1 ){
				dayString = ips.getString( 'one_day', { first: fullDays[0] } );
			} else {
				dayString = ips.getString( 'multiple_day', { days: fullDays.slice(0, -1).join(', '), last: fullDays[ fullDays.length - 1 ] });
			}

			return ips.getString( 'week_string', { week: weekString, days: dayString } );
		},

		/**
		 * Resizes the "Event End" grid box to be the same height as the start box
		 *
		 * @returns 	{void}
		 */
		_resizeEndGrid: function () {
			var height = 'auto';

			if( !ips.utils.responsive.enabled() || !ips.utils.responsive.currentIs('phone') ){
				height = this.scope.find('#elDateGrid_start').outerHeight() + 'px';
			}

			this.scope.find('#elDateGrid_end').css({
				height: height
			});
		}
	});
}(jQuery, _));]]></file>
 <file javascript_app="calendar" javascript_location="front" javascript_path="controllers/venue" javascript_name="ips.venue.main.js" javascript_type="controller" javascript_version="103009" javascript_position="1000200"><![CDATA[/**
 * Invision Community
 * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
 *
 * ips.venue.main.js - Venue main browsing controller
 *
 */
;( function($, _, undefined){
	"use strict";

	ips.controller.register('calendar.front.venue.main', {

		_ajaxObj: null,
		
		initialize: function () {
			this.on( 'click', '[data-action="changeView"]', this.changeView );
			this.on( window, 'statechange', this.stateChange );
			this.setup();
		},

		/**
		 * Controller setup method
		 *
		 * @returns {void}
		 */
		setup: function () {
			History.pushState( { controller: 'venueView' }, document.title, window.location.href );
		},

		/**
		 * Changes the calendar view dynamically
		 *
		 * @param 	{event} 	e 	Event object
		 * @returns {void}
		 */
		changeView: function (e) {
			e.preventDefault();

			// Load the url via ajax instead
			var self = this;
			var title = $( e.currentTarget ).attr('title');
			var url = $( e.currentTarget ).attr('href');

			History.pushState( { controller: 'venueView' }, title, url );
		},

		/**
		 * Event handler for history state changes
		 *
		 * @param 	{event} 	e 	Event object
		 * @returns {void}
		 */
		stateChange: function () {
			var state = History.getState();

			if( _.isUndefined( state.data.controller ) || state.data.controller != 'venueView' ) {
				return;
			}

			// Track page view
			ips.utils.analytics.trackPageView( state.url );

			this._updateView( state.url, state.title )
		},

		/**
		 * Loads a new view 
		 *
		 * @param 	{string} 	url 	URL to load
		 * @param 	{string} 	title 	New browser title
		 * @returns {void}
		 */
		_updateView: function (url, title) {
			var self = this;

			if( this._ajaxObj && _.isFunction( this._ajaxObj.abort ) ){
				this._ajaxObj.abort();
			}

			this._setLoading( true );

			this._ajaxObj = ips.getAjax()( url, {
				showLoading: true
			} )
				.done( function (response) {
					console.log( response );
					self.scope.html( response );

					$( document ).trigger( 'contentChange', [ self.scope ] );

					History.pushState( { controller: 'venueView' }, title, url );
				})
				.always( function () {
					self._setLoading( false );
				});
		},

		/**
		 * Toggles the loading state on the view
		 *
		 * @param 	{boolean} 	state 		Enable the loading state?
		 * @returns {void}
		 */
		_setLoading: function (state) {
			if( state ){
				this.scope.animate( { opacity: 0.6 }, 'fast' );
			} else {
				this.scope.animate( { opacity: 1 }, 'fast' );
			}
		}
	});
}(jQuery, _));]]></file>
 <file javascript_app="calendar" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.reminderButton.js" javascript_type="controller" javascript_version="103009" javascript_position="1000150"><![CDATA[/**
 * Invision Community
 * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
 *
 * ips.calendar.reminderButton.js - Controller for event reminder button
 *
 * Author: Andrew Millne
 */
;( function($, _, undefined){
	"use strict";

	ips.controller.register('calendar.front.view.reminderButton', {

		initialize: function () {
			this.setup();
			this.on( document, 'reminderItem', this.reminderItemChange );
		},

		setup: function () {
			this._id = this.scope.attr('data-reminderID');
			this._button = this.scope.find('[data-role="reminderButton"]');
		},

		/**
		 * Responds to events indicating the reminder status has changed
		 *
		 * @param 		{event} 	e 		Event object
		 * @param 		{object} 	data 	Event data object
		 * @returns 	{void}
		 */
		reminderItemChange: function (e, data) {
			this._reloadButton();
		},

		/**
		 * Gets a new reminder button from the server and replaces the current one with the response
		 *
		 * @returns 	{void}
		 */
		_reloadButton: function () {
			// Show button as loading
			this._button.addClass('ipsFaded ipsFaded_more');
			
			var self = this;
			var pos = ips.utils.position.getElemPosition( this._button );
			var dims = ips.utils.position.getElemDims( this._button );

			this.scope.append( ips.templates.render('calendar.reminder.loading') );

			// Adjust sizing
			this.scope
				.css({
					position: 'relative'
				})
				.find('.ipsLoading')
					.css({
						width: dims.outerWidth + 'px',
						height: dims.outerHeight + 'px',
						top: 0,
						left: 0,
						position: 'absolute',
						zIndex: ips.ui.zIndex()
					});

			// Load new contents
			ips.getAjax()( ips.getSetting('baseURL') + 'index.php?app=calendar&module=calendar&controller=event&do=reminderButton', {
				data: _.extend({
					id: this._id
				}, ( this.scope.attr('data-buttonType') ) ? { button_type: this.scope.attr('data-buttonType') } : {} )
			})
				.done( function (response) {
					self.scope.html( response );
					$( document ).trigger( 'contentChange', [ self.scope ] );
				})
				.fail( function () {
					self._button.removeClass('ipsFaded ipsFaded_more');
				})
				.always( function () {
					self.scope.find('.ipsLoading').remove();
				});
		}
	});
}(jQuery, _));]]></file>
 <file javascript_app="calendar" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.reminderForm.js" javascript_type="controller" javascript_version="103009" javascript_position="1000150">/**
 * Invision Community
 * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
 *
 * ips.calendar.reminderButton.js - Controller for reminder button
 *
 * Author: Andrew Millne
 */
;( function($, _, undefined){
	&quot;use strict&quot;;

	ips.controller.register('calendar.front.view.reminderForm', {

		initialize: function () {
			this.on( 'submit', this.submitForm );
			this.on( 'click', '[data-action=&quot;removereminder&quot;]', this.removereminder );
			this.setup();
		},

		/**
		 * Setup method
		 *
		 * @returns 	{void}
		 */
		setup: function () {
		},

		/**
		 * Event handler for removing reminder
		 *
		 * @param 		{event} 	e 		Event object
		 * @returns 	{void}
		 */
		removereminder: function (e) {
			e.preventDefault();
			this._doRemindAction( $( e.currentTarget ).attr('href'), {}, true );
		},

		/**
		 * Event handler for submitting the reminder form
		 *
		 * @param 		{event} 	e 		Event object
		 * @returns 	{void}
		 */
		submitForm: function (e) {
			e.preventDefault();
			this._doRemindAction( this.scope.attr('action'), this.scope.serialize(), false );
		},

		/**
		 * Performs an ajax action.
		 *
		 * @param 		{string} 	url		URL to call
		 * @param 		{object} 	data 	Object of data to include in the request
		 * @returns 	{void}
		 */
		_doRemindAction: function (url, data, removereminder ) {
			var self = this;
			var dims = ips.utils.position.getElemDims( this.scope.parent('div') );

			// Set it to loading
			this.scope
				.hide()
				.parent('div')
					.css({
						width: dims.outerWidth + 'px',
						height: dims.outerHeight + 'px'
					})
					.addClass('ipsLoading');

			// Update reminder preference via ajax
			ips.getAjax()( url, {
				data: data,
				type: 'post'
			})
				.done( function (response, status, jqXHR) {

					if( jqXHR.getAllResponseHeaders().indexOf('X-IPS-FormError: true') !== -1 || jqXHR.getAllResponseHeaders().indexOf('X-IPS-FormNoSubmit: true') !== -1 || jqXHR.getAllResponseHeaders().indexOf('x-ips-formerror: true') !== -1 || jqXHR.getAllResponseHeaders().indexOf('x-ips-formnosubmit: true') !== -1 ){
						self.scope
							.show()
							.html( response )
							.parent('div')
								.removeClass('ipsLoading')
								.css({
									width: 'auto',
									height: 'auto'
								});
					} else {
						// Success, so trigger event to update button
						self.trigger('reminderItem');
						if( removereminder ) {
							ips.ui.flashMsg.show(ips.getString('event_reminder_removed'));
						}
						else {
							ips.ui.flashMsg.show(ips.getString('event_reminder_added'));
						}

						self.scope.parents('.ipsHovercard').remove();
					}
				})
				.fail( function (jqXHR, textStatus, errorThrown) {
					window.location = url;
				})
				.always( function () {
					// If we're in a hovercard, remove it					
				});
		}
	});
}(jQuery, _));
</file>
 <file javascript_app="calendar" javascript_location="front" javascript_path="templates" javascript_name="ips.calendar.templates.js" javascript_type="framework" javascript_version="103009" javascript_position="1000050"><![CDATA[/**
 * Invision Community
 * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
 */

/* REMINDER BUTTON LOADING */
ips.templates.set('calendar.reminder.loading', " \
<div class='ipsLoading ipsLoading_tiny'></div>\
");]]></file>
 <order app="global" path="/dev/js//framework/">templates
common/ips.loader.js
common/ui
common/utils
common
controllers</order>
 <order app="global" path="/dev/js//library/">underscore
jquery
mustache
jstz
Debug.js
app.js</order>
 <order app="global" path="/dev/js//library//jquery">jquery.js
jquery.history.js
jquery.transform.js</order>
 <order app="global" path="/dev/js//library//linkify">linkify.min.js
linkify-jquery.min.js</order>
</javascript>
