/* !
Waypoints - 4.0.1
Copyright © 2011-2016 Caleb Troughton
Licensed under the MIT license.
https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
*/
( function () {
	'use strict';

	var keyCounter = 0;
	var allWaypoints = {};


	/* http://imakewebthings.com/waypoints/api/waypoint */
	function VcWaypoint ( options ) {
		if ( !options ) {
			throw new Error( 'No options passed to Waypoint constructor' );
		}
		if ( !options.element ) {
			throw new Error( 'No element option passed to Waypoint constructor' );
		}
		if ( !options.handler ) {
			throw new Error( 'No handler option passed to Waypoint constructor' );
		}

		this.key = 'waypoint-' + keyCounter;
		this.options = VcWaypoint.Adapter.extend({}, VcWaypoint.defaults, options );
		this.element = this.options.element;
		this.adapter = new VcWaypoint.Adapter( this.element );
		this.callback = options.handler;
		this.axis = this.options.horizontal ? 'horizontal' : 'vertical';
		this.enabled = this.options.enabled;
		this.triggerPoint = null;
		this.group = VcWaypoint.Group.findOrCreate({
			name: this.options.group,
			axis: this.axis
		});
		this.context = VcWaypoint.Context.findOrCreateByElement( this.options.context );

		if ( VcWaypoint.offsetAliases[ this.options.offset ]) {
			this.options.offset = VcWaypoint.offsetAliases[ this.options.offset ];
		}
		this.group.add( this );
		this.context.add( this );
		allWaypoints[ this.key ] = this;
		keyCounter += 1;
	}

	/* Private */
	VcWaypoint.prototype.queueTrigger = function ( direction ) {
		this.group.queueTrigger( this, direction );
	};

	/* Private */
	VcWaypoint.prototype.trigger = function ( args ) {
		if ( !this.enabled ) {
			return;
		}
		if ( this.callback ) {
			this.callback.apply( this, args );
		}
	};

	/* Public */
	/* http://imakewebthings.com/waypoints/api/destroy */
	VcWaypoint.prototype.destroy = function () {
		this.context.remove( this );
		this.group.remove( this );
		delete allWaypoints[ this.key ];
	};

	/* Public */
	/* http://imakewebthings.com/waypoints/api/disable */
	VcWaypoint.prototype.disable = function () {
		this.enabled = false;
		return this;
	};

	/* Public */
	/* http://imakewebthings.com/waypoints/api/enable */
	VcWaypoint.prototype.enable = function () {
		this.context.refresh();
		this.enabled = true;
		return this;
	};

	/* Public */
	/* http://imakewebthings.com/waypoints/api/next */
	VcWaypoint.prototype.next = function () {
		return this.group.next( this );
	};

	/* Public */
	/* http://imakewebthings.com/waypoints/api/previous */
	VcWaypoint.prototype.previous = function () {
		return this.group.previous( this );
	};

	/* Private */
	VcWaypoint.invokeAll = function ( method ) {
		var allWaypointsArray = [];
		for ( var waypointKey in allWaypoints ) {
			allWaypointsArray.push( allWaypoints[ waypointKey ]);
		}
		for ( var i = 0, end = allWaypointsArray.length; i < end; i ++ ) {
			allWaypointsArray[ i ][ method ]();
		}
	};

	/* Public */
	/* http://imakewebthings.com/waypoints/api/destroy-all */
	VcWaypoint.destroyAll = function () {
		VcWaypoint.invokeAll( 'destroy' );
	};

	/* Public */
	/* http://imakewebthings.com/waypoints/api/disable-all */
	VcWaypoint.disableAll = function () {
		VcWaypoint.invokeAll( 'disable' );
	};

	/* Public */
	/* http://imakewebthings.com/waypoints/api/enable-all */
	VcWaypoint.enableAll = function () {
		VcWaypoint.Context.refreshAll();
		for ( var waypointKey in allWaypoints ) {
			allWaypoints[ waypointKey ].enabled = true;
		}
		return this;
	};

	/* Public */
	/* http://imakewebthings.com/waypoints/api/refresh-all */
	VcWaypoint.refreshAll = function () {
		VcWaypoint.Context.refreshAll();
	};

	/* Public */
	/* http://imakewebthings.com/waypoints/api/viewport-height */
	VcWaypoint.viewportHeight = function () {
		return window.innerHeight || document.documentElement.clientHeight;
	};

	/* Public */
	/* http://imakewebthings.com/waypoints/api/viewport-width */
	VcWaypoint.viewportWidth = function () {
		return document.documentElement.clientWidth;
	};

	VcWaypoint.adapters = [];

	VcWaypoint.defaults = {
		context: window,
		continuous: true,
		enabled: true,
		group: 'default',
		horizontal: false,
		offset: 0
	};

	VcWaypoint.offsetAliases = {
		'bottom-in-view': function () {
			return this.context.innerHeight() - this.adapter.outerHeight();
		},
		'right-in-view': function () {
			return this.context.innerWidth() - this.adapter.outerWidth();
		}
	};

	window.VcWaypoint = VcWaypoint;
}() )
;( function () {
	'use strict';

	function requestAnimationFrameShim ( callback ) {
		window.setTimeout( callback, 1000 / 60 );
	}

	var keyCounter = 0;
	var contexts = {};
	var VcWaypoint = window.VcWaypoint;
	var oldWindowLoad = window.onload;

	/* http://imakewebthings.com/waypoints/api/context */
	function Context ( element ) {
		this.element = element;
		this.Adapter = VcWaypoint.Adapter;
		this.adapter = new this.Adapter( element );
		this.key = 'waypoint-context-' + keyCounter;
		this.didScroll = false;
		this.didResize = false;
		this.oldScroll = {
			x: this.adapter.scrollLeft(),
			y: this.adapter.scrollTop()
		};
		this.waypoints = {
			vertical: {},
			horizontal: {}
		};

		element.waypointContextKey = this.key;
		contexts[ element.waypointContextKey ] = this;
		keyCounter += 1;
		if ( !VcWaypoint.windowContext ) {
			VcWaypoint.windowContext = true;
			VcWaypoint.windowContext = new Context( window );
		}

		this.createThrottledScrollHandler();
		this.createThrottledResizeHandler();
	}

	/* Private */
	Context.prototype.add = function ( waypoint ) {
		var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical';
		this.waypoints[ axis ][ waypoint.key ] = waypoint;
		this.refresh();
	};

	/* Private */
	Context.prototype.checkEmpty = function () {
		var horizontalEmpty = this.Adapter.isEmptyObject( this.waypoints.horizontal );
		var verticalEmpty = this.Adapter.isEmptyObject( this.waypoints.vertical );
		var isWindow = this.element == this.element.window;
		if ( horizontalEmpty && verticalEmpty && !isWindow ) {
			this.adapter.off( '.vcwaypoints' );
			delete contexts[ this.key ];
		}
	};

	/* Private */
	Context.prototype.createThrottledResizeHandler = function () {
		var self = this;

		function resizeHandler () {
			self.handleResize();
			self.didResize = false;
		}

		this.adapter.on( 'resize.vcwaypoints', function () {
			if ( !self.didResize ) {
				self.didResize = true;
				VcWaypoint.requestAnimationFrame( resizeHandler );
			}
		});
	};

	/* Private */
	Context.prototype.createThrottledScrollHandler = function () {
		var self = this;

		function scrollHandler () {
			self.handleScroll();
			self.didScroll = false;
		}

		this.adapter.on( 'scroll.vcwaypoints', function () {
			if ( !self.didScroll || VcWaypoint.isTouch ) {
				self.didScroll = true;
				VcWaypoint.requestAnimationFrame( scrollHandler );
			}
		});
	};

	/* Private */
	Context.prototype.handleResize = function () {
		VcWaypoint.Context.refreshAll();
	};

	/* Private */
	Context.prototype.handleScroll = function () {
		var triggeredGroups = {};
		var axes = {
			horizontal: {
				newScroll: this.adapter.scrollLeft(),
				oldScroll: this.oldScroll.x,
				forward: 'right',
				backward: 'left'
			},
			vertical: {
				newScroll: this.adapter.scrollTop(),
				oldScroll: this.oldScroll.y,
				forward: 'down',
				backward: 'up'
			}
		};

		for ( var axisKey in axes ) {
			var axis = axes[ axisKey ];
			var isForward = axis.newScroll > axis.oldScroll;
			var direction = isForward ? axis.forward : axis.backward;

			for ( var waypointKey in this.waypoints[ axisKey ]) {
				var waypoint = this.waypoints[ axisKey ][ waypointKey ];
				if ( waypoint.triggerPoint === null ) {
					continue;
				}
				var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint;
				var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint;
				var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint;
				var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint;
				if ( crossedForward || crossedBackward ) {
					waypoint.queueTrigger( direction );
					triggeredGroups[ waypoint.group.id ] = waypoint.group;
				}
			}
		}

		for ( var groupKey in triggeredGroups ) {
			triggeredGroups[ groupKey ].flushTriggers();
		}

		this.oldScroll = {
			x: axes.horizontal.newScroll,
			y: axes.vertical.newScroll
		};
	};

	/* Private */
	Context.prototype.innerHeight = function () {

		if ( this.element == this.element.window ) {
			return VcWaypoint.viewportHeight();
		}

		return this.adapter.innerHeight();
	};

	/* Private */
	Context.prototype.remove = function ( waypoint ) {
		delete this.waypoints[ waypoint.axis ][ waypoint.key ];
		this.checkEmpty();
	};

	/* Private */
	Context.prototype.innerWidth = function () {

		if ( this.element == this.element.window ) {
			return VcWaypoint.viewportWidth();
		}

		return this.adapter.innerWidth();
	};

	/* Public */
	/* http://imakewebthings.com/waypoints/api/context-destroy */
	Context.prototype.destroy = function () {
		var allWaypoints = [];
		for ( var axis in this.waypoints ) {
			for ( var waypointKey in this.waypoints[ axis ]) {
				allWaypoints.push( this.waypoints[ axis ][ waypointKey ]);
			}
		}
		for ( var i = 0, end = allWaypoints.length; i < end; i ++ ) {
			allWaypoints[ i ].destroy();
		}
	};

	/* Public */
	/* http://imakewebthings.com/waypoints/api/context-refresh */
	Context.prototype.refresh = function () {

		var isWindow = this.element == this.element.window;

		var contextOffset = isWindow ? undefined : this.adapter.offset();
		var triggeredGroups = {};
		var axes;

		this.handleScroll();
		axes = {
			horizontal: {
				contextOffset: isWindow ? 0 : contextOffset.left,
				contextScroll: isWindow ? 0 : this.oldScroll.x,
				contextDimension: this.innerWidth(),
				oldScroll: this.oldScroll.x,
				forward: 'right',
				backward: 'left',
				offsetProp: 'left'
			},
			vertical: {
				contextOffset: isWindow ? 0 : contextOffset.top,
				contextScroll: isWindow ? 0 : this.oldScroll.y,
				contextDimension: this.innerHeight(),
				oldScroll: this.oldScroll.y,
				forward: 'down',
				backward: 'up',
				offsetProp: 'top'
			}
		};

		for ( var axisKey in axes ) {
			var axis = axes[ axisKey ];
			for ( var waypointKey in this.waypoints[ axisKey ]) {
				var waypoint = this.waypoints[ axisKey ][ waypointKey ];
				var adjustment = waypoint.options.offset;
				var oldTriggerPoint = waypoint.triggerPoint;
				var elementOffset = 0;
				var freshWaypoint = oldTriggerPoint == null;
				var contextModifier, wasBeforeScroll, nowAfterScroll;
				var triggeredBackward, triggeredForward;

				if ( waypoint.element !== waypoint.element.window ) {
					elementOffset = waypoint.adapter.offset()[ axis.offsetProp ];
				}

				if ( typeof adjustment === 'function' ) {
					adjustment = adjustment.apply( waypoint );
				} else if ( typeof adjustment === 'string' ) {
					adjustment = parseFloat( adjustment );
					if ( waypoint.options.offset.indexOf( '%' ) > - 1 ) {
						adjustment = Math.ceil( axis.contextDimension * adjustment / 100 );
					}
				}

				contextModifier = axis.contextScroll - axis.contextOffset;
				waypoint.triggerPoint = Math.floor( elementOffset + contextModifier - adjustment );
				wasBeforeScroll = oldTriggerPoint < axis.oldScroll;
				nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll;
				triggeredBackward = wasBeforeScroll && nowAfterScroll;
				triggeredForward = !wasBeforeScroll && !nowAfterScroll;

				if ( !freshWaypoint && triggeredBackward ) {
					waypoint.queueTrigger( axis.backward );
					triggeredGroups[ waypoint.group.id ] = waypoint.group;
				} else if ( !freshWaypoint && triggeredForward ) {
					waypoint.queueTrigger( axis.forward );
					triggeredGroups[ waypoint.group.id ] = waypoint.group;
				} else if ( freshWaypoint && axis.oldScroll >= waypoint.triggerPoint ) {
					waypoint.queueTrigger( axis.forward );
					triggeredGroups[ waypoint.group.id ] = waypoint.group;
				}
			}
		}

		VcWaypoint.requestAnimationFrame( function () {
			for ( var groupKey in triggeredGroups ) {
				triggeredGroups[ groupKey ].flushTriggers();
			}
		});

		return this;
	};

	/* Private */
	Context.findOrCreateByElement = function ( element ) {
		return Context.findByElement( element ) || new Context( element );
	};

	/* Private */
	Context.refreshAll = function () {
		for ( var contextId in contexts ) {
			contexts[ contextId ].refresh();
		}
	};

	/* Public */
	/* http://imakewebthings.com/waypoints/api/context-find-by-element */
	Context.findByElement = function ( element ) {
		return contexts[ element.waypointContextKey ];
	};

	window.onload = function () {
		if ( oldWindowLoad ) {
			oldWindowLoad();
		}
		Context.refreshAll();
	};

	VcWaypoint.requestAnimationFrame = function ( callback ) {
		var requestFn = window.requestAnimationFrame ||
			window.mozRequestAnimationFrame ||
			window.webkitRequestAnimationFrame ||
			requestAnimationFrameShim;
		requestFn.call( window, callback );
	};
	VcWaypoint.Context = Context;
}() )
;( function () {
	'use strict';

	function byTriggerPoint ( a, b ) {
		return a.triggerPoint - b.triggerPoint;
	}

	function byReverseTriggerPoint ( a, b ) {
		return b.triggerPoint - a.triggerPoint;
	}

	var groups = {
		vertical: {},
		horizontal: {}
	};
	var VcWaypoint = window.VcWaypoint;

	/* http://imakewebthings.com/waypoints/api/group */
	function Group ( options ) {
		this.name = options.name;
		this.axis = options.axis;
		this.id = this.name + '-' + this.axis;
		this.waypoints = [];
		this.clearTriggerQueues();
		groups[ this.axis ][ this.name ] = this;
	}

	/* Private */
	Group.prototype.add = function ( waypoint ) {
		this.waypoints.push( waypoint );
	};

	/* Private */
	Group.prototype.clearTriggerQueues = function () {
		this.triggerQueues = {
			up: [],
			down: [],
			left: [],
			right: []
		};
	};

	/* Private */
	Group.prototype.flushTriggers = function () {
		for ( var direction in this.triggerQueues ) {
			var waypoints = this.triggerQueues[ direction ];
			var reverse = direction === 'up' || direction === 'left';
			waypoints.sort( reverse ? byReverseTriggerPoint : byTriggerPoint );
			for ( var i = 0, end = waypoints.length; i < end; i += 1 ) {
				var waypoint = waypoints[ i ];
				if ( waypoint.options.continuous || i === waypoints.length - 1 ) {
					waypoint.trigger([ direction ]);
				}
			}
		}
		this.clearTriggerQueues();
	};

	/* Private */
	Group.prototype.next = function ( waypoint ) {
		this.waypoints.sort( byTriggerPoint );
		var index = VcWaypoint.Adapter.inArray( waypoint, this.waypoints );
		var isLast = index === this.waypoints.length - 1;
		return isLast ? null : this.waypoints[ index + 1 ];
	};

	/* Private */
	Group.prototype.previous = function ( waypoint ) {
		this.waypoints.sort( byTriggerPoint );
		var index = VcWaypoint.Adapter.inArray( waypoint, this.waypoints );
		return index ? this.waypoints[ index - 1 ] : null;
	};

	/* Private */
	Group.prototype.queueTrigger = function ( waypoint, direction ) {
		this.triggerQueues[ direction ].push( waypoint );
	};

	/* Private */
	Group.prototype.remove = function ( waypoint ) {
		var index = VcWaypoint.Adapter.inArray( waypoint, this.waypoints );
		if ( index > - 1 ) {
			this.waypoints.splice( index, 1 );
		}
	};

	/* Public */
	/* http://imakewebthings.com/waypoints/api/first */
	Group.prototype.first = function () {
		return this.waypoints[ 0 ];
	};

	/* Public */
	/* http://imakewebthings.com/waypoints/api/last */
	Group.prototype.last = function () {
		return this.waypoints[ this.waypoints.length - 1 ];
	};

	/* Private */
	Group.findOrCreate = function ( options ) {
		return groups[ options.axis ][ options.name ] || new Group( options );
	};

	VcWaypoint.Group = Group;
}() )
;( function () {
	'use strict';

	var $ = window.jQuery;
	var VcWaypoint = window.VcWaypoint;

	function JQueryAdapter ( element ) {
		this.$element = $( element );
	}

	$.each([
		'innerHeight',
		'innerWidth',
		'off',
		'offset',
		'on',
		'outerHeight',
		'outerWidth',
		'scrollLeft',
		'scrollTop'
	], function ( i, method ) {
		JQueryAdapter.prototype[ method ] = function () {
			var args = Array.prototype.slice.call( arguments );
			return this.$element[ method ].apply( this.$element, args );
		};
	});

	$.each([
		'extend',
		'inArray',
		'isEmptyObject'
	], function ( i, method ) {
		JQueryAdapter[ method ] = $[ method ];
	});

	VcWaypoint.adapters.push({
		name: 'jquery',
		Adapter: JQueryAdapter
	});
	VcWaypoint.Adapter = JQueryAdapter;
}() )
;( function () {
	'use strict';

	var VcWaypoint = window.VcWaypoint;

	function createExtension ( framework ) {
		return function () {
			var waypoints = [];
			var overrides = arguments[ 0 ];

			if ( framework.isFunction( arguments[ 0 ]) ) {
				overrides = framework.extend({}, arguments[ 1 ]);
				overrides.handler = arguments[ 0 ];
			}

			this.each( function () {
				var options = framework.extend({}, overrides, {
					element: this
				});
				if ( typeof options.context === 'string' ) {
					options.context = framework( this ).closest( options.context )[ 0 ];
				}
				waypoints.push( new VcWaypoint( options ) );
			});

			return waypoints;
		};
	}

	if ( window.jQuery ) {
		window.jQuery.fn.vcwaypoint = createExtension( window.jQuery );
	}
	if ( window.Zepto ) {
		window.Zepto.fn.vcwaypoint = createExtension( window.Zepto );
	}
}() )
;
