jQuery(function($){
window.get_breakpoint_ie8 = function(width) {
if(width >= 1080) {
return 'desktop';
}
if(width >= 570 && width <= 1079) {
return 'tablet';
}
if(width >= 0 && width <= 569) {
return 'mobile';
}
}
});
/* upfront-layout */
jQuery(document).ready(function($){
	var throttle = function(a,b,c){var d,e,f,g=null,h=0;c||(c={});var i=function(){h=c.leading===!1?0:new Date().getTime(),g=null,f=a.apply(d,e),g||(d=e=null)};return function(){var j=new Date().getTime();h||c.leading!==!1||(h=j);var k=b-(j-h);return d=this,e=arguments,0>=k||k>b?(clearTimeout(g),g=null,h=j,f=a.apply(d,e),g||(d=e=null)):g||c.trailing===!1||(g=setTimeout(i,k)),f}};
	var lastKey = new Date();
	var lastClick = new Date();
	
	function css_support( property )
	{
		var div = document.createElement('div'),
		    reg = new RegExp("(khtml|moz|ms|webkit|)"+property, "i");
		for ( s in div.style ) {
			if ( s.match(reg) )
				return true;
		}
		return false;
	}

	var previous_breakpoint = '';
	var current_breakpoint = '';
	function get_breakpoint(){
		if (!window.getComputedStyle) {
				window.getComputedStyle = function(el, pseudo) {
				this.el = el;
				this.getPropertyValue = function(prop) {
					var re = /(\-([a-z]){1})/g;
					if (prop == 'float') prop = 'styleFloat';
					if (re.test(prop)) {
						prop = prop.replace(re, function () {
							return arguments[2].toUpperCase();
						});
					}
					return el.currentStyle[prop] ? el.currentStyle[prop] : null;
				}
				return this;
			}
		}
		var breakpoint = window.getComputedStyle(document.body,':after').getPropertyValue('content');

		if(breakpoint === null && $('html').hasClass('ie8')) {
			breakpoint = window.get_breakpoint_ie8($( window ).width());
			$(window).trigger('resize');
		}

		if(breakpoint) {
			breakpoint = breakpoint.replace(/['"]/g, '')
			if (current_breakpoint != breakpoint) {
				previous_breakpoint = current_breakpoint;
				current_breakpoint = breakpoint;
			}
			return breakpoint;
		}
	}
	window.upfront_get_breakpoint = get_breakpoint; // Expose to global

	/**
	 * Get the previously used breakpoint
	 *
	 * @return {String} Previous breakpoint
	 */
	function get_previous_breakpoint () {
		get_breakpoint();
		return previous_breakpoint;
	}
	window.upfront_get_previous_breakpoint = get_previous_breakpoint; // Expose to global

	/* Youtube API */
	var youtube_api_loaded = false;
	var youtube_api_ready = false;
	var youtube_player_ids = [];

	function change_youtube_video (id, type) {
		youtube_player_ids.push(id);
		if ( !youtube_api_loaded ){
			var tag = document.createElement('script');
			tag.src = "https://www.youtube.com/iframe_api";
			var firstScriptTag = document.getElementsByTagName('script')[0];
			firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
			window.onYouTubeIframeAPIReady = function () {
				youtube_api_ready = true;
				create_youtube_players(type);
			}
			youtube_api_loaded = true;
			return;
		}
		if ( youtube_api_ready ) {
			create_youtube_players(type);
		}
	}

	function create_youtube_players (type) {
		for ( var i = 0; i < youtube_player_ids.length; i++ )
			// Only Loop video.
			if (type === 'loop') {
				var player = new YT.Player(youtube_player_ids[i], {
					events: {
						'onReady': on_loop_youtube_ready
					}
				});
			} else if (type === 'loopAndMute') {
				// Loop and mute video.
				var player = new YT.Player(youtube_player_ids[i], {
					events: {
						'onReady': function(e) {
							on_loop_youtube_ready(e);
							on_mute_youtube_ready(e);
						}
					}
				});
			// Only mute:
			} else {
				var player = new YT.Player(youtube_player_ids[i], {
					events: {
						'onReady': on_mute_youtube_ready
					}
				});
			}
		youtube_player_ids = [];
	}

	function on_mute_youtube_ready (event) {
		return event.target.mute();
	}

	function on_loop_youtube_ready (event) {
		var time, duration;
		return setInterval(function(){
			time = event.target.getCurrentTime();
			duration = event.target.getDuration();
			if(time > duration - 0.5) {
				event.target.seekTo(0);
				event.target.playVideo();
			}
		}, 200);
	}

	/* Vimeo API */
	var vimeo_listened  = false;
	function mute_vimeo_video (id) {
		if ( !vimeo_listened ) {
			if (window.addEventListener)
				window.addEventListener('message', on_vimeo_message, false);
			else
				window.attachEvent('onmessage', on_vimeo_message, false);
			vimeo_listened = true;
		}
	}

	function on_vimeo_message (e) {
		if ( !e.origin.match(/vimeo\./) )
			return;
		var data = JSON.parse(e.data);
		if ( data.event == 'ready' ) {
			var player = $('#'+data.player_id),
				url = player.attr('src').split('?'),
				data = {
					method: 'setVolume',
					value: 0
				};
			player[0].contentWindow.postMessage(data, url);
		}
	}


	/* Responsive background */
	var windowWidth = $(window).width();
	var initialUpdateBackgroundDone = false;
	function update_background () {
		var newWindowWidth = $(window).width();
		// Update background only on width change, do initial update always
		if (initialUpdateBackgroundDone && windowWidth === newWindowWidth) {
			return;
		}
		initialUpdateBackgroundDone = true;
		windowWidth = newWindowWidth;

		var breakpoint = get_breakpoint();
		breakpoint = !breakpoint ? 'desktop' : breakpoint;
		$('[data-bg-type-'+breakpoint+']').each(function(){
			var type = $(this).attr('data-bg-type-'+breakpoint),
				$overlay = $(this).find('> .upfront-output-bg-'+breakpoint)
			;
			$(this).find('> .upfront-output-bg-overlay').not($overlay).each(function(){
				if ( $(this).is('.upfront-output-bg-video') ) {
					$(this).children().not('script.video-embed-code').remove();
				}
				if ( $(this).attr('data-bg-parallax') && $(this).data('uparallax') ) {
					$(this).uparallax('destroy');
				}
			});
			if ( $overlay.attr('data-bg-parallax') ) {
				setTimeout(function () { // Zero timeout to shift it out
					var $container = $overlay.closest('.upfront-output-region-container');
					if ( $container.length ) {
						var $next = $container.next('.upfront-output-region-container'),
							$next_bg = $next.find('.upfront-region-container-bg'),
							$prev = $container.prev('.upfront-output-region-container'),
							$prev_bg = $prev.find('.upfront-region-container-bg'),
							next_bg_color = $next_bg.css('background-color'),
							next_type = $next_bg.attr('data-bg-type-' + breakpoint),
							prev_bg_color = $prev_bg.css('background-color'),
							prev_type = $prev_bg.attr('data-bg-type-' + breakpoint),
							has_alpha = function (color) {
								if (!color) return false;
								if ("transparent" == color) return true;
								var matches = color.match(/(rgba|hsla)\(.*?,.*?,.*?,.*?([\d.]+).*?\)/);
								if (matches && matches[2] && parseFloat(matches[2]) < 1) return true;
								return false;
							},
							overflow_top = ( $prev.length > 0 && prev_type == 'color' && prev_bg_color && has_alpha(prev_bg_color) ? 0 : false ),
							overflow_bottom = ( $next.length > 0 && next_type == 'color' && next_bg_color && has_alpha(next_bg_color) ? 0 : false )
						;
						// No overlow if the next/prev container is contained
						if ( $prev.length > 0 && $prev.hasClass('upfront-region-container-clip') ) overflow_top = 0;
						if ( $next.length > 0 && $next.hasClass('upfront-region-container-clip') ) overflow_bottom = 0;
						$overlay.uparallax({
							element: $overlay.attr('data-bg-parallax')
						});
						if (false === overflow_top && $prev.length > 0 && $prev.height() < 200) overflow_top = $prev.height() * 0.5;
						if (false === overflow_bottom && $next.length > 0 && $next.height() < 200) overflow_bottom = $next.height() * 0.5;
						if (false !== overflow_top) $overlay.uparallax('setOption', 'overflowTop', overflow_top);
						if (false !== overflow_bottom) $overlay.uparallax('setOption', 'overflowBottom', overflow_bottom);
						$(document).on('upfront-responsive-nav-open upfront-responsive-nav-close', function () {
							if ( $overlay.data('uparallax') ) {
								$overlay.uparallax('refresh');
							}
						});
					}
				}, 0);
			}
			if ( type == 'image' || type == 'featured' ) {
				var is_overlay = $(this).attr('data-bg-overlay-'+breakpoint),
					$el = is_overlay ? $overlay.children('.upfront-bg-image') : $(this),
					before_src = $el.attr('data-src'),
					src = $el.attr('data-src-'+breakpoint),
					ratio = $el.attr('data-bg-image-ratio-'+breakpoint)
				;
				if ( is_overlay ) {
					$(this).css('background-image', 'none');
				}
				if ( src ) {
					$el.attr('data-src', src);
				}
				else {
					$el.removeAttr('data-src');
				}
				if ( ratio ) {
					$el.attr('data-bg-image-ratio', ratio);
				}
				else {
					$el.removeAttr('data-bg-image-ratio').css('background-position', '').css('background-size', '');
				}
				if ( src && before_src != src && $el.hasClass('upfront-image-lazy') ){
					$el.removeClass('upfront-image-lazy-loaded');
				}
				else {
					$el.css('background-image', 'url("' + src + '")');
				}
			}
			else if ( type == 'color' ) {
				$(this).css('background-image', 'none');
			}
			else {
				$(this).css('background-image', 'none');
				$overlay.each(function(){
					if ( $(this).is('.upfront-output-bg-video') && $(this).children().length == 1 ){
						var $iframe = $($(this).children('script.video-embed-code').html()),
							id = $iframe.attr('id');
						$(this).append($iframe);
						// If mute is enabled:
						var src;
						if ( $(this).attr('data-bg-video-mute') == 1 ) {
							src = $iframe.attr('src');
							if ( src.match(/youtube\.com/i) ) {
								// If loop is enabled too.
								if ( $(this).attr('data-bg-video-loop') == 1 ) {
									change_youtube_video(id, 'loopAndMute');
								} else {
									change_youtube_video(id, 'mute');
								}
							} else if ( src.match(/vimeo\./i) ) {
								mute_vimeo_video(id);
							}
						// If only loop is enabled:
						} else if ( $(this).attr('data-bg-video-loop') == 1 ) {
							src = $iframe.attr('src');
							// Only loop via this method if youtube video.
							if ( src.match(/youtube\.com/i) ) {
								change_youtube_video(id, 'loop');
							}
						}
					}
				});
			}
		});
	}
	update_background();
	var lazyUpdateBackground = throttle(update_background, 300);
	$(window).on('resize.uf_layout', lazyUpdateBackground);

	// Making sure sidebar region height is fixed
	function fix_region_height () {
		set_full_screen();
		$('.upfront-output-region-container').each(function(){
			var $regions = $(this).find('.upfront-output-region').filter('.upfront-region-center, .upfront-region-side-left, .upfront-region-side-right'),
				is_full_screen = $(this).hasClass('upfront-region-container-full'),
				min_height = height = 0;
			if ( $regions.length > 1 ){
				$regions.each(function(){
					var min = parseInt($(this).css('min-height'), 10),
						h = $(this).outerHeight();
					if ( min )
						min_height = min > min_height ? min : min_height;
					height = h > height ? h : height;
				});
				$regions.css({
					minHeight: height,
					height: "",
					maxHeight: ""
				});
			}
		});
	}
	function set_full_screen () {
		$('.upfront-output-region-container.upfront-region-container-full').each(function(){
			var $region = $(this).find('.upfront-region-center'),
				$sub = $(this).find('.upfront-region-side-top, .upfront-region-side-bottom'),
				body_off = $('body').offset(),
				height = $(window).height() - body_off.top,
				$bg_overlay = $(this).find('.upfront-output-bg-overlay')
			;
			if ( $bg_overlay.length ) $bg_overlay.css('height', height);
			$sub.each(function(){
				height -= $(this).outerHeight();
			});
			$region.css({
				minHeight: height
			});
			// Keep element position to ratio if enabled
			var behavior = $(this).attr('data-behavior'),
				original_height = parseInt($(this).attr('data-original-height'), 10)
			;
			if ( behavior == 'keep-ratio' && original_height > 0 ){
				var $wrappers = $region.find('> .upfront-region-wrapper > .upfront-output-wrapper'),
					region_off = $region.offset(),
					modules = [],
					lines = [],
					line_index = -1,
					total_height = 0,
					total_fill = 0,
					ori_bottom_space = 0,
					avail_bottom_space = 0,
					available_space = 0,
					original_space = 0
				;

				$wrappers.each(function(){
					var $modules = $(this).find('> .upfront-output-module, > .upfront-output-module-group');
					if ( $modules.length == 0 ) return;
					var wrap_obj = {
						$el: $(this),
						top_space: 0,
						bottom_space: 0,
						fill: 0,
						modules: []
					};
					$modules.each(function(module_index){
						var $el = $(this).hasClass('upfront-output-module-group') ? $(this) : $(this).find('> .upfront-output-object');
						$el.css({
							paddingTop: '',
							paddingBottom: '',
							minHeight: ''
						});
						var padding_top = parseFloat($el.css('padding-top')),
							padding_bottom = parseFloat($el.css('padding-bottom')),
							height = parseFloat($(this).css('height')),
							min_height = parseFloat($el.css('min-height'))
						;
						if ( module_index == 0 ) {
							wrap_obj.top_space = padding_top;
						}
						wrap_obj.bottom_space = padding_bottom;
						wrap_obj.fill += height;
						wrap_obj.modules.push({
							$el: $el,
							top: padding_top,
							bottom: padding_bottom,
							height: height - padding_top - padding_bottom,
							min_height: min_height !== min_height ? 0 : min_height
						});
					});
					wrap_obj.fill -= wrap_obj.top_space + wrap_obj.bottom_space;

					var wrap_off = $(this).offset(),
						wrap_left = parseFloat($(this).css('margin-left')),
						wrap_height = parseFloat($(this).css('height'))
					;

					if ( Math.abs(wrap_off.left-wrap_left-region_off.left) < 5 ){
						line_index++;
						lines[line_index] = {
							wrappers: [wrap_obj],
							height: wrap_height,
							top_space: wrap_obj.top_space,
							bottom_space: wrap_obj.bottom_space
						};
					}
					else {
						lines[line_index].top_space = wrap_obj.top_space < lines[line_index].top_space ? wrap_obj.top_space : lines[line_index].top_space;
						if ( wrap_height >= lines[line_index].height ) {
							lines[line_index].height = wrap_height;
							lines[line_index].bottom_space = wrap_obj.bottom_space < lines[line_index].bottom_space ? wrap_obj.bottom_space : lines[line_index].bottom_space;
						}
						lines[line_index].wrappers.push(wrap_obj);
					}
				});

				$.each(lines, function(index, line){
					total_height += line.height;
					total_fill += line.height - line.top_space - line.bottom_space;
					original_space += line.top_space + line.bottom_space;
				});
				ori_bottom_space = original_height > total_height ? original_height-total_height : 0;
				original_space += ori_bottom_space;
				available_space = height > total_fill ? height - total_fill : 0;

				var count_space = function (from, until) {
					var total_space = 0,
						from = typeof from == "number" ? from : 0,
						until = typeof until == "number" ? until : -1
					;
					$.each(lines, function(index, line){
						if ( index < from || ( until > -1 && index > until ) ) return;
						var top_space = false,
							bottom_space = false,
							line_height = 0
						;
						$.each(line.wrappers, function(w, wrap){
							var wrap_height = wrap.fill + wrap.top_space + wrap.bottom_space;
							line_height = wrap_height > line_height ? wrap_height : line_height;
						});
						$.each(line.wrappers, function(w, wrap){
							var wrap_bottom_space = line_height - wrap.fill - wrap.top_space;
							top_space = ( top_space === false || wrap.top_space < top_space ) ? wrap.top_space : top_space;
							bottom_space = ( bottom_space === false || wrap_bottom_space < bottom_space ) ? wrap_bottom_space : bottom_space;
						});
						total_space += top_space + bottom_space;
					});
					return total_space;
				}

				$.each(lines, function(index, line){
					var line_top_space = Math.round(line.top_space/original_space * available_space),
						line_bottom_space = Math.round(line.bottom_space/original_space * available_space)
					;
					$.each(line.wrappers, function(w, wrap){
						$.each(wrap.modules, function(m, module){
							var new_top = module.top - line.top_space + line_top_space,
								new_bottom = module.bottom - line.bottom_space + line_bottom_space,
								min_height = module.min_height
							;
							if ( m == 0 ) {
								module.$el.css('padding-top', new_top + 'px');
								min_height -= module.top - new_top;
							}
							if ( m == wrap.modules.length - 1 ) {
								module.$el.css('padding-bottom', new_bottom + 'px');
								min_height -= module.bottom - new_bottom;
							}
							min_height = min_height > 0 ? min_height : 0;
							module.$el.css('min-height', min_height + 'px');
						});
					});
				});
			}
		});
	}
	var lazySetFullScreen = throttle(set_full_screen, 100);
	var lazyFixRegionHeight = throttle(fix_region_height, 100);
	if ( css_support('flex') ){
		$('html').addClass('flexbox-support');
		set_full_screen();
		$(window).on('load.uf_layout', set_full_screen);
		$(window).on('resize.uf_layout', lazySetFullScreen);
	}
	else {
		fix_region_height();
		$(window).on('load.uf_layout', fix_region_height);
		$(window).on('resize.uf_layout', lazyFixRegionHeight);
	}

	// Full width image and video background
	function fix_full_bg () {
		var body_off = $('body').offset();
		$('[data-bg-image-ratio]').each(function(){
			var is_layout = $(this).is('.upfront-output-layout'),
				is_full_screen = ( ( $(this).is('.upfront-region-container-bg') || $(this).is('.upfront-output-region') ) && $(this).closest('.upfront-region-container-full').length > 0 ),
				width = is_layout ? $(window).width() : $(this).outerWidth(),
				height = is_layout ? $(window).height() : ( is_full_screen ? $(window).height()-body_off.top : $(this).outerHeight() ),
				ratio = parseFloat($(this).attr('data-bg-image-ratio'));

			// If Parallax, do not change background size/position.
			if (this.parentNode.getAttribute('data-bg-parallax')) {
				return;
			}

			if ( Math.round(height/width*100)/100 > ratio ) {
				$(this).data('bg-position-y', 0);
				$(this).data('bg-position-x', '50%');
				$(this).css({
					'background-position': '50% 0',
					'background-size': Math.round(height/ratio) + "px " + height + "px" /*"auto 100%"*/
				});
			} else {
				$(this).data('bg-position-y', Math.round( ( height - (width*ratio) ) / 2 ));
				$(this).data('bg-position-x', '0');
				$(this).css({
					'background-position': '0 ' + Math.round( ( ( height - (width*ratio) ) / 2) ) + 'px',
					'background-size': width + "px " + Math.round(width*ratio) + "px" /*"100% auto"*/
				});
			}
		});
		$('[data-bg-video-ratio]').each(function(){
			var is_layout = $(this).parent().is('.upfront-output-layout'),
				is_full_screen = (  $(this).parent().is('.upfront-output-region, .upfront-region-container-bg') && $(this).closest('.upfront-region-container-full').length > 0 ),
				width = is_layout ? $(window).width() : $(this).outerWidth(),
				height = is_layout ? $(window).height() : ( is_full_screen ? $(window).height()-body_off.top : $(this).outerHeight() ),
				ratio = parseFloat($(this).attr('data-bg-video-ratio')),
				style = $(this).attr('data-bg-video-style') || 'crop',
				$embed = $(this).children('iframe');

			if ( $embed.length === 0) {
				$embed = $(this).find('video');
			}
			$(this).css('overflow', 'hidden');
			$embed.css({
				position: 'absolute'
			});
			if ( style == 'crop' ){
				if ( Math.round(height/width*100)/100 > ratio ){
					var embed_w = Math.round(height/ratio);
					$embed.css({
						width: embed_w,
						height: height,
						top: 0,
						left: Math.round((width-embed_w)/2)
					});
				}
				else {
					var embed_h = Math.round(width*ratio);
					$embed.css({
						width: width,
						height: embed_h,
						top: Math.round((height-embed_h)/2),
						left: 0
					});
				}
			}
			else if ( style == 'full' ) {
				$embed.css({
					top: 0,
					left: 0,
					width: width,
					height: height
				});
			}
			else if ( style == 'inside' ) {
				if ( Math.round(height/width*100)/100 < ratio ){
					var embed_w = Math.round(height/ratio);
					$embed.css({
						width: embed_w,
						height: height,
						top: 0,
						left: Math.round((width-embed_w)/2)
					});
				}
				else {
					var embed_h = Math.round(width*ratio);
					$embed.css({
						width: width,
						height: embed_h,
						top: Math.round((height-embed_h)/2),
						left: 0
					});
				}
			}
		});
		$('.upfront-output-object .upfront-featured-image-smaller').each(function() {
			var $img = $(this),
				$container = $img.parent(),
				data = $img.data('featured-image'),
				align = $img.data('featured-align'),
				valign = $img.data('featured-valign'),
				dotalign = $img.data('featured-dotalign'),
				mode = $img.data('featured-mode'),
				imgHeight = $img.height(),
				imgWidth = $img.width(),
				breakpoint = get_breakpoint()
			;

			// If table or mobile breakpoint, image is smaller than container and dotAlign is true make it inline
			if((breakpoint === "tablet" || breakpoint === "mobile") &&
					((mode === "small" || mode === "vertical" ) && dotalign === true)) {

				// Set text-align for parent container
				$container.css({
					'textAlign': align,
					'maxWidth': '100%'
				});

				// Make image inline
				$img.css({
					'position': 'static',
					'display': 'inline-block'
				});

				// Update margin to position image top or bottom
				/*if(valign === "center") {
					$img.css({
						'marginTop': (data.offsetHeight / 2) - (imgHeight / 2),
					});
				} else if (valign === "bottom") {
					$img.css({
						'marginTop': (data.offsetHeight - imgHeight),
					});
				}*/
			} else {
				if((breakpoint === "tablet" || breakpoint === "mobile") && mode === "small") {
					// Null above
					$container.css({
						'textAlign': 'center',
						'maxWidth': '100%',
						'width': '100%'
					});

					$img.css({
						'position': 'static',
						'display': 'inline-block'
					});
				} else if ((breakpoint === "tablet" || breakpoint === "mobile") && mode !== "small") {
					// Set image 100% width
					$container.css({
						'width': '100%',
						'height': 'auto'
					});
					$img.css({
						'width': '100%',
						'height': 'auto',
						'left': 0
					});
				} else {
					// Null above and position image into parent container
					$img.css({
						'top': data.offsetTop,
						'left': data.offsetLeft,
						'position': 'relative',
						'display': 'block',
						'marginTop': 0,
						'width': 'initial'
					});

					$container.css({ 'width': data.offsetWidth, 'height': data.offsetHeight});
				}
			}
		});
		$('.upfront-output-object .uf-post .thumbnail, .uf-post-data .upostdata-part.thumbnail').each(function(){
			var is_upostdata = $(this).hasClass('upostdata-part'),
				$object = $(this).closest('.upfront-output-object'),
				height = is_upostdata ? parseInt($object.css('min-height'), 10) : $(this).height(),
				width = $(this).width(),
				padding_top = parseInt($object.css('padding-top'), 10),
				padding_bottom = parseInt($object.css('padding-bottom'), 10),
				$img = $(this).find('img'),
				$container = $(this),
				imgHeight = $img.height(),
				imgWidth = $img.width(),
				breakpoint = get_breakpoint(),
				img = new Image,
				img_h, img_w
			;
			if ( is_upostdata ) {
				if(breakpoint === "tablet" || breakpoint === "mobile") {
					// Set image 100% width
					$container.css({
						'width': '100%',
						'height': 'auto'
					});
					$img.css({
						'width': '100%',
						'height': 'auto'
					});
					// Set height to image
					height = imgHeight;
					$object.css('min-height', height);
					$object.closest('.upfront-output-object-group').css('min-height', height);
				}
				else {
					$object.css('min-height', '');
					$object.closest('.upfront-output-object-group').css('min-height', '');
				}

				if ( !$img.hasClass('upfront-featured-image-fit-wrapper') ) return; // No fit for this
				height -= padding_top + padding_bottom;
				$(this).css('height', height);
			}
			if ( $(this).attr('data-resize') == "1" ) {
				img.src = $img.attr('src');
				img_h = img.height;
				img_w = img.width;
				if ( height/width > img_h/img_w ) {
					$img.css({ height: '100%', width: 'auto', marginLeft: (width-Math.round(height/img_h*img_w))/2, marginTop: "" });
				}
				else {
					$img.css({ height: 'auto', width: '100%', marginLeft: "", marginTop: (height-Math.round(width/img_w*img_h))/2 });
				}
			}
			else {
				img_h = $img.height();
				if ( height != img_h ) {
					$img.css('margin-top', (height-img_h)/2);
				}
			}
		});
	}
	fix_full_bg();
	var lazyFixFullBg = throttle(fix_full_bg, 500);
	$(window).on('resize.uf_layout', lazyFixFullBg);
	$(window).on('load.uf_layout', lazyFixFullBg);

	// Regions behavior on scroll
	var _scroll_data = {};
	function regions_scroll_update () {
		var breakpoint = get_breakpoint(),
			body_off = typeof _scroll_data.body_off != 'undefined' ? _scroll_data.body_off : $('body').offset(),
			scroll_top = $(window).scrollTop(),
			win_height = $(window).height(),
			scroll_bottom = scroll_top + win_height,
			$sticky_regions = typeof _scroll_data.$sticky_regions != 'undefined'
				? _scroll_data.$sticky_regions
				: $('.upfront-output-region-container[data-sticky="1"], .upfront-output-region-sub-container[data-sticky="1"]'),
			$floating_regions = typeof _scroll_data.$floating_regions != 'undefined'
				? _scroll_data.$floating_regions
				: $('.upfront-output-region-container.upfront-region-container-full, .upfront-output-region-container.upfront-region-container-full .upfront-output-region-sub-container:not(.upfront-output-region-container-sticky), .upfront-output-region.upfront-region-side-fixed[data-restrict-to-container="1"]')
		;
		_scroll_data.body_off = body_off;
		_scroll_data.$sticky_regions = $sticky_regions;
		_scroll_data.$floating_regions = $floating_regions;

		if ( body_off.top > 0 ){
			scroll_top += body_off.top;
			win_height -= body_off.top;
		}
		scroll_top = scroll_top < body_off.top ? body_off.top : scroll_top;

		// Sticky region behavior
		$sticky_regions.each(function(){
			var is_sub_container = $(this).hasClass('upfront-output-region-sub-container'),
				is_top = ( is_sub_container && $(this).nextAll('.upfront-grid-layout').length > 0 ),
				offset = $(this).offset(),
				sticky_top = $(this).data('sticky-top'),
				css = {};
			if ( typeof sticky_top != 'number' && scroll_top > offset.top ) {
				css.position = 'fixed';
				css.top = $('#wpadminbar').css('position') != 'fixed' ? 0 : body_off.top;
				css.left = 0;
				css.right = 0;
				css.bottom = 'auto';
				$(this).addClass('upfront-output-region-container-sticky');
				$(this).data('sticky-top', offset.top);
				if ( is_sub_container ) {
					$(this).closest('.upfront-region-container-bg').css( ( is_top ? 'padding-top' : 'padding-bottom' ), $(this).height() );
						$(this).find('.upfront-region-container-bg').css({position: 'fixed', top: 0});
				}
				else {
					$(this).next('.upfront-output-region-container').css('padding-top', $(this).height());
				}
			}
			else if ( typeof sticky_top == 'number' && scroll_top <= sticky_top ) {
				css.position = '';
				css.top = '';
				css.left = '';
				css.right = '';
				css.bottom = '';
				$(this).removeClass('upfront-output-region-container-sticky');
				$(this).removeData('sticky-top');
				if ( is_sub_container )
					$(this).closest('.upfront-region-container-bg').css( ( is_top ? 'padding-top' : 'padding-bottom' ), '');
				else
					$(this).next('.upfront-output-region-container').css('padding-top', '');
			}
			$(this).css(css);
		});

		// Floating behavior
		$floating_regions.each(function(){
			var is_float = $(this).is('.upfront-region-side-fixed'),
				is_full_screen = $(this).is('.upfront-region-container-full'),
				is_sub_container = $(this).is('.upfront-output-region-sub-container'),
				$container = $(this).closest('.upfront-output-region-container'),
				container_height = $container.outerHeight(),
				container_offset = $container.offset(),
				container_bottom = container_offset.top + container_height,
				height = $(this).height(),
				top = is_float ? parseInt($(this).attr('data-top'), 10) : 0,
				is_top = is_float ? ( typeof $(this).attr('data-top') != "undefined" ) : ( $(this).nextAll('.upfront-grid-layout').length > 0 ),
				bottom = is_float ? parseInt($(this).attr('data-bottom'), 10) : 0,
				is_bottom = is_float ? ( typeof $(this).attr('data-bottom') != "undefined" ) : ( $(this).prevAll('.upfront-grid-layout').length > 0 ),
				css = {}
			;
			if ( is_full_screen ) {
				var $bg_image = $(this).find('.upfront-region-container-bg'),
					is_bg_image = ( $bg_image.css('background-image') != 'none' ),
					$bg_overlay = $(this).find('.upfront-output-bg-overlay:visible'),
					is_bg_overlay = ( $bg_overlay.length > 0 ),
					bg_position_y = 0,
					bg_position_x = 0,
					bg_position_css = $bg_image.css('background-position')
				;
				if ( is_bg_image ) {
					if ( typeof $bg_image.data('bg-position-y') == 'undefined' )
						$bg_image.data('bg-position-y', bg_position_css.match(/\d+(%|px|)$/)[0]);
					if ( typeof $bg_image.data('bg-position-x') == 'undefined' )
						$bg_image.data('bg-position-x', bg_position_css.match(/^\d+(%|px|)/)[0]);
					bg_position_y = $bg_image.data('bg-position-y');
					bg_position_x = $bg_image.data('bg-position-x');
					if ( typeof bg_position_y == 'string' && bg_position_y.match(/%$/) ){
						var img = new Image;
						img.src = $bg_image.css('background-image').replace(/^url\(\s*['"]?\s*/, '').replace(/\s*['"]?\s*\)$/, '');
						bg_position_y = parseInt(bg_position_y, 10)/100 * (height-img.height);
					}
					else {
						bg_position_y = parseInt(bg_position_y, 10);
					}
				}
			}
			if ( scroll_top >= container_offset.top && scroll_bottom <= container_bottom ){
				if ( is_float || is_sub_container ) {
					css.position = 'fixed';
					if ( is_top )
						css.top = top + body_off.top;
					else {
						css.top = 'auto';
						css.bottom = bottom;
					}
				}
				if ( is_sub_container ){
					css.left = 0;
					css.right = 0;
					if ( is_top )
						$container.find('> .upfront-region-container-bg').css('padding-top', height);
					else
						$container.find('> .upfront-region-container-bg').css('padding-bottom', height);
				}
				if ( is_full_screen ){
					if ( is_bg_image ) {
						$bg_image.css({
							backgroundAttachment: 'fixed',
							backgroundPosition: bg_position_x + ' ' + bg_position_y + 'px'
						});
					}
					else if ( is_bg_overlay ) {
						$bg_overlay.css({
							position: 'fixed',
							top: ( scroll_top - body_off.top )
						});
					}
				}
			}
			else {
				if ( is_float ) {
					css.position = 'absolute';
					if ( is_top ) {
						if ( container_height > win_height && scroll_top >= ( container_offset.top + container_height - win_height ) )
							css.top = container_height - win_height + top;
						else
							css.top = top;
					}
					else {
						if ( container_height > win_height && scroll_bottom <= ( container_offset.top + win_height ) )
							css.bottom =  container_height - win_height + bottom;
						else
							css.bottom = bottom;
					}
				}
				else if ( is_sub_container ) {
					css.position = 'relative';
					if ( is_top ) {
						css.top = container_height - win_height + top;
					}

					// If sticky subregion.
					if ($(this).data('sticky') === 1) {
						// If scrolled to top of subregion's home, switch to position relative.
						if (is_top ? $(window).scrollTop() < body_off.top : $(window).scrollTop() < container_bottom - $(this).height()) {
							$(this).find('.upfront-region-container-bg').css({position: 'relative', top: ''});
							// Make sure subregion is on top of page (scrolling fast made it forget to go to the top).
							css.top = 0;
						} else {
							// Else switch to fixed position.
							$(this).find('.upfront-region-container-bg').css({position: 'fixed', top: body_off.top});
						}
					}
					css.bottom = '';
					css.left = '';
					css.right = '';
					$container.find('> .upfront-region-container-bg').css({
						paddingTop: '',
						paddingBottom: ''
					});
				}
				else if ( is_full_screen ) {
					if ( is_bg_image ) {
						$bg_image.css({
							backgroundAttachment: '',
							backgroundPosition: bg_position_x + ' ' + ( bg_position_y + ( container_height - win_height ) ) + 'px'
						});
					}
					else if ( is_bg_overlay ) {
						$bg_overlay.css({
							position: '',
							top: ( container_height - win_height )
						});
					}
				}
			}
			$(this).css(css);
		});
	}
	regions_scroll_update();
	$(window).on('load.uf_layout', regions_scroll_update);
	var lazyScrollUpdate = throttle(regions_scroll_update, 100);
	$(window).on('scroll.uf_layout', regions_scroll_update);
	$(window).on('resize.uf_layout', lazyScrollUpdate);

	/* Lightbox front end logic */
	var overlay = $('<div class="upfront-lightbox-bg"></div>'),
		close= $('<div class="upfront-ui close_lightbox"></div>'),
		close_icon= $('<div class="upfront-icon upfront-icon-popup-close"></div>');

	$("[data-group-link]").css({'cursor': 'pointer'});
	$(document).on("click", "[data-group-link]", function () {
		var url = $(this).data("groupLink");
		var target = $(this).data("groupTarget") || '_self';

		if(url.indexOf('#') === -1) {
			// Not an anchor, follow link
			window.open(url, target);
			return;
		}

		// It is an anchor
		if (url.match(/^#.*/) !== null) {
			// Starts with #, it's safe to do the jQuery stuff
			var nav = $('.upfront-output-region-container[data-sticky="1"], .upfront-output-region-sub-container[data-sticky="1"]').first();
			var height = nav.height() ? nav.height() : 0;
			$('html,body').animate({scrollTop: $(url).offset().top - height },'slow');
			return;
		}

		// It's an absolute url with anchor
		var urlParts = url.split('#');
		if (urlParts[0] === location.origin + location.pathname) {
			// Target is on the current page
			var nav = $('.upfront-output-region-container[data-sticky="1"], .upfront-output-region-sub-container[data-sticky="1"]').first();
			var height = nav.height() ? nav.height() : 0;
			$('html,body').animate({scrollTop: $('#' + urlParts[1]).offset().top - height },'slow');
			return;
		}

		// It's not on the current page
		if ($(this).attr('target') === '_blank') {
			// Open in a new window
			window.open(url);
			return;
		}

		// Open in this window
		window.location = url;
	});

	$(document).on('click', 'a', function(e) {
		//If we are in the editor the lightbox is open using the region.
		//if(typeof(Upfront) != 'undefined' && Upfront.Views)
			//return;

		if($(e.target).closest('div.redactor_box') > 0)
			return;

		if($('div#sidebar-ui').length > 0 && $('div#sidebar-ui').css('display') == 'block') {

				if($(e.target).hasClass('upfront_cta')) {
					e.preventDefault();
					return;
				}

				var url = $(e.target).attr('href');

				if(url && url.indexOf && url.indexOf('#ltb-') > -1)	 {

					e.preventDefault();
					var regions = Upfront.Application.layout.get('regions');
					var urlanchor = url.split('#');

					region = regions ? regions.get_by_name(urlanchor[1]) : false;
					if(region){
						//hide other lightboxes
						_.each(regions.models, function(model) {
							if(model.attributes.sub == 'lightbox')
								Upfront.data.region_views[model.cid].hide();
						});
						var regionview = Upfront.data.region_views[region.cid];
						regionview.show();

					}
				}

			return;
		}

		var url = $(this).attr('href');
		if(!url) {
			return;
		}

		if(url.indexOf('#') === -1) return;

		if($(this).closest('div.upfront-navigation').data('style') == 'burger' && $(this).parent('li.menu-item.menu-item-has-children').length > 0) {
			var linkitem = $(this).parent('li.menu-item.menu-item-has-children');

			if(linkitem.children('ul.sub-menu').closest('li.menu-item').hasClass('burger_sub_display'))
					linkitem.children('ul.sub-menu').closest('li.menu-item').removeClass('burger_sub_display');
			else
				linkitem.children('ul.sub-menu').closest('li.menu-item').addClass('burger_sub_display');

			var menu = linkitem.closest('ul.menu');
			var menucontainer = menu.closest('div.upfront-output-unewnavigation').children('div');
			if(menucontainer.data('burger_over') == 'pushes' && menucontainer.data('burger_alignment') == 'top') {

				$('div#page').css('margin-top', menu.height());


				//var topbar_height = $('div#upfront-ui-topbar').outerHeight();
				var adminbar_height = $('div#wpadminbar').outerHeight();
				menu.offset({top:adminbar_height, left:$('div').offset().left});
				//menu.width($('div#page').width());

			}
		}

		e.preventDefault();
		var tempurl = url.split('#');
		if(tempurl[1].trim() === '') {
			return;
		}

		if (tempurl[1].trim().indexOf('ltb-') == 0) {
			var lightbox =  $('div.upfront-region-'+tempurl[1].trim());

			overlay.css('background-color', lightbox .data('overlay')).insertBefore(lightbox);

			if(lightbox.data('closeicon') == 'yes' || lightbox.data('addclosetext') == 'yes') {
				lightbox.prepend(close);

				if(lightbox.data('addclosetext') == 'yes') {
					close.append($('<h3>'+lightbox.data('closetext')+'</h3>'));
					if(lightbox.data('closeicon') == 'yes')
						close.children('h3').css('margin-right', '40px');
				}
				if(lightbox.data('closeicon') == 'yes')
					close.append(close_icon);

				close.bind('click', function() {
					lightboxhide();
				});
			}

			if(lightbox.data('clickout') == 'yes') {
				overlay.bind('click', function() {
					lightboxhide();
				});
			}
			// If Grid exists, use that. Otherwise default to 45px per column.
			var column_width = typeof Upfront !== 'undefined' && Upfront.Settings ? Upfront.Settings.LayoutEditor.Grid.column_width : 45;
			// Note that max-width and max-height are set in global.css for responsive design.
			// translate width in columns to width in pixels
			var lightbox_width = column_width * lightbox.data('col');
			var lightbox_height = lightbox.data('height');
			lightbox.show().css({'width': lightbox_width, 'height': lightbox_height, 'min-height': 200});
			// Based upon above CSS.
			lightbox.css({'margin-left': -(parseInt(lightbox.width()/2, 10)), 'margin-top': -(parseInt(lightbox.height()/2, 10))});

			/* elements can subscribe to the following event to
			 * to render their content based
			 * on the dimensions of the lightbox
			 * itself, such elements are gallery and slider
			*/
			$(document).trigger("upfront-lightbox-open", lightbox);

			e.preventDefault();
			function lightboxhide() {
				close.html('').remove()
				overlay.remove();
				lightbox.hide();
				
				// Stop YT video if any
				var yt_video = lightbox.find('.upfront-youtube-container iframe');
				
				if(yt_video.length) {
					var yt_src = yt_video.attr('src');
					yt_video.attr('src', '').attr('src', yt_src);
				}
			}
			return;
		}

		var nav = $('.upfront-output-region-container[data-sticky="1"], .upfront-output-region-sub-container[data-sticky="1"]').first();
		var height = nav.height() ? nav.height() : 0;
		//It is an anchor
		// Starts with #, it's safe to do the jQuery stuff
		if (url.match(/^#.*/) !== null) {
			$('html,body').animate({scrollTop: $(url).offset().top - height },'slow');
			return;
		}

		// It's an absolute url with anchor
		var urlParts = url.split('#');
		if (urlParts[0] === location.origin + location.pathname) {
			// Target is on the current page
			$('html,body').animate({scrollTop: $('#' + urlParts[1]).offset().top - height },'slow');
			return;
		}

		// It's not on the current page
		if ($(this).attr('target') === '_blank') {
			// Open in a new window
			window.open(url);
			return;
		}

		// Open in this window
		window.location = url;
	});

	/* Lazy loaded image */
	var image_lazy_load_t;
	var image_lazy_scroll = window._upfront_image_lazy_scroll;
	function image_lazy_load () {
		clearTimeout(image_lazy_load_t);
		image_lazy_load_t = setTimeout(function(){
			var scroll = $(window).scrollTop(),
				w_height = $(window).height(),
				w_width = $(window).width();
			$('.upfront-image-lazy').each(function(){
				if ( $(this).hasClass('upfront-image-lazy-loading') )
					return;
				var me = this,
					offset = $(this).offset(),
					height = $(this).height(),
					width = $(this).width(),
					source, src, closest;
				if (
					( ( image_lazy_scroll && offset.top+height >= scroll && offset.top < scroll+w_height ) || !image_lazy_scroll ) &&
					( width > 0 && height > 0 )
				){
					source = $(this).attr('data-sources');
					if ( source )
						source = JSON.parse(source);
					else
						src = $(this).attr('data-src');
					if ( typeof source != 'undefined' && source.length || src ){
						if ( typeof source != 'undefined' && source.length ){
							for ( var s = 0; s < source.length; s++ ) {
								if ( source[s][1] <= width || ( closest >= 0 && source[closest][1] < width && source[s][1] > width ) )
									closest = s;
							}
							if ( $(this).data('loaded') == closest )
								return;
							src = source[closest][0];
							$(this).data('loaded', closest);
						}
						else if ( src && $(this).hasClass('upfront-image-lazy-loaded') ){
							return;
						}
						$(this).removeClass('upfront-image-lazy-loaded').addClass('upfront-image-lazy-loading');
						$('<img>').attr('src', src).on('load', function(){
							if ( $(me).hasClass('upfront-image-lazy-bg') )
								$(me).css('background-image', 'url("' + $(this).attr('src') + '")');
							else
								$(me).attr('src', $(this).attr('src'));
							$(me).removeClass('upfront-image-lazy-loading').addClass('upfront-image-lazy-loaded');
						});
					}
				}
			});
		}, 100);
	}


	/**
	 * The queue object, used to chain-load images within a load level.
	 */
	function LazyLoad_Queue () {
		var deferreds = [],
			targets = []
		;

		function get_lazy_loading_image_promise (obj) {
			var deferred = new $.Deferred();
			obj.$el.removeClass('upfront-image-lazy-loaded').addClass('upfront-image-lazy-loading');
			$('<img />')
				.attr('src', obj.url)
				.on('load', function () {
					if (obj.$el.is(".upfront-image-lazy-bg")) obj.$el.css('background-image', 'url("' + obj.url + '")');
					else (obj.$el.attr('src', obj.url));
					obj.$el.removeClass('upfront-image-lazy-loading').addClass('upfront-image-lazy-loaded');
					deferred.resolve();
				})
				.on('error abort', function () {
					deferred.reject();
				})
			;
			return deferred.promise();
		}
		function add (src, $img) {
			targets.push({
				url: src,
				$el: $img
			});
		}
		function start () {
			var semaphore = new $.Deferred();
			$.each(targets, function (idx, obj) {
				deferreds.push(get_lazy_loading_image_promise(obj));
			});
			$.when.apply($, deferreds)
				.always(function () {
					semaphore.resolve();
				})
			;
			return semaphore.promise();
		}
		return {
			add: add,
			start: start
		}
	}

	/**
	 * The stack of queues, used to chain-load queued levels.
	 */
	function LazyLoad_QueueStack (queues) {
		function start () {
			queues.reverse();
			execute();
		}
		function execute () {
			var q = queues.pop();
			if (!q) return false;
			q.start().done(execute);
		}
		return { start: start };
	}

	/**
	 * Initial background loading of the images.
	 * Separate images into priority queues and load each one appropriately.
	 */
	function image_lazy_load_bg () {
		var secondary_delta = 1500,
		// Sources
			$images = $('.upfront-image-lazy'),
		// Queues
			primary = new LazyLoad_Queue(),
			secondary = new LazyLoad_Queue(),
			tertiary = new LazyLoad_Queue(),
		// Misc
			scroll = $(window).scrollTop(),
			w_height = $(window).height(),
			w_width = $(window).width(),
			breakpoint = get_breakpoint()
		;
		breakpoint = !breakpoint || 'none' === breakpoint ? 'desktop' : breakpoint; // "none" in FF

		if (!$images.length) return false;
		$images.each(function () {
			var $img = $(this),
				offset = $img.offset(),
				source = $img.attr('data-sources'),
				src = $img.attr('data-src'),
				point_src = $img.attr('data-src-' + breakpoint),
				height = $img.height(),
				width = $img.width()
			;

			//Remove blank.gif to calculate width correctly
			$img.attr('src', '');

			if ($img.is(".upfront-image-lazy-loaded")) return true; // already loaded
			if (!source && !src && !point_src) return true; // we don't know how to load
			if (height <= 0 && width <= 0) return true; // Don't lazy load backgrounds for hidden regions.

			if (source) {
				// Deal with source JSON and populate `src` from there
				var width = $img.width(),
					closest = 0
				;
				source = JSON.parse(source);
				for ( var s = 0; s < source.length; s++ ) {
					if ( source[s][1] <= width || ( closest >= 0 && source[closest][1] < width && source[s][1] > width ) )
						closest = s;
				}
				if ( $(this).data('loaded') == closest ) return true;
				src = source[closest][0]; // Use this to load
				$(this).data('loaded', closest);
			} else if (point_src) src = point_src;

			if (offset.top+height >= scroll && offset.top < scroll+w_height) {
				primary.add(src, $img);
			} else if (offset.top+height+secondary_delta >= scroll && offset.top < scroll+w_height+secondary_delta) {
				secondary.add(src, $img);
			} else {
				tertiary.add(src, $img);
			}

		});
		$(window).off('scroll', image_lazy_load); // Since we scheduled image loads, kill the scroll load

		// We're ready now
		var stack = new LazyLoad_QueueStack([
			// Order is significant
			primary,
			secondary,
			tertiary
		]).start();

	}

	// Initialize appropriate behavior
	var lazyImageLazyLoad = throttle(image_lazy_load, 100);
	$(window).on('resize', lazyImageLazyLoad); // Okay, so this should keep on happening on resizes
	if ( image_lazy_scroll ) {
		$(window).on('scroll', lazyImageLazyLoad);
		image_lazy_load();
	} else {
		$(image_lazy_load_bg); // Do background load instead
	}


	/* Responsive custom theme styles */
	function update_theme_styles () {
		var breakpoint = get_breakpoint();
		$('[data-theme-styles]').each(function(){
			var theme_styles = $(this).attr('data-theme-styles'),
				classes = [];
			theme_styles = theme_styles.replace("\"default\":", "\"defaults\":");
			if ( theme_styles )
				theme_styles = JSON.parse(theme_styles);
			$.each(theme_styles, function(id, style_class){
				classes.push(style_class);
			});
			$(this).removeClass(classes.join(' '));
			if ( !breakpoint && theme_styles.defaults )
				$(this).addClass( theme_styles.defaults );
			else if ( breakpoint && ( theme_styles[breakpoint] || theme_styles.defaults ) )
				$(this).addClass( theme_styles[breakpoint] ? theme_styles[breakpoint] : theme_styles.defaults );
		});
	}
	update_theme_styles();
	var lazyUpdateThemeStyles = throttle(update_theme_styles, 100);
	$(window).on('resize.uf_layout', lazyUpdateThemeStyles);

	/* Apply responsive class */
	function update_responsive_class () {
		var breakpoint = get_breakpoint();
		if ( $('#page').hasClass('upfront-layout-view') ){
			return remove_responsive_class();
		}
		if (previous_breakpoint) {
			$('#page').removeClass(previous_breakpoint + '-breakpoint');
		}
		if ( breakpoint && breakpoint !== 'none' && breakpoint !== 'desktop' ) {
			$('html').addClass('uf-responsive');
			$('#page').removeClass('desktop-breakpoint default-breakpoint').addClass('responsive-breakpoint ' + breakpoint + '-breakpoint');
		}
		else {
			$('#page').removeClass('responsive-breakpoint').addClass('default-breakpoint desktop-breakpoint');
			remove_responsive_class();
		}
	}
	function remove_responsive_class () {
		$('html').removeClass('uf-responsive');
	}
	function reset_responsive_class () {
		var breakpoint = get_breakpoint();
		if ( breakpoint ) {
			$('#page').removeClass(breakpoint + '-breakpoint');
		}
	}
	update_responsive_class();
	var lazyUpdateResponsiveClass = throttle(update_responsive_class, 100);
	$(window).on('resize.uf_layout', lazyUpdateResponsiveClass);



	/**
	 * Trigger DOM event on breakpoint change,
	 * so elements can subscribe to it
	 *
	 * Front-end responsive presets propagation depends on this
	 * event being fired properly
	 */
	function propagate_breakpoint_change () {
		var breakpoint = get_breakpoint() || 'desktop',
			previous = get_previous_breakpoint() || 'desktop'
		;
		if (breakpoint !== previous) {
			/**
			 * Trigger a DOM event on actual breakpoint change
			 * Responsive presets propagation listens for this event
			 */
			$(document).trigger("upfront-breakpoint-change", breakpoint);
		}
	}
	var lazy_propagate_breakpoint_change = throttle(propagate_breakpoint_change, 20, {trailing: false});
	$(window).on('resize.uf_layout', lazy_propagate_breakpoint_change);
	// done propagating breakpoint change

	/**
	 * Swap preset classes per breakpoint for each of the object elements
	 * Happens only on breakpoint change event
	 */
	function propagate_responsive_presets (e, breakpoint) {
		breakpoint = breakpoint || get_breakpoint() || 'desktop';
		if (!breakpoint) return;

		$("[data-preset_map]").each(function () {
			var $me = $(this),
				rmap = $me.attr("data-preset_map"),
				map = rmap ? JSON.parse(rmap) : {},
				current_preset_class,
				final_preset_class
			;

			// Edge case, for when we don't have a preset for this
			// breakpoint in an element - it should retain its classes
			// if (!map[breakpoint]) return true;

			// we have to provide proper fallback here, mobile -> tablet -> desktop
			if ( breakpoint == 'mobile' ) {
				map[breakpoint] = map[breakpoint] || map['tablet'] || map['desktop'];
			} else if ( breakpoint == 'tablet' ) {
				map[breakpoint] = map[breakpoint] || map['desktop'];
			} else {
				map[breakpoint] = map[breakpoint];
			}

			$.each(map, function (bp, preset) {
				if ( $me.hasClass(preset) ) {
					current_preset_class = preset;
					$me.removeClass(preset);
				}
				if (bp === breakpoint && !final_preset_class) final_preset_class = preset;
			});

			if (final_preset_class) {
				$me.addClass(final_preset_class);
				// find all children with such preset class, some elements do have this
				$me.find('.' + current_preset_class).each(function(){
					$(this).removeClass(current_preset_class);
					$(this).addClass(final_preset_class);
				});
			}

		});

		/**
		 * Trigger a DOM event on responsive presets change
		 * The legacy preset elements (accordion, tabs, button) listen to this event
		 */
		$(document).trigger("upfront-responsive_presets-changed", breakpoint);
	}
	var lazy_propagate_responsive_presets = throttle(propagate_responsive_presets, 200, {trailing: false});
	$(document).on("upfront-breakpoint-change", lazy_propagate_responsive_presets);
	// done propagating presets

	// Make sure breakpoint change is propagated
	propagate_breakpoint_change();
	// end

	function remove_all_bound_events () {
		$(window).off('resize.uf_layout');
		$(window).off('scroll.uf_layout');
		$(window).off('load.uf_layout');
		// Also destroy parallax
		$('.upfront-output-layout .upfront-parallax').uparallax('destroy');
	}

	$(document).on('upfront-load', function(){
		Upfront.Events.once("application:mode:before_switch", remove_all_bound_events);
		Upfront.Events.once("application:mode:before_switch", reset_responsive_class);
		Upfront.Events.once("layout:render", remove_responsive_class);
	});

	// remove inline panels on Image Insert redactor-box FE
	var $image_insert_inline_panels = $('.upfront-output-wrapper .upfront-inserted_image-basic-wrapper').find('.upfront-inline-panel-item');
	if ( $image_insert_inline_panels.length > 0 ) {
		$image_insert_inline_panels.remove();
	}
	
	// Keyboard Focus Styles http://codepen.io/fusco/pen/4de5926b34d3a76c9ac9854b6beefebb
	$(this).on('focusin', function (e) {
		$('.keyboard-outline').removeClass('keyboard-outline');
		var wasByKeyboard = lastClick < lastKey;
		if (wasByKeyboard) {
			$(e.target).addClass('keyboard-outline');
		}
	});

	$(this).on('mousedown', function () {
		lastClick = new Date();
	});

	$(this).on('keydown', function () {
		lastKey = new Date();
	});
});

/* upfront-effect */
(function( $ ) {
	var rAFPollyfill = function(callback){
		var currTime = new Date().getTime(),
			lastTime,
			timeToCall = Math.max(0, 16 - (currTime - lastTime)),
			id = setTimeout(function() { callback(currTime + timeToCall); }, timeToCall)
		;
		lastTime = currTime + timeToCall;
		return id;
	};

	var rgba_to_rba = function(color){
		if( typeof Upfront !== "undefined" && Upfront.Util  ) // If we are in editor then delegate to Upfront.Util.colors.rgba_to_rgb
			return Upfront.Util.colors.rgba_to_rgb( color );

		return color.replace(/ /g,'').replace(/^rgba\((\d+)\,(\d+)\,(\d+)\,(\d+\.?\d{0,}?)\)$/, "rgb($1, $2, $3)");
	};
	var requestAnimationFrame =
			$.proxy(window.requestAnimationFrame, window) ||
			$.proxy(window.webkitRequestAnimationFrame, window) ||
			$.proxy(window.mozRequestAnimationFrame, window) ||
			$.proxy(window.oRequestAnimationFrame, window) ||
			$.proxy(window.msRequestAnimationFrame, window) ||
			rAFPollyfill
		;

	$.fn.uparallax = function (args) {
		var isMethod = typeof args === 'string',
			callArgs = isMethod ? Array.prototype.slice.call(arguments, 1) : [],
			result
		;

		this.each(function () {
			var $el = $(this),
				object = $el.data('uparallax')
			;

			if (object) {
				if (isMethod) {
					result = object.callMethod(args, callArgs);
				}
			}
			else {
				if (isMethod) {
					$.error('Can\'t call the method ' + args + '. The object is not initialized');
				}
				else {
					// Initialize object
					args.bgColor = rgba_to_rba( $el.parent().css("background-color") );
					$el.data('uparallax', new Upfront_Parallax($el, args));
				}
			}
		});

		if (this.length == 1 & typeof result != 'undefined') {
			return result;
		}
		return this;
	};

	var Upfront_Parallax = function ($el, args) {
		var me = this,
			data = $.extend({
				autostart: true,
				element: '',
				effect: 'scroll', // Available: scroll, rotate, scale, opacity
				movement: 30, // px
				rotation: 15, // degrees
				scaling: 1.1,
				opacity: 0.5,
				renderer: this.getDefaultRenderer(), // Available: canvas, absolute, fixed,
				overflowTop: 100, // px, render more than the background height to prevent artifact on late refresh
				overflowBottom: 100, // px, render more than the background height to prevent artifact on late refresh
				bgColor: "#fff"
			}, args)
		;
		this.opts = data;
		this.$parent = $el.parent();
		this.$element = $el;
		this.$moveElement = typeof this.opts.element === 'string' ? $el.find(this.opts.element) : this.opts.element;

		Upfront_Parallax.id++;
		this.id = Upfront_Parallax.id;
		Upfront_Parallax.instances[this.id] = this;

		if (this.opts.autostart) {
			this.start();
		}
	};

	// Static ID
	Upfront_Parallax.id = 0;
	Upfront_Parallax.instances = {};
	Upfront_Parallax.prevTime = 0;
	Upfront_Parallax.started = false;
	Upfront_Parallax.cache = {
		lastScrollTop: -1,
		scrollTop: 0,
		winHeight: 0,
		scrollBottom: 0
	};
	Upfront_Parallax.canvas = false;
	Upfront_Parallax.context = false;
	Upfront_Parallax.start = function () {
		if (Upfront_Parallax.started) return;
		Upfront_Parallax.started = true;
		Upfront_Parallax.draw();
	};
	Upfront_Parallax.draw = function (time) {
		var scrollTop = Upfront_Parallax.cache.scrollTop;
		if (
			Upfront_Parallax.cache.lastScrollTop == scrollTop
			&&
			time - Upfront_Parallax.prevTime < 5000 // Re-draw every 5 second
		) {
			requestAnimationFrame(Upfront_Parallax.draw);
			return;
		}
		var winHeight = $(window).height(),
			scrollBottom = Math.round(scrollTop + winHeight);
		Upfront_Parallax.cache.lastScrollTop = scrollTop;
		Upfront_Parallax.cache.winHeight = winHeight;
		Upfront_Parallax.cache.scrollBottom = scrollBottom;

		for (var id in Upfront_Parallax.instances) {
			Upfront_Parallax.instances[id].draw(time);
		}
		Upfront_Parallax.prevTime = time;
		requestAnimationFrame(Upfront_Parallax.draw);
	};
	Upfront_Parallax.updateScroll = function (e) {
		var scrollTop = window.pageYOffset;
		Upfront_Parallax.cache.scrollTop = scrollTop;
	};
	$(window).one('load.upfront_paralax', Upfront_Parallax.updateScroll);
	$(window).on('load.upfront_paralax', Upfront_Parallax.draw);
	$(window).on('scroll.upfront_paralax', Upfront_Parallax.updateScroll);

	Upfront_Parallax.prototype = {
		cache: {},
		canvas: false,
		context: false,
		imgCanvas: false,
		imgContext: false,
		callMethod: function (method, args) {
			switch (method) {
				case 'start':
					this.start();
					break;
				case 'stop':
					this.stop();
					break;
				case 'destroy':
					this.destroy();
					break;
				case 'refresh':
					this.refresh();
					break;
				case 'setOption':
					this.setOption(args[0], args[1]);
					break;
				case 'setEffect':
					this.setOption('effect', args[0]);
					break;
				case 'setMovement':
					this.setOption('movement', args[0]);
					break;
				case 'setOpacity':
					this.setOption('opacity', args[0]);
					break;
				case 'setRotation':
					this.setOption('rotation', args[0]);
					break;
				case 'setScaling':
					this.setOption('scaling', args[0]);
					break;
			}
		},
		bindEvents: function () {
			//$(window).on('scroll.upfront_parallax_' + this.id, $.proxy(this.update, this));
			$(window).on('load.upfront_parallax_' + this.id, $.proxy(this.refresh, this));
			$(window).on('resize.upfront_parallax_' + this.id, $.proxy(this.refresh, this));
		},
		unbindEvents: function () {
			//$(window).off('scroll.upfront_parallax_' + this.id);
			$(window).off('load.upfront_parallax_' + this.id);
			$(window).off('resize.upfront_parallax_' + this.id);
		},
		setOption: function (option, value) {
			this.opts[option] = value;
			this.refresh();
		},
		getDefaultRenderer: function () {
			return 'canvas';
		},
		start: function () {
			this.$element.addClass('upfront-parallax');
			this.$moveElement.addClass('upfront-parallax-element');
			this.reset_cache();
			if ('fixed' == this.opts.renderer) {
				this.prepareFixedPos();
			}
			else if ('canvas' == this.opts.renderer) {
				this.prepareCanvas();
			}
			this.refresh();
			this.bindEvents();
			Upfront_Parallax.start();
		},
		stop: function () {
			this.$element.removeClass('upfront-parallax');
			this.$moveElement.removeClass('upfront-parallax-element');
			if ('fixed' == this.opts.renderer) {
				this.restorePos();
			}
			else if ('canvas' == this.opts.renderer) {
				this.removeCanvas();
			}
			this.reset();
			this.unbindEvents();
		},
		reset_cache: function() {
			this.cache = {
				translate: 0,
				offsetTop: 0,
				offsetBottom: 0,
				offsetLeft: 0,
				height: 0,
				width: 0,
				visible: true,
				img: false,
				imgCanvas: false,
				imgContext: false
			};
		},
		reset: function () {
			this.$moveElement.css({
				transform: '',
				opacity: '',
				top: '',
				bottom: ''
			});
		},
		destroy: function () {
			this.stop();
			delete Upfront_Parallax.instances[this.id];
			this.$element.removeData('uparallax');
		},
		prepareFixedPos: function () {
			this.$element.css({
				position: 'fixed',
				top: 0,
				left: 0
			});
		},
		restorePos: function () {
			this.$element.css({
				position: '',
				top: '',
				left: '',
				transform: ''
			});
		},
		prepareCanvas: function () {
			if (this.canvas === false) {
				this.canvas = document.createElement('canvas');
				this.canvas.id = 'uparallax-' + this.id;
				$(this.canvas).css({
					position: 'fixed',
					top: 0,
					left: 0,
					zIndex: -1,
					display: 'block',
					pointerEvents: 'none'
				});
				$('.upfront-output-layout, .upfront-layout').append(this.canvas);
			}
			this.context = this.canvas.getContext('2d');
			if( this.is_image_png() )
				this.context.fillStyle = this.opts.bgColor;
			this.updateCanvas();
		},
		updateCanvas: function () {
			if (this.canvas === false) return;
			this.canvas.width = $(window).width();
			this.canvas.height = $(window).height();
		},
		removeCanvas: function () {
			// this.canvas.remove(); // This does not work on IE11 and crash the UF editor
			$(this.canvas).remove();
		},
		prepareImage: function () {
			if (this.cache.img) {
				if (!this.imgCanvas) this.renderImage();
				this.$element.css('display', 'none');
				return;
			}
			var me = this,
				img = new Image(),
				src = this.$moveElement.css('background-image').replace(/^url\(\s*['"]?\s*/, '').replace(/\s*['"]?\s*\)$/, ''),
				position = this.$moveElement.css('background-position').split(' ')
			;

			// Convert percent to decimal.
			this.size_percentage = parseInt(this.$moveElement.css('background-size'), 10) * 0.01;
			// Get user set positions (convert percentage to decimal).
			this.percent_x = parseInt(position[0], 10) * 0.01;
			this.percent_y = parseInt(position[1], 10) * 0.01;

			// Check if scaling is NaN, if it is, we set default parameter
			if ( isNaN(this.size_percentage) ) {
				this.size_percentage = 1;
				this.percent_x = 0.5;
				this.percent_y = 0.5;
			}

			if (src != 'none') {
				this.cache.img = img;
				this.cache.background_color = this.$parent.css("background-color") || "#fff";
				img.src = src;
				this.$element.css('display', 'none');
				this.$parent.css({
					background: 'none'
				});
			}
		},
		renderImage: function () {
			if (!this.cache.img) return;
			if (!this.imgCanvas) {
				this.imgCanvas = document.createElement('canvas');
				$(this.imgCanvas).css({
					display: 'block'
				});

				this.imgContext = this.imgCanvas.getContext('2d', {alpha: false});
			}
			var width = this.cache.width,
				height = this.cache.height,
				parallaxHeight = height + (this.movementOffset*2),
				winHeight = Upfront_Parallax.cache.winHeight,
				ratio = this.cache.img.height/this.cache.img.width,
				imgWidth = width,
				imgHeight = parallaxHeight,
				imgY = 0,
				drawWidth = 0,
				drawHeight = 0,
				drawX = 0,
				drawY = 0
			;
			this.imgCanvas.width = width;
			this.imgCanvas.height = parallaxHeight;
			if (parallaxHeight/width > ratio) {
				imgWidth = parallaxHeight/ratio;
				drawWidth = Math.floor(width/imgWidth * this.cache.img.width);
			}
			else {
				imgHeight = width*ratio;
				drawWidth = this.cache.img.width;
			}
			imgY = (height-imgHeight) / 2;
			drawHeight = Math.floor(parallaxHeight/imgHeight * this.cache.img.height);
			drawX = (this.cache.img.width - drawWidth) / 2;
			drawY = (this.cache.img.height - drawHeight) / 2;
			scale = this.size_percentage;
			// Offset X and Y by user set position.
			position_x = (-0.5 * width * scale) + (width * scale * this.percent_x);
			position_y = (-0.5 * height * scale) + (height * scale * this.percent_y);

			if ( this.is_image_png() ) {
				this.fillCanvas(width, parallaxHeight);
			}

			try {
				this.imgContext.drawImage(this.cache.img, drawX, drawY, drawWidth, drawHeight, position_x, position_y, (width * scale), (parallaxHeight * scale));
			} catch (e) {
				Upfront.Util.log('Broken image provided for Parallax');
			}

		},
		refresh: function () {
			this.refreshCache();
			var height = this.cache.height,
				winHeight = $(window).height(),
				heightOff =  Math.round((winHeight - height) / 2)
			;
			if (heightOff - this.opts.movement > this.opts.movement) {
				this.movementOffset = heightOff - this.opts.movement;
			}
			else {
				this.movementOffset = this.opts.movement;
			}
			/*
			 * this.$moveElement must have position absolute, with top and bottom set to 0 initially, height auto
			 * */
			this.$moveElement.css({
				top: this.movementOffset*-1,
				bottom: this.movementOffset*-1
				//height: height+this.movementOffset*2
			});
			if ('fixed' == this.opts.renderer) {
				this.$element.css({
					left: this.cache.offsetLeft,
					height: this.cache.height,
					width: this.cache.width
				});
			}
			else if ('canvas' == this.opts.renderer) {
				this.updateCanvas();
				this.renderImage();
			}
			this.update();
		},
		refreshCache: function () {
			var offset = this.$parent.offset(),
				height = this.$parent.height(),
				width = this.$parent.width()
			;
			this.cache.offsetTop = offset.top;
			this.cache.offsetBottom = offset.top + height;
			this.cache.offsetLeft = offset.left;
			this.cache.height = height;
			this.cache.width = width;
		},
		update: function () {
			requestAnimationFrame($.proxy(this.draw, this));
		},
		draw: function (time) {
			if ( !(this.id in Upfront_Parallax.instances) ) return;
			var offsetTop = this.cache.offsetTop,
				offsetBottom = this.cache.offsetBottom,
				height = this.cache.height,
				scrollTop = Upfront_Parallax.cache.scrollTop,
				scrollBottom = Upfront_Parallax.cache.scrollBottom,
				winHeight = Upfront_Parallax.cache.winHeight,
				moveHeight = (this.movementOffset * 2) + (this.opts.movement * 2),
				range = 2 * this.movementOffset,
				movement = (this.movementOffset > 0 ? range / moveHeight : 1),
				translate = Math.round(movement * (scrollBottom - offsetTop - height)) - this.movementOffset,
				maxTranslate = Math.round(movement * (winHeight)) - this.movementOffset,
				minTranslate = maxTranslate*-1,
				effects = this.opts.effect.split(','),
				transform = ''
			;
			if ('canvas' == this.opts.renderer) {
				this.prepareImage();
				if (!this.cache.img) return;
			}
			if (offsetBottom > scrollTop && offsetTop < scrollBottom) {
				if ('fixed' == this.opts.renderer) {
					if (!this.cache.visible) {
						this.$element.css('visibility', 'visible');
					}
					this.$element.css({
						//transform: 'translate3d(0, ' + (offsetTop-scrollTop) + 'px, 0)'
						transform: 'translateY(' + (offsetTop-scrollTop) + 'px)'
					});
				}
				this.cache.visible = true;
			}
			else {
				if (this.cache.visible) {
					if ('fixed' == this.opts.renderer) {
						this.$element.css({
							visibility: 'hidden'
						});
					}
					else if ('canvas' == this.opts.renderer) {
						this.clearCanvas();
					}
					this.cache.visible = false;
				}
			}
			if (translate > maxTranslate) {
				translate = maxTranslate;
			}
			else if (translate < minTranslate) {
				translate = minTranslate;
			}

			if (!this.cache.visible) return;
			this.cache.translate = translate;

			if ('canvas' == this.opts.renderer) {
				this.drawCanvas(translate, maxTranslate);
			}
			else {
				for (var i in effects) {
					var effect = this.getEffect(effects[i], translate, maxTranslate);
					if (effect.property == 'transform') {
						transform += (transform == '' ? '' : ' ');
						transform += effect.value;
					}
					else {
						this.$moveElement.css(effect.property, effect.value);
					}
				}
				if (transform !== '') {
					this.$moveElement.css('transform', transform);
				}
			}
		},
		drawCanvas: function (translate, maxTranslate) {
			if (!this.cache.img || !this.imgCanvas) return;
			var offsetTop = this.cache.offsetTop,
				offsetBottom = this.cache.offsetBottom,
				offsetLeft = this.cache.offsetLeft,
				width = this.cache.width,
				height = this.cache.height,
				parallaxHeight = height + (this.movementOffset*2),
				scrollTop = Upfront_Parallax.cache.scrollTop,
				scrollBottom = Upfront_Parallax.cache.scrollBottom,
				winHeight = Upfront_Parallax.cache.winHeight,
				visibleHeight = height,
				ratio = this.cache.img.height/this.cache.img.width,
				imgWidth = width,
				imgHeight = parallaxHeight,
				imgY = 0,
				drawWidth = 0,
				drawHeight = 0,
				drawVisibleHeight = 0,
				drawX = 0,
				drawY = 0,
				drawRelY = 0,
				closest = this.findClosestInstances(),
				clearTop = offsetTop,
				clearBottom = offsetBottom
			;
			if (offsetTop < scrollTop) {
				visibleHeight = offsetBottom - scrollTop;
			}
			else if (offsetBottom > scrollBottom) {
				visibleHeight = scrollBottom - offsetTop;
			}
			visibleHeight = Math.min(winHeight, visibleHeight);
			drawY = (parallaxHeight > height ? Math.round((parallaxHeight - height) / 2) : 0);
			if (offsetTop < scrollTop) {
				drawRelY = scrollTop - offsetTop;
				drawY += drawRelY;
			}

			drawY += translate * -1;
			if (closest.top && closest.top.cache.offsetBottom < offsetTop) {
				clearTop -= Math.min(this.opts.overflowTop, Math.ceil((offsetTop - closest.top.cache.offsetBottom) / 2));
			}
			else if (!closest.top) {
				clearTop -= this.opts.overflowTop;
			}
			if (closest.bottom && closest.bottom.cache.offsetTop > offsetBottom) {
				clearBottom += Math.min(this.opts.overflowBottom, Math.floor((closest.bottom.cache.offsetTop - offsetBottom) / 2));
			}
			else if (!closest.bottom) {
				clearBottom += this.opts.overflowBottom;
			}

			this.context.drawImage(this.imgCanvas, 0, 0, width, parallaxHeight, offsetLeft, offsetTop-this.movementOffset-scrollTop+translate, width, parallaxHeight);

			if (clearTop > scrollTop) {
				this.context.clearRect(offsetLeft, 0, width, clearTop-scrollTop);
			}
			if (winHeight > clearBottom-scrollTop) {
				this.context.clearRect(offsetLeft, clearBottom-scrollTop, width, winHeight-(clearBottom-scrollTop));
			}
		},
		/**
		 * Checks if image src image in png
		 * @returns {boolean|*|Array|{index: number, input: string}}
         */
		is_image_png: function(){
			return this.cache.img && this.cache.img.src && this.cache.img.src.toLowerCase().match(/.png/);
		},
		fillCanvas: function(width, parallaxHeight){
			this.imgContext.fillStyle = this.opts.bgColor;
			this.imgContext.rect(0, 0, width, parallaxHeight);
			this.imgContext.fill();
		},
		clearCanvas: function () {
			this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
		},
		findClosestInstances: function () {
			var current = false,
				closestTop = false,
				closestBottom = false
			;
			for (var id in Upfront_Parallax.instances) {
				current = Upfront_Parallax.instances[id];
				if (current.id == this.id) continue;
				if (current.cache.offsetBottom <= this.cache.offsetTop) {
					if (closestTop !== false && closestTop.cache.offsetBottom > current.cache.offsetBottom) continue;
					closestTop = current;
				}
				else if (current.cache.offsetTop >= this.cache.offsetBottom) {
					if (closestBottom !== false && closestBottom.cache.offsetTop < current.cache.offsetTop) continue;
					closestBottom = current;
				}
			}
			return {
				top: closestTop,
				bottom: closestBottom
			};
		},
		getEffect: function (effect, translate, maxTranslate) {
			var property = 'transform',
				value = '',
				position = translate/maxTranslate
			;
			switch (effect) {
				case 'scroll':
					//value = 'translate3d(0, ' + translate + 'px, 0)';
					value = 'translateY(' + translate + 'px)';
					//property = 'margin-top';
					//value = translate;
					break;
				case 'rotate':
					value = 'rotate(' + (position*this.opts.rotation) + 'deg)';
					break;
				case 'scale':
					value = 'scale(' + (1 - ( (1-this.opts.scaling) * Math.abs(position) )) + ')';
					break;
				case 'opacity':
					property = 'opacity';
					value = 1 - ( (1-this.opts.opacity) * Math.abs(position) );
					break;
			}
			return {
				property: property,
				value: value
			};
		}
	};

}( jQuery ));

/* upfront-default-map */
// If Google Maps has Authentication error (must be global function).
function gm_authFailure() {return google_maps_auth_error = true};
(function($){
	var throttle = function(a,b,c){var d,e,f,g=null,h=0;c||(c={});var i=function(){h=c.leading===!1?0:new Date().getTime(),g=null,f=a.apply(d,e),g||(d=e=null)};return function(){var j=new Date().getTime();h||c.leading!==!1||(h=j);var k=b-(j-h);return d=this,e=arguments,0>=k||k>b?(clearTimeout(g),g=null,h=j,f=a.apply(d,e),g||(d=e=null)):g||c.trailing===!1||(g=setTimeout(i,k)),f}};

	function init_map ($el) {
		if ( $el.data('map') )
			return;
		var data = JSON.parse($el.attr('data-bg-map')),
			options = {
				center: new google.maps.LatLng(data.center[0], data.center[1]),
				zoom: parseInt(data.zoom, 10) || 0,
				mapTypeId: google.maps.MapTypeId[data.style],
				panControl: (data.controls && data.controls.indexOf("pan") >= 0),
				zoomControl: (data.controls && data.controls.indexOf("zoom") >= 0),
				mapTypeControl: (data.controls && data.controls.indexOf("map_type") >= 0),
				scaleControl: (data.controls && data.controls.indexOf("scale") >= 0),
				streetViewControl: (data.controls && data.controls.indexOf("street_view") >= 0),
				overviewMapControl: (data.controls && data.controls.indexOf("overview_map") >= 0),
				scrollwheel: false,
				styles: (data.use_custom_map_code ? JSON.parse(data.styles) || false : false)
			},
			map = new google.maps.Map($el.get(0), options)
		;
		$el.data('map', map);
		if (!!data.show_markers) {
			var mrk = new google.maps.Marker({
				position: options.center,
				draggable: false,
				map: map
			});
		}
	}

	function load_google_maps () {
		if ($(document).data("upfront-google_maps-loading")) return false;
		$(document).data("upfront-google_maps-loading", true);
		if (typeof google === 'object' && typeof google.maps === 'object' && typeof google.maps.Map === 'object') return upfront_bg_map_init();
		var protocol = '',
			key = (window._upfront_api_keys || {})['gmaps'] || false,
			script = document.createElement("script")
		;
		try { protocol = document.location.protocol; } catch (e) { protocol = 'http:'; }
		key = key ? '&key=' + key : '';
		script.type = "text/javascript";
		script.src = protocol + "//maps.google.com/maps/api/js?v=4" + key + "&libraries=places&sensor=false&callback=upfront_maps_loaded";
		document.body.appendChild(script);
	}

	function upfront_bg_map_init () {
		$("[data-bg-map]").each(function () {
			if ( $(this).css('display') != 'none' )
				init_map($(this));
		});
	}

	function init () {
		if (!("Upfront" in window || $("[data-bg-map]").length)) {
			// No Upfront object, no region maps - nothing to do
			return false;
		}

		$(document).on('upfront-google_maps-loaded', upfront_bg_map_init);
		var lazyUpfrontBgMapInit = throttle(upfront_bg_map_init, 100);

		if (!window.upfront_maps_loaded) {
			window.upfront_maps_loaded = window.upfront_maps_loaded || function () {
				$(document).trigger("upfront-google_maps-loaded");
				$(document).data("upfront-google_maps-loading", false);
				$(window).on('resize', lazyUpfrontBgMapInit);
			};
			load_google_maps();
		}
	}

	$(init);

})(jQuery);

/* upfront-default-slider */
(function( $ ) {
	var throttle = function(a,b,c){var d,e,f,g=null,h=0;c||(c={});var i=function(){h=c.leading===!1?0:new Date().getTime(),g=null,f=a.apply(d,e),g||(d=e=null)};return function(){var j=new Date().getTime();h||c.leading!==!1||(h=j);var k=b-(j-h);return d=this,e=arguments,0>=k||k>b?(clearTimeout(g),g=null,h=j,f=a.apply(d,e),g||(d=e=null)):g||c.trailing===!1||(g=setTimeout(i,k)),f}};

	$.fn.upfront_default_slider = function (args) {
		var isMethod = typeof args === 'string',
			result
		;

		this.each(function(){
			var $slider = $(this),
				uslider = $slider.data('uslider')
			;

			if(uslider){
				if(isMethod)
					result = uslider.callMethod(args);
			}
			else{
				if(isMethod)
					$.error('Can\'t call the ueditor method ' + args + '. The slider is not initialized');
				else {
					// Initialize slider
					$slider.data('uslider', new JQueryUslider($slider, args));
				}
			}
		});

		if( this.length == 1 & typeof result != 'undefined')
			return result;
		return this;
	};


	var JQueryUslider = function($slider, args){
		//debugger;
		var me = this,
			data = $.extend({
				auto: true,
				interval: 5000, // in ms
				auto_height: true, // true | false
				control: 'outside', // outside | inside
				control_num: true,
				control_next_prev: true,
				show_control: 'always', //  always | hover
				effect: 'crossfade', // crossfade | slide-down | slide-up | slide-left | slide-right
				classname: {
					slider: 'upfront-default-slider',
					slider_wrap: 'upfront-default-slider-wrap',
					item: 'upfront-default-slider-item',
					nav: 'upfront-default-slider-nav',
					nav_item: 'upfront-default-slider-nav-item',
					prev: 'upfront-default-slider-nav-prev',
					next: 'upfront-default-slider-nav-next'
				},
				adjust_slide_size: true,
				starting_slide: 0,
				caption_height: false
			}, args),
			$items = data.item ? $slider.find('>'+data.item) : $slider.find('>.'+data.classname.item)
		;

		this.$slider = $slider.data('slider-applied', true)
			.addClass(data.classname.slider)
			.append('<div class="' + data.classname.slider_wrap + '" />')
		;

		this.opts = data;
		this.index = 0;
		this.pause = false;
		this.timer = false;

		this.update_configs();
		this.update_items($items);

		this.$slider.append($('<div class="' + data.classname.nav + '" />'));
		this.update_nav();

		// Next and previous navigation
		if ( data.control_next_prev )
			this.prev_next_navigation();
		
		// Control slides with arrow keys
		if ( data.keyboard_control )
			this.keyboard_controls();

		this.slider_switch(data.starting_slide);
		this.update_auto_slide();

		this.bind_events();

		this.$slider.trigger('rendered');
	};

	JQueryUslider.prototype = {
		callMethod: function(method){
			switch(method) {
				case 'next':
					this.next();
					break;
				case 'prev':
					this.prev();
					break;
			}
		},

		update_configs: function(){
			var $slider = this.$slider,
				slider_auto = $slider.attr('data-slider-auto'),
				data = this.opts
			;
			$slider.removeClass(data.classname.slider + '-control-' + data.control);
			$slider.removeClass(data.classname.slider + '-control-' + data.show_control);

			if ( typeof slider_auto != 'string' ) {
				slider_auto = data.auto;
			} else {
				slider_auto = slider_auto == '0' ? false : true;
			}

			data.auto = slider_auto;
			data.interval = parseInt($slider.attr('data-slider-interval') || data.interval, 10);
			data.effect = $slider.attr('data-slider-effect') || data.effect;
			data.control = $slider.attr('data-slider-control') || data.control;
			data.show_control = $slider.attr('data-slider-show-control') || data.show_control;
			data.caption_height = parseInt($slider.attr('data-caption_height') || data.caption_height, 10) === 1;
			$slider.addClass(data.classname.slider + '-control-' + data.control);
			$slider.addClass(data.classname.slider + '-control-' + data.show_control);
		},

		update_items: function($new_items){
			var $slider = this.$slider,
				data = this.opts,
				$slider_wrap = $slider.find('.' + data.classname.slider_wrap)
			;
			this.items = $new_items;

			$slider_wrap.html('')
				.append(this.items)
			;

			//add texts
			this.items.each(function(idx, item){
				var slide = $(item),
					captionSelector = slide.data('caption-selector'),
					caption = slide.data('caption'),
					text = slide.find('.uslide-caption')
				;
				if(captionSelector || caption){
					if(!text.length){
						text = $('<div class="uslide-caption" />');
						slide.append(text);
					}
					if(captionSelector) {
						text.html($(captionSelector).html());
					} else {
						text.html(caption);
					}
				} else if(text.length) {
					text.remove();
				}
			});

			this.items.addClass(data.classname.item);
			if ( data.auto_height ){ // Auto height adjustment to the highest slide
				this.calc_height();
				$slider.find('img').one('load', $.proxy(this.calc_height, this));
			}
			else if(data.adjust_slide_size) { // Adjust slides to available space
				this.adjust_slide_size();
			}
		},

		calc_height: function(){
			var me = this,
				max_height
			;
			this.$slider.css('height', 9999);
			this.items.each(function(){
				var $img = $(this).find('.uslide-image'),
					$text = $(this).find('.uslide-caption'),
					textHeight = me.opts.caption_height ? $text.outerHeight(true) : 0,
					img_h = $img.outerHeight(true) + textHeight
				;
				max_height = max_height > img_h ? max_height : img_h;
			});
			this.$slider.css({
				'padding-top': Math.ceil(max_height/15)*15,
				'height': 'auto'
			});
		},

		adjust_slide_size: function(){
			var height = this.$slider.outerHeight(),
				width = this.$slider.outerWidth()
			;

			this.items.each(function(){
				var $img = $(this).find('img'),
					img_h, img_w
				;
				$img.css({ height: "", width: "" });
				img_h = $img.height();
				img_w = $img.width();
				if ( height/width > img_h/img_w )
					$img.css({ height: '100%', width: 'auto', marginLeft: (width-Math.round(height/img_h*img_w))/2, marginTop: "" });
				else
					$img.css({ height: 'auto', width: '100%', marginLeft: "", marginTop: (height-Math.round(width/img_w*img_h))/2 });
			});
		},

		update_nav: function(){
			var me = this,
				data = this.opts,
				$nav = this.$slider.find('.' + data.classname.nav)
			;
			$nav.html('');
			if ( data.control_num ){
				this.items.each(function(index){
					$nav.append('<i class="' + data.classname.nav_item + ' uslider-dotnav-' + index + '" data-slider-index="' + index + '">'+index+'</i>');
				});

				this.$slider.on('click', '.'+data.classname.nav_item, function(e){
					e.preventDefault();
					var index = $(this).data('slider-index');
					me.slider_switch(index);
					me.pause = true;
				});
			}
		},
		
		keyboard_controls: function() {
			var me = this,
				data = this.opts,
				$slider = this.$slider.closest('.uslider')
			;
			
			// Handle key press
			$slider.keydown(function(e) {
				// Previous slide
				if (e.which == 37) {
					me.prev();
				}
				
				// Next slide
				if (e.which == 39) {
					me.next();
				}
			});
		},

		prev_next_navigation: function(){
			var me = this,
				data = this.opts
			;
			this.$slider.append('<div class="' + data.classname.prev + '" /><div class="' + data.classname.next + '" />')
				.on('click', '.'+data.classname.prev, function(e){
					e.preventDefault();
					me.prev();
				})
				.on('click', '.'+data.classname.next, function(e){
					e.preventDefault();
					me.next();
				})
			;
		},

		next: function(){
			var data = this.opts,
				fx = data.effect
			;
			this.slider_switch(this.index+1 >= this.items.length ? 0 : this.index+1, false, fx);
			this.pause = true;
		},

		prev: function(){
			var data = this.opts,
				fx = (
					data.effect == 'slide-left' ? 'slide-right' : (
						data.effect == 'slide-right' ? 'slide-left' : (
							data.effect == 'slide-down' ? 'slide-up' : (
								data.effect == 'slide-up' ? 'slide-down' : 'crossfade'
							)
						)
					)
				)
			;
			this.slider_switch(this.index > 0 ? this.index-1 : this.items.length-1, false, fx);
			this.pause = true;
		},

		slider_switch: function(index, is_auto, effect){
			var data = this.opts,
				$nav = this.$slider.find(data.classname.nav),
				$slider = this.$slider,
				$n = $nav.find('.'+data.classname.nav_item).eq(index),
				$item = this.items.eq(index),
				current = $slider.find('.'+data.classname.item+'-current'),
				event_end = 'animationend.slider webkitAnimationEnd.slider MSAnimationEnd.slider oAnimationEnd.slider webkitTransitionEnd.slider otransitionend.slider oTransitionEnd.slider msTransitionEnd.slider transitionend.slider'
			;
			if(!effect)
				effect = data.effect;

			if ( !$item.hasClass(data.classname.item+'-current') && !(is_auto && this.pause) ){
				$slider.trigger('slideout', current)
					.find('div.slide-previous').removeClass('slide-previous');
				current.removeClass(data.classname.item+'-current').addClass('slide-previous');
				$item.addClass(data.classname.item+'-current');
				$nav.find('.'+data.classname.nav_item+'-selected').removeClass(data.classname.nav_item+'-selected');
				$n.addClass(data.classname.nav_item+'-selected');
				this.index = index;
				// Animation effect
				$item.addClass(data.classname.item+'-effect-'+effect);
				$item.one(event_end, function () {
					$(this).removeClass(data.classname.item+'-effect-'+effect);
					if($item.hasClass(data.classname.item+'-current'))
						$slider.trigger('slidein', [$item, index]);
					$item.off(event_end);
				});
				
				$slider.find('.upfront-default-slider-nav-item').removeClass('uslider-dotnav-current');
				$slider.find('.uslider-dotnav-' + index).addClass('uslider-dotnav-current');
			}

			this.pause = false;
		},

		update_auto_slide: function() {
			var me = this,
				data = this.opts
			;
			if ( this.timer )
				clearInterval(this.timer);
			if ( data.auto && data.interval > 999 ){
				this.timer = setInterval(function(){
					me.slider_switch( me.index+1 >= me.items.length ? 0 : me.index+1, true );
				}, data.interval);
			}
		},

		bind_events: function(){
			var me = this,
				$slider = me.$slider,
				data = me.opts
			;
			$slider.on('refresh', function(){
				var $new_items = data.item ? $slider.find('>'+data.item) : $slider.find('>.'+data.classname.item),
					new_length = $new_items.length,
					length = me.items.length
				;
				me.update_configs();
				me.update_auto_slide();
				if ( new_length ){
					me.update_items($new_items);
					me.update_nav();
					if ( new_length != length ) {
						me.slider_switch(data.starting_slide);
					}
				}
				else {
					if ( data.auto_height ) {
						me.calc_height();
					}
				}
				if ( !data.auto_height && data.adjust_slide_size){
					me.adjust_slide_size();
					me.items.find('img').one('load', $.proxy(me.adjust_slide_size, me));
				}
			})
			.on('pause', function(){
				clearInterval(me.timer);
			})
			.on('resume', function(){
				me.update_auto_slide();
			});
		}
	};

	$(document).ready(function(){
		// Inline post slider setup
		var inline_slider = {
			item: '.upfront-inserted_image-wrapper',
			control_next_prev: false
		};
		$('.upfront-inline_post-slider').upfront_default_slider(inline_slider);

		// Bg slider
		var bg_slider = {
				auto_height: false,
				control: 'inside'
			},
			init_bg_slider = function () {
				$('.upfront-bg-slider').each(function(){
					if ( $(this).closest('.upfront-output-bg-overlay').css('display') != 'none' )
						$(this).upfront_default_slider(bg_slider);
				});
			};
		init_bg_slider();

		// Refresh size on window.load and window.resize
		$(window).on('load', function(){
			$('.upfront-inline_post-slider, .upfront-bg-slider').trigger('refresh');
		});
		var lazyInitBgSlider = throttle(function(){
			init_bg_slider();
			$('.upfront-inline_post-slider, .upfront-bg-slider').trigger('refresh');
		}, 100);
		$(window).on('resize', lazyInitBgSlider);

		// Integration with Upfront editor
		$(document).on('upfront-load', function(){
			Upfront.Events.on('application:mode:after_switch', function(){
				$('.upfront-inline_post-slider').upfront_default_slider(inline_slider);
			});
			Upfront.Events.on('entity:background:update', function(view, model){
				var $s = view.$el.find('.upfront-region-bg-slider');
				if ( $s.length ){
					$s.each(function(){
						if ( $(this).data('slider-applied') )
							$(this).trigger('refresh');
						else
							$(this).upfront_default_slider(bg_slider);
					});
				}
			});
		});

		/*
		CKEDITOR.on('currentInstance', function(){
			editor = CKEDITOR.currentInstance;
			//$('.upfront-inline_post-slider').upfront_default_slider(inline_slider);
			if ( !editor )
				return;
			editor.on('insertHtml', function(){
			//	$('.upfront-inline_post-slider').upfront_default_slider(inline_slider);
			});
		}); */
	});

}( jQuery ));

/* jquery-plugin */
/* Simple JavaScript Inheritance
 * By John Resig http://ejohn.org/
 * MIT Licensed.
 */
// Inspired by base2 and Prototype
(function(){
	var initializing = false;

	// The base JQClass implementation (does nothing)
	window.JQClass = function(){};

	// Collection of derived classes
	JQClass.classes = {};
 
	// Create a new JQClass that inherits from this class
	JQClass.extend = function extender(prop) {
		var base = this.prototype;

		// Instantiate a base class (but only create the instance,
		// don't run the init constructor)
		initializing = true;
		var prototype = new this();
		initializing = false;

		// Copy the properties over onto the new prototype
		for (var name in prop) {
			// Check if we're overwriting an existing function
			prototype[name] = typeof prop[name] == 'function' &&
				typeof base[name] == 'function' ?
				(function(name, fn){
					return function() {
						var __super = this._super;

						// Add a new ._super() method that is the same method
						// but on the super-class
						this._super = function(args) {
							return base[name].apply(this, args || []);
						};

						var ret = fn.apply(this, arguments);				

						// The method only need to be bound temporarily, so we
						// remove it when we're done executing
						this._super = __super;

						return ret;
					};
				})(name, prop[name]) :
				prop[name];
		}

		// The dummy class constructor
		function JQClass() {
			// All construction is actually done in the init method
			if (!initializing && this._init) {
				this._init.apply(this, arguments);
			}
		}

		// Populate our constructed prototype object
		JQClass.prototype = prototype;

		// Enforce the constructor to be what we expect
		JQClass.prototype.constructor = JQClass;

		// And make this class extendable
		JQClass.extend = extender;

		return JQClass;
	};
})();

(function($) { // Ensure $, encapsulate

	/** Abstract base class for collection plugins v1.0.1.
		Written by Keith Wood (kbwood{at}iinet.com.au) December 2013.
		Licensed under the MIT (http://keith-wood.name/licence.html) license.
		@module $.JQPlugin
		@abstract */
	JQClass.classes.JQPlugin = JQClass.extend({

		/** Name to identify this plugin.
			@example name: 'tabs' */
		name: 'plugin',

		/** Default options for instances of this plugin (default: {}).
			@example defaultOptions: {
 	selectedClass: 'selected',
 	triggers: 'click'
 } */
		defaultOptions: {},
		
		/** Options dependent on the locale.
			Indexed by language and (optional) country code, with '' denoting the default language (English/US).
			@example regionalOptions: {
	'': {
		greeting: 'Hi'
	}
 } */
		regionalOptions: {},
		
		/** Names of getter methods - those that can't be chained (default: []).
			@example _getters: ['activeTab'] */
		_getters: [],

		/** Retrieve a marker class for affected elements.
			@private
			@return {string} The marker class. */
		_getMarker: function() {
			return 'is-' + this.name;
		},
		
		/** Initialise the plugin.
			Create the jQuery bridge - plugin name <code>xyz</code>
			produces <code>$.xyz</code> and <code>$.fn.xyz</code>. */
		_init: function() {
			// Apply default localisations
			$.extend(this.defaultOptions, (this.regionalOptions && this.regionalOptions['']) || {});
			// Camel-case the name
			var jqName = camelCase(this.name);
			// Expose jQuery singleton manager
			$[jqName] = this;
			// Expose jQuery collection plugin
			$.fn[jqName] = function(options) {
				var otherArgs = Array.prototype.slice.call(arguments, 1);
				if ($[jqName]._isNotChained(options, otherArgs)) {
					return $[jqName][options].apply($[jqName], [this[0]].concat(otherArgs));
				}
				return this.each(function() {
					if (typeof options === 'string') {
						if (options[0] === '_' || !$[jqName][options]) {
							throw 'Unknown method: ' + options;
						}
						$[jqName][options].apply($[jqName], [this].concat(otherArgs));
					}
					else {
						$[jqName]._attach(this, options);
					}
				});
			};
		},

		/** Set default values for all subsequent instances.
			@param options {object} The new default options.
			@example $.plugin.setDefauls({name: value}) */
		setDefaults: function(options) {
			$.extend(this.defaultOptions, options || {});
		},
		
		/** Determine whether a method is a getter and doesn't permit chaining.
			@private
			@param name {string} The method name.
			@param otherArgs {any[]} Any other arguments for the method.
			@return {boolean} True if this method is a getter, false otherwise. */
		_isNotChained: function(name, otherArgs) {
			if (name === 'option' && (otherArgs.length === 0 ||
					(otherArgs.length === 1 && typeof otherArgs[0] === 'string'))) {
				return true;
			}
			return $.inArray(name, this._getters) > -1;
		},
		
		/** Initialise an element. Called internally only.
			Adds an instance object as data named for the plugin.
			@param elem {Element} The element to enhance.
			@param options {object} Overriding settings. */
		_attach: function(elem, options) {
			elem = $(elem);
			if (elem.hasClass(this._getMarker())) {
				return;
			}
			elem.addClass(this._getMarker());
			options = $.extend({}, this.defaultOptions, this._getMetadata(elem), options || {});
			var inst = $.extend({name: this.name, elem: elem, options: options},
				this._instSettings(elem, options));
			elem.data(this.name, inst); // Save instance against element
			this._postAttach(elem, inst);
			this.option(elem, options);
		},

		/** Retrieve additional instance settings.
			Override this in a sub-class to provide extra settings.
			@param elem {jQuery} The current jQuery element.
			@param options {object} The instance options.
			@return {object} Any extra instance values.
			@example _instSettings: function(elem, options) {
 	return {nav: elem.find(options.navSelector)};
 } */
		_instSettings: function(elem, options) {
			return {};
		},

		/** Plugin specific post initialisation.
			Override this in a sub-class to perform extra activities.
			@param elem {jQuery} The current jQuery element.
			@param inst {object} The instance settings.
			@example _postAttach: function(elem, inst) {
 	elem.on('click.' + this.name, function() {
 		...
 	});
 } */
		_postAttach: function(elem, inst) {
		},

		/** Retrieve metadata configuration from the element.
			Metadata is specified as an attribute:
			<code>data-&lt;plugin name>="&lt;setting name>: '&lt;value>', ..."</code>.
			Dates should be specified as strings in this format: 'new Date(y, m-1, d)'.
			@private
			@param elem {jQuery} The source element.
			@return {object} The inline configuration or {}. */
		_getMetadata: function(elem) {
			try {
				var data = elem.data(this.name.toLowerCase()) || '';
				data = data.replace(/'/g, '"');
				data = data.replace(/([a-zA-Z0-9]+):/g, function(match, group, i) { 
					var count = data.substring(0, i).match(/"/g); // Handle embedded ':'
					return (!count || count.length % 2 === 0 ? '"' + group + '":' : group + ':');
				});
				data = $.parseJSON('{' + data + '}');
				for (var name in data) { // Convert dates
					var value = data[name];
					if (typeof value === 'string' && value.match(/^new Date\((.*)\)$/)) {
						data[name] = eval(value);
					}
				}
				return data;
			}
			catch (e) {
				return {};
			}
		},

		/** Retrieve the instance data for element.
			@param elem {Element} The source element.
			@return {object} The instance data or {}. */
		_getInst: function(elem) {
			return $(elem).data(this.name) || {};
		},
		
		/** Retrieve or reconfigure the settings for a plugin.
			@param elem {Element} The source element.
			@param name {object|string} The collection of new option values or the name of a single option.
			@param [value] {any} The value for a single named option.
			@return {any|object} If retrieving a single value or all options.
			@example $(selector).plugin('option', 'name', value)
 $(selector).plugin('option', {name: value, ...})
 var value = $(selector).plugin('option', 'name')
 var options = $(selector).plugin('option') */
		option: function(elem, name, value) {
			elem = $(elem);
			var inst = elem.data(this.name);
			if  (!name || (typeof name === 'string' && value == null)) {
				var options = (inst || {}).options;
				return (options && name ? options[name] : options);
			}
			if (!elem.hasClass(this._getMarker())) {
				return;
			}
			var options = name || {};
			if (typeof name === 'string') {
				options = {};
				options[name] = value;
			}
			this._optionsChanged(elem, inst, options);
			$.extend(inst.options, options);
		},
		
		/** Plugin specific options processing.
			Old value available in <code>inst.options[name]</code>, new value in <code>options[name]</code>.
			Override this in a sub-class to perform extra activities.
			@param elem {jQuery} The current jQuery element.
			@param inst {object} The instance settings.
			@param options {object} The new options.
			@example _optionsChanged: function(elem, inst, options) {
 	if (options.name != inst.options.name) {
 		elem.removeClass(inst.options.name).addClass(options.name);
 	}
 } */
		_optionsChanged: function(elem, inst, options) {
		},
		
		/** Remove all trace of the plugin.
			Override <code>_preDestroy</code> for plugin-specific processing.
			@param elem {Element} The source element.
			@example $(selector).plugin('destroy') */
		destroy: function(elem) {
			elem = $(elem);
			if (!elem.hasClass(this._getMarker())) {
				return;
			}
			this._preDestroy(elem, this._getInst(elem));
			elem.removeData(this.name).removeClass(this._getMarker());
		},

		/** Plugin specific pre destruction.
			Override this in a sub-class to perform extra activities and undo everything that was
			done in the <code>_postAttach</code> or <code>_optionsChanged</code> functions.
			@param elem {jQuery} The current jQuery element.
			@param inst {object} The instance settings.
			@example _preDestroy: function(elem, inst) {
 	elem.off('.' + this.name);
 } */
		_preDestroy: function(elem, inst) {
		}
	});
	
	/** Convert names from hyphenated to camel-case.
		@private
		@param value {string} The original hyphenated name.
		@return {string} The camel-case version. */
	function camelCase(name) {
		return name.replace(/-([a-z])/g, function(match, group) {
			return group.toUpperCase();
		});
	}
	
	/** Expose the plugin base.
		@namespace "$.JQPlugin" */
	$.JQPlugin = {
	
		/** Create a new collection plugin.
			@memberof "$.JQPlugin"
			@param [superClass='JQPlugin'] {string} The name of the parent class to inherit from.
			@param overrides {object} The property/function overrides for the new class.
			@example $.JQPlugin.createPlugin({
 	name: 'tabs',
 	defaultOptions: {selectedClass: 'selected'},
 	_initSettings: function(elem, options) { return {...}; },
 	_postAttach: function(elem, inst) { ... }
 }); */
		createPlugin: function(superClass, overrides) {
			if (typeof superClass === 'object') {
				overrides = superClass;
				superClass = 'JQPlugin';
			}
			superClass = camelCase(superClass);
			var className = camelCase(overrides.name);
			JQClass.classes[className] = JQClass.classes[superClass].extend(overrides);
			new JQClass.classes[className]();
		}
	};

})(jQuery);
/* jquery-realperson */
/* http://keith-wood.name/realPerson.html
   Real Person Form Submission for jQuery v2.0.1.
   Written by Keith Wood (kwood{at}iinet.com.au) June 2009.
   Available under the MIT (http://keith-wood.name/licence.html) license. 
   Please attribute the author if you use it. */

(function($) { // Hide scope, no $ conflict

	var pluginName = 'realperson';
	
	var ALPHABETIC = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
	var ALPHANUMERIC = ALPHABETIC + '0123456789';
	var DOTS = [
		['   *   ', '  * *  ', '  * *  ', ' *   * ', ' ***** ', '*     *', '*     *'],
		['****** ', '*     *', '*     *', '****** ', '*     *', '*     *', '****** '],
		[' ***** ', '*     *', '*      ', '*      ', '*      ', '*     *', ' ***** '],
		['****** ', '*     *', '*     *', '*     *', '*     *', '*     *', '****** '],
		['*******', '*      ', '*      ', '****   ', '*      ', '*      ', '*******'],
		['*******', '*      ', '*      ', '****   ', '*      ', '*      ', '*      '],
		[' ***** ', '*     *', '*      ', '*      ', '*   ***', '*     *', ' ***** '],
		['*     *', '*     *', '*     *', '*******', '*     *', '*     *', '*     *'],
		['*******', '   *   ', '   *   ', '   *   ', '   *   ', '   *   ', '*******'],
		['      *', '      *', '      *', '      *', '      *', '*     *', ' ***** '],
		['*     *', '*   ** ', '* **   ', '**     ', '* **   ', '*   ** ', '*     *'],
		['*      ', '*      ', '*      ', '*      ', '*      ', '*      ', '*******'],
		['*     *', '**   **', '* * * *', '*  *  *', '*     *', '*     *', '*     *'],
		['*     *', '**    *', '* *   *', '*  *  *', '*   * *', '*    **', '*     *'],
		[' ***** ', '*     *', '*     *', '*     *', '*     *', '*     *', ' ***** '],
		['****** ', '*     *', '*     *', '****** ', '*      ', '*      ', '*      '],
		[' ***** ', '*     *', '*     *', '*     *', '*   * *', '*    * ', ' **** *'],
		['****** ', '*     *', '*     *', '****** ', '*   *  ', '*    * ', '*     *'],
		[' ***** ', '*     *', '*      ', ' ***** ', '      *', '*     *', ' ***** '],
		['*******', '   *   ', '   *   ', '   *   ', '   *   ', '   *   ', '   *   '],
		['*     *', '*     *', '*     *', '*     *', '*     *', '*     *', ' ***** '],
		['*     *', '*     *', ' *   * ', ' *   * ', '  * *  ', '  * *  ', '   *   '],
		['*     *', '*     *', '*     *', '*  *  *', '* * * *', '**   **', '*     *'],
		['*     *', ' *   * ', '  * *  ', '   *   ', '  * *  ', ' *   * ', '*     *'],
		['*     *', ' *   * ', '  * *  ', '   *   ', '   *   ', '   *   ', '   *   '],
		['*******', '     * ', '    *  ', '   *   ', '  *    ', ' *     ', '*******'],
		['  ***  ', ' *   * ', '*   * *', '*  *  *', '* *   *', ' *   * ', '  ***  '],
		['   *   ', '  **   ', ' * *   ', '   *   ', '   *   ', '   *   ', '*******'],
		[' ***** ', '*     *', '      *', '     * ', '   **  ', ' **    ', '*******'],
		[' ***** ', '*     *', '      *', '    ** ', '      *', '*     *', ' ***** '],
		['    *  ', '   **  ', '  * *  ', ' *  *  ', '*******', '    *  ', '    *  '],
		['*******', '*      ', '****** ', '      *', '      *', '*     *', ' ***** '],
		['  **** ', ' *     ', '*      ', '****** ', '*     *', '*     *', ' ***** '],
		['*******', '     * ', '    *  ', '   *   ', '  *    ', ' *     ', '*      '],
		[' ***** ', '*     *', '*     *', ' ***** ', '*     *', '*     *', ' ***** '],
		[' ***** ', '*     *', '*     *', ' ******', '      *', '     * ', ' ****  ']];

	/** Create the real person plugin.
		<p>Displays a challenge to confirm that the viewer is a real person.</p>
		<p>Expects HTML like:</p>
		<pre>&lt;input...></pre>
		<p>Provide inline configuration like:</p>
		<pre>&lt;input data-realperson="name: 'value'">...></pre>
	 	@module RealPerson
		@augments JQPlugin
		@example $(selector).realperson()
 $(selector).realperson({length: 200, toggle: false}) */
	$.JQPlugin.createPlugin({
	
		/** The name of the plugin. */
		name: pluginName,

		/** The set of alphabetic characters. */
		alphabetic: ALPHABETIC,
		/** The set of alphabetic and numeric characters. */
		alphanumeric: ALPHANUMERIC,
		/** The set dots that make up each character. */
		defaultDots: DOTS,

		/** More/less change callback.
			Triggered when the more/less button is clicked.
			@callback changeCallback
			@param expanding {boolean} True if expanding the text, false if collapsing. */
			
		/** Default settings for the plugin.
			@property [length=6] {number} Number of characters to use.
			@property [regenerate='Click to change'] {string} Instruction text to regenerate.
			@property [hashName='{n}Hash'] {string} Name of the hash value field to compare with,
						use {n} to substitute with the original field name.
			@property [dot='*'] {string} The character to use for the dot patterns.
			@property [dots=defaultDots] {string[][]} The dot patterns per letter in chars.
			@property [chars=alphabetic] {string} The characters allowed. */
		defaultOptions: {
			length: 6,
			regenerate: 'Click to change',
			hashName: '{n}Hash',
			dot: '*',
			dots: DOTS,
			chars: ALPHABETIC
		},
		
		_getters: ['getHash'],

		_challengeClass: pluginName + '-challenge',
		_disabledClass: pluginName + '-disabled',
		_hashClass: pluginName + '-hash',
		_regenerateClass: pluginName + '-regen',
		_textClass: pluginName + '-text',

		_optionsChanged: function(elem, inst, options) {
			$.extend(inst.options, options);
			var text = '';
			for (var i = 0; i < inst.options.length; i++) {
				text += inst.options.chars.charAt(Math.floor(Math.random() * inst.options.chars.length));
			}
			inst.hash = hash(text + salt);
			var self = this;
			elem.closest('form').off('.' + inst.name).
				on('submit.' + inst.name, function() {
					var name = inst.options.hashName.replace(/\{n\}/, elem.attr('name'));
					var form = $(this);
					form.find('input[name="' + name + '"]').remove();
					form.append('<input type="hidden" class="' + self._hashClass + '" name="' + name +
						'" value="' + hash(text + salt) + '">');
					setTimeout(function() {
						form.find('input[name="' + name + '"]').remove();
					}, 0);
				});
			elem.prevAll('.' + this._challengeClass + ',.' + this._hashClass).remove().end().
				before(this._generateHTML(inst, text)).
				prevAll('div.' + this._challengeClass).click(function() {
					if (!$(this).hasClass(self._disabledClass)) {
						elem.realperson('option', {});
					}
				});
		},

		/* Enable the plugin functionality for a control.
		   @param elem {element} The control to affect. */
		enable: function(elem) {
			elem = $(elem);
			if (!elem.hasClass(this._getMarker())) {
				return;
			}
			elem.removeClass(this._disabledClass).prop('disabled', false).
				prevAll('.' + this._challengeClass).removeClass(this._disabledClass);
		},

		/* Disable the plugin functionality for a control.
		   @param elem {element} The control to affect. */
		disable: function(elem) {
			elem = $(elem);
			if (!elem.hasClass(this._getMarker())) {
				return;
			}
			elem.addClass(this._disabledClass).prop('disabled', true).
				prevAll('.' + this._challengeClass).addClass(this._disabledClass);
		},
		
		/* Retrieve the hash value.
		   @param elem {Element} The control with the hash.
		   @return {number} The hash value. */
		getHash: function(elem) {
			var inst = this._getInst(elem);
			return inst ? inst.hash : 0;
		},
		
		/* Generate the additional content for this control.
		   @param inst {object} The current instance settings.
		   @param text {string} The text to display.
		   @return {string} The additional content. */
		_generateHTML: function(inst, text) {
			var html = '<div class="' + this._challengeClass + '">' +
				'<div class="' + this._textClass + '">';
			for (var i = 0; i < inst.options.dots[0].length; i++) {
				for (var j = 0; j < text.length; j++) {
					html += inst.options.dots[inst.options.chars.indexOf(text.charAt(j))][i].
						replace(/ /g, '&#160;').replace(/\*/g, inst.options.dot) +
						'&#160;&#160;';
				}
				html += '<br>';
			}
			html += '</div><div class="' + this._regenerateClass + '">' +
				inst.options.regenerate + '</div></div>';
			return html;
		},

		_preDestroy: function(elem, inst) {
			elem.closest('form').off('.' + inst.name);
			elem.prevAll('.' + this._challengeClass + ',.' + this._hashClass).remove();
		}
	});

	/* Load salt value and clear. */
	var salt = $.salt || '#salt';
	delete $.salt;
	$(function() {
		var saltElem = $(salt);
		if (saltElem.length) {
			salt = saltElem.text();
			saltElem.remove();
		}
		if (salt === '#salt') {
			salt = '';
		}
	});

	/* Compute a hash value for the given text.
	   @param value {string} The text to hash.
	   @return {number} The corresponding hash value. */
	function hash(value) {
		var hash = 5381;
		for (var i = 0; i < value.length; i++) {
			hash = ((hash << 5) + hash) + value.charCodeAt(i);
		}
		return hash;
	}

})(jQuery);
/* ucontact-front */
;(function($){
var check_email = function(email){
		return /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(email);
	},
	show_message = function($form, message, info){
		var infoclass = info ? 'info' : 'error';
		$form.find('.ucontact-message-container').html(
			$('<div>').addClass('ucontact-msg msg ' + infoclass).html(message)
		);
	},
	hide_message = function($form){
		$form.find('.ucontact-message-container').html('');
	},
	add_error = function(error, errors, $elem){
		$elem.addClass('ucontact-field-error');
		return errors.push(error);
	}
;
if(!String.prototype.trim){
	String.prototype.trim = function(){
		return this.replace(/^\s+|\s+$/g, '');
	};
}
jQuery(function($){

	// Boot realperson with proper options
	$('[name="realPerson"]').each(function () {
		var $me = $(this),
			refresh = $me.attr('data-string'),
			opts = {}
		;
		if (refresh) opts.regenerate = refresh;
		$me.realperson(opts);
	});

	var $form = $('div.upfront-contact-form');
	$form.on('blur', '.ucontact-validate-field', function(e){
		var $elem = $(this),
			$container = $elem.parents('.upfront-contact-form'),
			field = $elem.attr('name'),
			errors = []
		;

		switch(field){
			case 'sendername':
				error = $elem.val().trim() ? false : ($elem.attr('data-string') || 'You must write your name.');
				break;
			case 'senderemail':
				error = check_email($elem.val().trim()) ? false : ($elem.attr('data-string') || 'The email address is not valid.');
				break;
			case 'subject':
				error = $elem.val().trim() ? false : ($elem.attr('data-string') || 'You must write a subject for the message.');
				break;
			case 'sendermessage':
				error = $elem.val().trim() ? false : ($elem.attr('data-string') || 'You forgot to write a message.');
		}

		if (error){
			$elem.addClass('ucontact-field-error');
			show_message($container, error);
		} else{
			$elem.removeClass('ucontact-field-error');
			hide_message($container);
		}
	});

	$form.find('form').on('submit', function(e){
		e.preventDefault();
		e.stopPropagation();
		var $this = $(this),
			name = $this.find('input[name=sendername]'),
			email = $this.find('input[name=senderemail]'),
			subject = $this.find('input[name=subject]'),
			message = $this.find('textarea[name=sendermessage]'),
			realPerson = $this.find('input[name="realPerson"]'),
			errors = []
		;

		if (!name.val().trim()) add_error(
			(name.attr("data-string") || 'You must write your name.'),
			errors, name
		);
		if (!check_email(email.val().trim())) add_error(
			(email.attr("data-string") || 'The email address is not valid.'),
			errors, email
		);
		if (subject.length > 0 && !subject.val().trim()) add_error(
			(subject.attr("data-string") || 'You must write a subject for the message.'),
			errors, subject
		);
		if(!message.val().trim()) add_error(
			(message.attr("data-string") || 'You forgot to write a message.'),
			errors, message
		);
		if (typeof realPerson !== "undefined" && typeof realPerson.val() !== "undefined" && !realPerson.val().trim()) add_error(
			'You must write CAPTCHA number.',
			errors, realPerson
		);

		if (errors.length > 0){
			//Stop sending
			show_message($this.parent(), errors.join('<br />'));
		} else{
			//Everything ok, try to send it via ajax
			$.ajax({
				url: ajax_url,
				type: 'POST',
				data: {
					action: 'upfront_contact-form',
					sendername: name.val().trim(),
					senderemail: email.val().trim(),
					subject: subject.length ? subject.val().trim() : '',
					sendermessage: message.val().trim(),
					ucontact: $this.find('input[name=ucontact]').val(),
					contactformid: $this.find('input[name=contactformid]').val(),
					entity_ids: $this.find('input[name=entity_ids]').val(),
					realPerson: realPerson.length ? realPerson.val() : '',
					realPersonHash: realPerson.length ? realPerson.realperson('getHash') : ''
				},
				success: function(data){
					var msg = (data.data && "message" in data.data ? data.data.message : ''),
						err = (data.data && "error" in data.data ? !!data.data.error : true)
					;
					if (!err) {
						msg = '<div><p>' + msg + '</p></div>';
					}
					show_message($this, msg, !err);
					if (!err) {
						$form.find(".ucontact-message-container").addClass("ucontact-success-response");
						//$form.find("input,button,textarea").attr("disabled", true);

						$form.find(".ucontact-message-container").bind('click', function() {
							$(this).removeClass("ucontact-success-response").html("");
							$(this).unbind('click');
						});

						name.val('');
						email.val('');
						if (subject.length)	{subject.val('');}
						message.val('');

						if (realPerson.length) {
							realPerson.val('');
							realPerson.realperson('destroy');
							realPerson.realperson();
						}
					}
				},
				error: function(error){
					var response = JSON.parse(error.responseText);
					show_message($this, response.error);
				}
			});
		}
		return false;
	});
});
})(jQuery);

/* magnific */
// Magnific Popup v0.9.3 by Dmitry Semenov
// http://bit.ly/magnific-popup#build=inline+image+gallery+retina
(function(a){var b="Close",c="BeforeClose",d="AfterClose",e="BeforeAppend",f="MarkupParse",g="Open",h="Change",i="mfp",j="."+i,k="mfp-ready",l="mfp-removing",m="mfp-prevent-close",n,o=function(){},p=!!window.jQuery,q,r=a(window),s,t,u,v,w,x=function(a,b){n.ev.on(i+a+j,b)},y=function(b,c,d,e){var f=document.createElement("div");return f.className="mfp-"+b,d&&(f.innerHTML=d),e?c&&c.appendChild(f):(f=a(f),c&&f.appendTo(c)),f},z=function(b,c){n.ev.triggerHandler(i+b,c),n.st.callbacks&&(b=b.charAt(0).toLowerCase()+b.slice(1),n.st.callbacks[b]&&n.st.callbacks[b].apply(n,a.isArray(c)?c:[c]))},A=function(){(n.st.focus?n.content.find(n.st.focus).eq(0):n.wrap).trigger("focus")},B=function(b){if(b!==w||!n.currTemplate.closeBtn)n.currTemplate.closeBtn=a(n.st.closeMarkup.replace("%title%",n.st.tClose)),w=b;return n.currTemplate.closeBtn},C=function(){a.magnificPopup.instance||(n=new o,n.init(),a.magnificPopup.instance=n)},D=function(b){if(a(b).hasClass(m))return;var c=n.st.closeOnContentClick,d=n.st.closeOnBgClick;if(c&&d)return!0;if(!n.content||a(b).hasClass("mfp-close")||n.preloader&&b===n.preloader[0])return!0;if(b!==n.content[0]&&!a.contains(n.content[0],b)){if(d&&a.contains(document,b))return!0}else if(c)return!0;return!1},E=function(){var a=document.createElement("p").style,b=["ms","O","Moz","Webkit"];if(a.transition!==undefined)return!0;while(b.length)if(b.pop()+"Transition"in a)return!0;return!1};o.prototype={constructor:o,init:function(){var b=navigator.appVersion;n.isIE7=b.indexOf("MSIE 7.")!==-1,n.isIE8=b.indexOf("MSIE 8.")!==-1,n.isLowIE=n.isIE7||n.isIE8,n.isAndroid=/android/gi.test(b),n.isIOS=/iphone|ipad|ipod/gi.test(b),n.supportsTransition=E(),n.probablyMobile=n.isAndroid||n.isIOS||/(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent),s=a(document.body),t=a(document),n.popupsCache={}},open:function(b){var c;if(b.isObj===!1){n.items=b.items.toArray(),n.index=0;var d=b.items,e;for(c=0;c<d.length;c++){e=d[c],e.parsed&&(e=e.el[0]);if(e===b.el[0]){n.index=c;break}}}else n.items=a.isArray(b.items)?b.items:[b.items],n.index=b.index||0;if(n.isOpen){n.updateItemHTML();return}n.types=[],v="",b.mainEl&&b.mainEl.length?n.ev=b.mainEl.eq(0):n.ev=t,b.key?(n.popupsCache[b.key]||(n.popupsCache[b.key]={}),n.currTemplate=n.popupsCache[b.key]):n.currTemplate={},n.st=a.extend(!0,{},a.magnificPopup.defaults,b),n.fixedContentPos=n.st.fixedContentPos==="auto"?!n.probablyMobile:n.st.fixedContentPos,n.st.modal&&(n.st.closeOnContentClick=!1,n.st.closeOnBgClick=!1,n.st.showCloseBtn=!1,n.st.enableEscapeKey=!1),n.bgOverlay||(n.bgOverlay=y("bg").on("click"+j,function(){n.close()}),n.wrap=y("wrap").attr("tabindex",-1).on("click"+j,function(a){D(a.target)&&n.close()}),n.container=y("container",n.wrap)),n.contentContainer=y("content"),n.st.preloader&&(n.preloader=y("preloader",n.container,n.st.tLoading));var h=a.magnificPopup.modules;for(c=0;c<h.length;c++){var i=h[c];i=i.charAt(0).toUpperCase()+i.slice(1),n["init"+i].call(n)}z("BeforeOpen"),n.st.showCloseBtn&&(n.st.closeBtnInside?(x(f,function(a,b,c,d){c.close_replaceWith=B(d.type)}),v+=" mfp-close-btn-in"):n.wrap.append(B())),n.st.alignTop&&(v+=" mfp-align-top"),n.fixedContentPos?n.wrap.css({overflow:n.st.overflowY,overflowX:"hidden",overflowY:n.st.overflowY}):n.wrap.css({top:r.scrollTop(),position:"absolute"}),(n.st.fixedBgPos===!1||n.st.fixedBgPos==="auto"&&!n.fixedContentPos)&&n.bgOverlay.css({height:t.height(),position:"absolute"}),n.st.enableEscapeKey&&t.on("keyup"+j,function(a){a.keyCode===27&&n.close()}),r.on("resize"+j,function(){n.updateSize()}),n.st.closeOnContentClick||(v+=" mfp-auto-cursor"),v&&n.wrap.addClass(v);var l=n.wH=r.height(),m={};if(n.fixedContentPos&&n._hasScrollBar(l)){var o=n._getScrollbarSize();o&&(m.paddingRight=o)}n.fixedContentPos&&(n.isIE7?a("body, html").css("overflow","hidden"):m.overflow="hidden");var p=n.st.mainClass;n.isIE7&&(p+=" mfp-ie7"),p&&n._addClassToMFP(p),n.updateItemHTML(),z("BuildControls"),a("html").css(m),n.bgOverlay.add(n.wrap).prependTo(document.body),n._lastFocusedEl=document.activeElement,setTimeout(function(){n.content?(n._addClassToMFP(k),A()):n.bgOverlay.addClass(k),t.on("focusin"+j,function(b){if(b.target!==n.wrap[0]&&!a.contains(n.wrap[0],b.target))return A(),!1})},16),n.isOpen=!0,n.updateSize(l),z(g)},close:function(){if(!n.isOpen)return;z(c),n.isOpen=!1,n.st.removalDelay&&!n.isLowIE&&n.supportsTransition?(n._addClassToMFP(l),setTimeout(function(){n._close()},n.st.removalDelay)):n._close()},_close:function(){z(b);var c=l+" "+k+" ";n.bgOverlay.detach(),n.wrap.detach(),n.container.empty(),n.st.mainClass&&(c+=n.st.mainClass+" "),n._removeClassFromMFP(c);if(n.fixedContentPos){var e={paddingRight:""};n.isIE7?a("body, html").css("overflow",""):e.overflow="",a("html").css(e)}t.off("keyup"+j+" focusin"+j),n.ev.off(j),n.wrap.attr("class","mfp-wrap").removeAttr("style"),n.bgOverlay.attr("class","mfp-bg"),n.container.attr("class","mfp-container"),n.st.showCloseBtn&&(!n.st.closeBtnInside||n.currTemplate[n.currItem.type]===!0)&&n.currTemplate.closeBtn&&n.currTemplate.closeBtn.detach(),n._lastFocusedEl&&a(n._lastFocusedEl).trigger("focus"),n.currItem=null,n.content=null,n.currTemplate=null,n.prevHeight=0,z(d)},updateSize:function(a){if(n.isIOS){var b=document.documentElement.clientWidth/window.innerWidth,c=window.innerHeight*b;n.wrap.css("height",c),n.wH=c}else n.wH=a||r.height();n.fixedContentPos||n.wrap.css("height",n.wH),z("Resize")},updateItemHTML:function(){var b=n.items[n.index];n.contentContainer.detach(),n.content&&n.content.detach(),b.parsed||(b=n.parseEl(n.index));var c=b.type;z("BeforeChange",[n.currItem?n.currItem.type:"",c]),n.currItem=b;if(!n.currTemplate[c]){var d=n.st[c]?n.st[c].markup:!1;z("FirstMarkupParse",d),d?n.currTemplate[c]=a(d):n.currTemplate[c]=!0}u&&u!==b.type&&n.container.removeClass("mfp-"+u+"-holder");var e=n["get"+c.charAt(0).toUpperCase()+c.slice(1)](b,n.currTemplate[c]);n.appendContent(e,c),b.preloaded=!0,z(h,b),u=b.type,n.container.prepend(n.contentContainer),z("AfterChange")},appendContent:function(a,b){n.content=a,a?n.st.showCloseBtn&&n.st.closeBtnInside&&n.currTemplate[b]===!0?n.content.find(".mfp-close").length||n.content.append(B()):n.content=a:n.content="",z(e),n.container.addClass("mfp-"+b+"-holder"),n.contentContainer.append(n.content)},parseEl:function(b){var c=n.items[b],d=c.type;c.tagName?c={el:a(c)}:c={data:c,src:c.src};if(c.el){var e=n.types;for(var f=0;f<e.length;f++)if(c.el.hasClass("mfp-"+e[f])){d=e[f];break}c.src=c.el.attr("data-mfp-src"),c.src||(c.src=c.el.attr("href"))}return c.type=d||n.st.type||"inline",c.index=b,c.parsed=!0,n.items[b]=c,z("ElementParse",c),n.items[b]},addGroup:function(a,b){var c=function(c){c.mfpEl=this,n._openClick(c,a,b)};b||(b={});var d="click.magnificPopup";b.mainEl=a,b.items?(b.isObj=!0,a.off(d).on(d,c)):(b.isObj=!1,b.delegate?a.off(d).on(d,b.delegate,c):(b.items=a,a.off(d).on(d,c)))},_openClick:function(b,c,d){var e=d.midClick!==undefined?d.midClick:a.magnificPopup.defaults.midClick;if(!e&&(b.which===2||b.ctrlKey||b.metaKey))return;var f=d.disableOn!==undefined?d.disableOn:a.magnificPopup.defaults.disableOn;if(f)if(a.isFunction(f)){if(!f.call(n))return!0}else if(r.width()<f)return!0;b.type&&(b.preventDefault(),n.isOpen&&b.stopPropagation()),d.el=a(b.mfpEl),d.delegate&&(d.items=c.find(d.delegate)),n.open(d)},updateStatus:function(a,b){if(n.preloader){q!==a&&n.container.removeClass("mfp-s-"+q),!b&&a==="loading"&&(b=n.st.tLoading);var c={status:a,text:b};z("UpdateStatus",c),a=c.status,b=c.text,n.preloader.html(b),n.preloader.find("a").on("click",function(a){a.stopImmediatePropagation()}),n.container.addClass("mfp-s-"+a),q=a}},_addClassToMFP:function(a){n.bgOverlay.addClass(a),n.wrap.addClass(a)},_removeClassFromMFP:function(a){this.bgOverlay.removeClass(a),n.wrap.removeClass(a)},_hasScrollBar:function(a){return(n.isIE7?t.height():document.body.scrollHeight)>(a||r.height())},_parseMarkup:function(b,c,d){var e;d.data&&(c=a.extend(d.data,c)),z(f,[b,c,d]),a.each(c,function(a,c){if(c===undefined||c===!1)return!0;e=a.split("_");if(e.length>1){var d=b.find(j+"-"+e[0]);if(d.length>0){var f=e[1];f==="replaceWith"?d[0]!==c[0]&&d.replaceWith(c):f==="img"?d.is("img")?d.attr("src",c):d.replaceWith('<img src="'+c+'" class="'+d.attr("class")+'" />'):d.attr(e[1],c)}}else b.find(j+"-"+a).html(c)})},_getScrollbarSize:function(){if(n.scrollbarSize===undefined){var a=document.createElement("div");a.id="mfp-sbm",a.style.cssText="width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;",document.body.appendChild(a),n.scrollbarSize=a.offsetWidth-a.clientWidth,document.body.removeChild(a)}return n.scrollbarSize}},a.magnificPopup={instance:null,proto:o.prototype,modules:[],open:function(a,b){return C(),a||(a={}),a.isObj=!0,a.index=b||0,this.instance.open(a)},close:function(){return a.magnificPopup.instance.close()},registerModule:function(b,c){c.options&&(a.magnificPopup.defaults[b]=c.options),a.extend(this.proto,c.proto),this.modules.push(b)},defaults:{disableOn:0,key:null,midClick:!1,mainClass:"",preloader:!0,focus:"",closeOnContentClick:!1,closeOnBgClick:!0,closeBtnInside:!0,showCloseBtn:!0,enableEscapeKey:!0,modal:!1,alignTop:!1,removalDelay:0,fixedContentPos:"auto",fixedBgPos:"auto",overflowY:"auto",closeMarkup:'<button title="%title%" type="button" class="mfp-close">&times;</button>',tClose:"Close (Esc)",tLoading:"Loading..."}},a.fn.magnificPopup=function(b){C();var c=a(this);if(typeof b=="string")if(b==="open"){var d,e=p?c.data("magnificPopup"):c[0].magnificPopup,f=parseInt(arguments[1],10)||0;e.items?d=e.items[f]:(d=c,e.delegate&&(d=d.find(e.delegate)),d=d.eq(f)),n._openClick({mfpEl:d},c,e)}else n.isOpen&&n[b].apply(n,Array.prototype.slice.call(arguments,1));else p?c.data("magnificPopup",b):c[0].magnificPopup=b,n.addGroup(c,b);return c};var F="inline",G,H,I,J=function(){I&&(H.after(I.addClass(G)).detach(),I=null)};a.magnificPopup.registerModule(F,{options:{hiddenClass:"hide",markup:"",tNotFound:"Content not found"},proto:{initInline:function(){n.types.push(F),x(b+"."+F,function(){J()})},getInline:function(b,c){J();if(b.src){var d=n.st.inline,e=a(b.src);if(e.length){var f=e[0].parentNode;f&&f.tagName&&(H||(G=d.hiddenClass,H=y(G),G="mfp-"+G),I=e.after(H).detach().removeClass(G)),n.updateStatus("ready")}else n.updateStatus("error",d.tNotFound),e=a("<div>");return b.inlineElement=e,e}return n.updateStatus("ready"),n._parseMarkup(c,{},b),c}}});var K,L=function(b){if(b.data&&b.data.title!==undefined)return b.data.title;var c=n.st.image.titleSrc;if(c){if(a.isFunction(c))return c.call(n,b);if(b.el)return b.el.attr(c)||""}return""};a.magnificPopup.registerModule("image",{options:{markup:'<div class="mfp-figure"><div class="mfp-close"></div><div class="mfp-img"></div><div class="mfp-bottom-bar"><div class="mfp-title"></div><div class="mfp-counter"></div></div></div>',cursor:"mfp-zoom-out-cur",titleSrc:"title",verticalFit:!0,tError:'<a href="%url%">The image</a> could not be loaded.'},proto:{initImage:function(){var a=n.st.image,c=".image";n.types.push("image"),x(g+c,function(){n.currItem.type==="image"&&a.cursor&&s.addClass(a.cursor)}),x(b+c,function(){a.cursor&&s.removeClass(a.cursor),r.off("resize"+j)}),x("Resize"+c,n.resizeImage),n.isLowIE&&x("AfterChange",n.resizeImage)},resizeImage:function(){var a=n.currItem;if(!a.img)return;if(n.st.image.verticalFit){var b=0;n.isLowIE&&(b=parseInt(a.img.css("padding-top"),10)+parseInt(a.img.css("padding-bottom"),10)),a.img.css("max-height",n.wH-b)}},_onImageHasSize:function(a){a.img&&(a.hasSize=!0,K&&clearInterval(K),a.isCheckingImgSize=!1,z("ImageHasSize",a),a.imgHidden&&(n.content&&n.content.removeClass("mfp-loading"),a.imgHidden=!1))},findImageSize:function(a){var b=0,c=a.img[0],d=function(e){K&&clearInterval(K),K=setInterval(function(){if(c.naturalWidth>0){n._onImageHasSize(a);return}b>200&&clearInterval(K),b++,b===3?d(10):b===40?d(50):b===100&&d(500)},e)};d(1)},getImage:function(b,c){var d=0,e=function(){b&&(b.img[0].complete?(b.img.off(".mfploader"),b===n.currItem&&(n._onImageHasSize(b),n.updateStatus("ready")),b.hasSize=!0,b.loaded=!0,z("ImageLoadComplete")):(d++,d<200?setTimeout(e,100):f()))},f=function(){b&&(b.img.off(".mfploader"),b===n.currItem&&(n._onImageHasSize(b),n.updateStatus("error",g.tError.replace("%url%",b.src))),b.hasSize=!0,b.loaded=!0,b.loadError=!0)},g=n.st.image,h=c.find(".mfp-img");if(h.length){var i=new Image;i.className="mfp-img",b.img=a(i).on("load.mfploader",e).on("error.mfploader",f),i.src=b.src,h.is("img")&&(b.img=b.img.clone()),b.img[0].naturalWidth>0&&(b.hasSize=!0)}return n._parseMarkup(c,{title:L(b),img_replaceWith:b.img},b),n.resizeImage(),b.hasSize?(K&&clearInterval(K),b.loadError?(c.addClass("mfp-loading"),n.updateStatus("error",g.tError.replace("%url%",b.src))):(c.removeClass("mfp-loading"),n.updateStatus("ready")),c):(n.updateStatus("loading"),b.loading=!0,b.hasSize||(b.imgHidden=!0,c.addClass("mfp-loading"),n.findImageSize(b)),c)}}});var M,N=function(){return M===undefined&&(M=document.createElement("p").style.MozTransform!==undefined),M};a.magnificPopup.registerModule("zoom",{options:{enabled:!1,easing:"ease-in-out",duration:300,opener:function(a){return a.is("img")?a:a.find("img")}},proto:{initZoom:function(){var a=n.st.zoom,d=".zoom";if(!a.enabled||!n.supportsTransition)return;var e=a.duration,f=function(b){var c=b.clone().removeAttr("style").removeAttr("class").addClass("mfp-animated-image"),d="all "+a.duration/1e3+"s "+a.easing,e={position:"fixed",zIndex:9999,left:0,top:0,"-webkit-backface-visibility":"hidden"},f="transition";return e["-webkit-"+f]=e["-moz-"+f]=e["-o-"+f]=e[f]=d,c.css(e),c},g=function(){n.content.css("visibility","visible")},h,i;x("BuildControls"+d,function(){if(n._allowZoom()){clearTimeout(h),n.content.css("visibility","hidden"),image=n._getItemToZoom();if(!image){g();return}i=f(image),i.css(n._getOffset()),n.wrap.append(i),h=setTimeout(function(){i.css(n._getOffset(!0)),h=setTimeout(function(){g(),setTimeout(function(){i.remove(),image=i=null,z("ZoomAnimationEnded")},16)},e)},16)}}),x(c+d,function(){if(n._allowZoom()){clearTimeout(h),n.st.removalDelay=e;if(!image){image=n._getItemToZoom();if(!image)return;i=f(image)}i.css(n._getOffset(!0)),n.wrap.append(i),n.content.css("visibility","hidden"),setTimeout(function(){i.css(n._getOffset())},16)}}),x(b+d,function(){n._allowZoom()&&(g(),i&&i.remove())})},_allowZoom:function(){return n.currItem.type==="image"},_getItemToZoom:function(){return n.currItem.hasSize?n.currItem.img:!1},_getOffset:function(b){var c;b?c=n.currItem.img:c=n.st.zoom.opener(n.currItem.el||n.currItem);var d=c.offset(),e=parseInt(c.css("padding-top"),10),f=parseInt(c.css("padding-bottom"),10);d.top-=a(window).scrollTop()-e;var g={width:c.width(),height:(p?c.innerHeight():c[0].offsetHeight)-f-e};return N()?g["-moz-transform"]=g.transform="translate("+d.left+"px,"+d.top+"px)":(g.left=d.left,g.top=d.top),g}}});var O=function(a){var b=n.items.length;return a>b-1?a-b:a<0?b+a:a},P=function(a,b,c){return a.replace("%curr%",b+1).replace("%total%",c)};a.magnificPopup.registerModule("gallery",{options:{enabled:!1,arrowMarkup:'<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',preload:[0,2],navigateByImgClick:!0,arrows:!0,tPrev:"Previous (Left arrow key)",tNext:"Next (Right arrow key)",tCounter:"%curr% of %total%"},proto:{initGallery:function(){var c=n.st.gallery,d=".mfp-gallery",e=Boolean(a.fn.mfpFastClick);n.direction=!0;if(!c||!c.enabled)return!1;v+=" mfp-gallery",x(g+d,function(){c.navigateByImgClick&&n.wrap.on("click"+d,".mfp-img",function(){if(n.items.length>1)return n.next(),!1}),t.on("keydown"+d,function(a){a.keyCode===37?n.prev():a.keyCode===39&&n.next()})}),x("UpdateStatus"+d,function(a,b){b.text&&(b.text=P(b.text,n.currItem.index,n.items.length))}),x(f+d,function(a,b,d,e){var f=n.items.length;d.counter=f>1?P(c.tCounter,e.index,f):""}),x("BuildControls"+d,function(){if(n.items.length>1&&c.arrows&&!n.arrowLeft){var b=c.arrowMarkup,d=n.arrowLeft=a(b.replace("%title%",c.tPrev).replace("%dir%","left")).addClass(m),f=n.arrowRight=a(b.replace("%title%",c.tNext).replace("%dir%","right")).addClass(m),g=e?"mfpFastClick":"click";d[g](function(){n.prev()}),f[g](function(){n.next()}),n.isIE7&&(y("b",d[0],!1,!0),y("a",d[0],!1,!0),y("b",f[0],!1,!0),y("a",f[0],!1,!0)),n.container.append(d.add(f))}}),x(h+d,function(){n._preloadTimeout&&clearTimeout(n._preloadTimeout),n._preloadTimeout=setTimeout(function(){n.preloadNearbyImages(),n._preloadTimeout=null},16)}),x(b+d,function(){t.off(d),n.wrap.off("click"+d),n.arrowLeft&&e&&n.arrowLeft.add(n.arrowRight).destroyMfpFastClick(),n.arrowRight=n.arrowLeft=null})},next:function(){n.direction=!0,n.index=O(n.index+1),n.updateItemHTML()},prev:function(){n.direction=!1,n.index=O(n.index-1),n.updateItemHTML()},goTo:function(a){n.direction=a>=n.index,n.index=a,n.updateItemHTML()},preloadNearbyImages:function(){var a=n.st.gallery.preload,b=Math.min(a[0],n.items.length),c=Math.min(a[1],n.items.length),d;for(d=1;d<=(n.direction?c:b);d++)n._preloadItem(n.index+d);for(d=1;d<=(n.direction?b:c);d++)n._preloadItem(n.index-d)},_preloadItem:function(b){b=O(b);if(n.items[b].preloaded)return;var c=n.items[b];c.parsed||(c=n.parseEl(b)),z("LazyLoad",c),c.type==="image"&&(c.img=a('<img class="mfp-img" />').on("load.mfploader",function(){c.hasSize=!0}).on("error.mfploader",function(){c.hasSize=!0,c.loadError=!0,z("LazyLoadError",c)}).attr("src",c.src)),c.preloaded=!0}}});var Q="retina";a.magnificPopup.registerModule(Q,{options:{replaceSrc:function(a){return a.src.replace(/\.\w+$/,function(a){return"@2x"+a})},ratio:1},proto:{initRetina:function(){if(window.devicePixelRatio>1){var a=n.st.retina,b=a.ratio;b=isNaN(b)?b():b,b>1&&(x("ImageHasSize."+Q,function(a,c){c.img.css({"max-width":c.img[0].naturalWidth/b,width:"100%"})}),x("ElementParse."+Q,function(c,d){d.src=a.replaceSrc(d,b)}))}}}})})(window.jQuery||window.Zepto)
/* jquery-shuffle */
// IMPORTANT!
// If you're already using Modernizr, delete it from this file. If you don't know what Modernizr is, leave it :)

/* Modernizr 2.8.3 (Custom Build) | MIT & BSD
 * Build: http://modernizr.com/download/#-csstransforms-csstransforms3d-csstransitions-mq-cssclasses-prefixed-teststyles
 */
if(typeof window.Modernizr == 'undefined')
	window.Modernizr=function(a,b,c){function A(a){j.cssText=a}function B(a,b){return A(m.join(a+";")+(b||""))}function C(a,b){return typeof a===b}function D(a,b){return!!~(""+a).indexOf(b)}function E(a,b){for(var d in a){var e=a[d];if(!D(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function F(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:C(f,"function")?f.bind(d||b):f}return!1}function G(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+o.join(d+" ")+d).split(" ");return C(b,"string")||C(b,"undefined")?E(e,b):(e=(a+" "+p.join(d+" ")+d).split(" "),F(e,b,c))}var d="2.8.3",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m=" -webkit- -moz- -o- -ms- ".split(" "),n="Webkit Moz O ms",o=n.split(" "),p=n.toLowerCase().split(" "),q={},r={},s={},t=[],u=t.slice,v,w=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["&#173;",'<style id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},x=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b)&&c(b).matches||!1;var d;return w("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},y={}.hasOwnProperty,z;!C(y,"undefined")&&!C(y.call,"undefined")?z=function(a,b){return y.call(a,b)}:z=function(a,b){return b in a&&C(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=u.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(u.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(u.call(arguments)))};return e}),q.csstransforms=function(){return!!G("transform")},q.csstransforms3d=function(){var a=!!G("perspective");return a&&"webkitPerspective"in g.style&&w("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},q.csstransitions=function(){return G("transition")};for(var H in q)z(q,H)&&(v=H.toLowerCase(),e[v]=q[H](),t.push((e[v]?"":"no-")+v));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)z(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},A(""),i=k=null,e._version=d,e._prefixes=m,e._domPrefixes=p,e._cssomPrefixes=o,e.mq=x,e.testProp=function(a){return E([a])},e.testAllProps=G,e.testStyles=w,e.prefixed=function(a,b,c){return b?G(a,b,c):G(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+t.join(" "):""),e}(this,this.document);


// Shuffle Doesn't require this shuffle/debounce plugin, but it works better with it.

/*
 * jQuery throttle / debounce - v1.1 - 3/7/2010
 * http://benalman.com/projects/jquery-throttle-debounce-plugin/
 *
 * Copyright (c) 2010 "Cowboy" Ben Alman
 * Dual licensed under the MIT and GPL licenses.
 * http://benalman.com/about/license/
 */
(function(b,c){var $=b.jQuery||b.Cowboy||(b.Cowboy={}),a;$.throttle=a=function(e,f,j,i){var h,d=0;if(typeof f!=="boolean"){i=j;j=f;f=c}function g(){var o=this,m=+new Date()-d,n=arguments;function l(){d=+new Date();j.apply(o,n)}function k(){h=c}if(i&&!h){l()}h&&clearTimeout(h);if(i===c&&m>e){l()}else{if(f!==true){h=setTimeout(i?k:l,i===c?e-m:e)}}}if($.guid){g.guid=j.guid=j.guid||$.guid++}return g};$.debounce=function(d,e,f){return f===c?a(d,e,false):a(d,f,e!==false)}})(this);

/**
 * jQuery Shuffle Plugin
 * Uses CSS Transforms to filter down a grid of items.
 * Dependencies: jQuery 1.9+, Modernizr 2.6.2. Optionally throttle/debounce by Ben Alman
 * Inspired by Isotope http://isotope.metafizzy.co/
 * Modified 2013-08-19
 * @license MIT license
 * @author Glen Cheney <cheney.glen@gmail.com>
 * @version 2.0.1
 */
(function($, Modernizr, undefined) {

'use strict';

// You can return `undefined` from the `by` function to revert to DOM order
// This plugin does NOT return a jQuery object. It returns a plain array because
// jQuery sorts everything in DOM order.
$.fn.sorted = function(options) {
    var opts = $.extend({}, $.fn.sorted.defaults, options),
        arr = this.get(),
        revert = false;

    if ( !arr.length ) {
        return [];
    }

    if ( opts.randomize ) {
        return $.fn.sorted.randomize( arr );
    }

    // Sort the elements by the opts.by function.
    // If we don't have opts.by, default to DOM order
    if (opts.by !== $.noop && opts.by !== null && opts.by !== undefined) {
        arr.sort(function(a, b) {

            // Exit early if we already know we want to revert
            if ( revert ) {
                return 0;
            }

            var valA = opts.by($(a)),
                valB = opts.by($(b));

            // If both values are undefined, use the DOM order
            if ( valA === undefined && valB === undefined ) {
                revert = true;
                return 0;
            }

            if ( valA === 'sortFirst' || valB === 'sortLast' ) {
                return -1;
            }

            if ( valA === 'sortLast' || valB === 'sortFirst' ) {
                return 1;
            }

            return (valA < valB) ? -1 :
                (valA > valB) ? 1 : 0;
        });
    }

    // Revert to the original array if necessary
    if ( revert ) {
        return this.get();
    }

    if ( opts.reverse ) {
        arr.reverse();
    }

    return arr;

};

$.fn.sorted.defaults = {
    reverse: false, // Use array.reverse() to reverse the results
    by: null, // Sorting function
    randomize: false // If true, this will skip the sorting and return a randomized order in the array
};


// http://stackoverflow.com/a/962890/373422
$.fn.sorted.randomize = function( array ) {
    var top = array.length,
        tmp, current;

    if ( !top ) {
        return array;
    }

    while ( --top ) {
        current = Math.floor( Math.random() * (top + 1) );
        tmp = array[ current ];
        array[ current ] = array[ top ];
        array[ top ] = tmp;
    }

    return array;
};

// Used for unique instance variables
var id = 0;

var Shuffle = function( $container, options ) {
    var self = this;
    $.extend( self, Shuffle.options, options, Shuffle.settings );

    self.$container = $container;
    self.$window = $(window);
    self.unique = 'shuffle_' + id++;

    self._fire('loading');
    self._init();
    self._fire('done');
};

Shuffle.prototype = {

    _init : function() {
        var self = this,
            containerCSS,
            resizeFunction = $.proxy( self._onResize, self ),
            debouncedResize = self.throttle ? self.throttle( self.throttleTime, resizeFunction ) : resizeFunction,
            sort = self.initialSort ? self.initialSort : null;

        // Save variables needed later then add some classes
        self._setVars();

        // Zero out all columns
        self._resetCols();

        // Add classes and invalidate styles
        self._addClasses();

        // Set initial css for each item
        self._initItems();

        // Bind resize events (http://stackoverflow.com/questions/1852751/window-resize-event-firing-in-internet-explorer)
        self.$window.on('resize.shuffle.' + self.unique, debouncedResize);

        // Get container css all in one request. Causes reflow
        containerCSS = self.$container.css(['paddingLeft', 'paddingRight', 'position', 'width']);

        // Position cannot be static.
        // This will cause an extra style layout if it has to be set and the sizer element is used.
        if ( containerCSS.position === 'static' ) {
            self.$container.css('position', 'relative');
        }

        // Get offset from container
        self.offset = {
            left: parseInt( containerCSS.paddingLeft, 10 ) || 0,
            top: parseInt( containerCSS.paddingTop, 10 ) || 0
        };

        // We already got the container's width above, no need to cause another reflow getting it again...
        // Calculate the number of columns there will be
        self._setColumns( parseInt( containerCSS.width, 10 ) );

        // Kick off!
        self.shuffle( self.group, sort );

        // The shuffle items haven't had transitions set on them yet
        // so the user doesn't see the first layout. Set them now that the first layout is done.
        if ( self.supported ) {
            setTimeout(function() {
                self._setTransitions();
                self.$container[0].style[ self.transitionName ] = 'height ' + self.speed + 'ms ' + self.easing;
            }, 0);
        }
    },

    // Will invalidate styles
    _addClasses : function() {
        var self = this;

        self.$container.addClass('shuffle');
        self.$items.addClass('shuffle-item filtered');

        return self;
    },

    _setVars : function() {
        var self = this;

        self.$items = self._getItems();
        self.transitionName = self.prefixed('transition'),
        self.transitionDelayName = self.prefixed('transitionDelay');
        self.transitionDuration = self.prefixed('transitionDuration');
        self.transform = self.getPrefixed('transform');

        // Get transitionend event name
        self.transitionend = {
            'WebkitTransition' : 'webkitTransitionEnd',
            'MozTransition'    : 'transitionend',
            'OTransition'      : 'oTransitionEnd',
            'msTransition'     : 'MSTransitionEnd',
            'transition'       : 'transitionend'
        }[ self.transitionName ];

        // If the columnWidth property is a function, then the grid is fluid
        self.isFluid = self.columnWidth && typeof self.columnWidth === 'function';

        // Column width is the default setting and sizer is not (meaning passed in)
        // Assume they meant column width to be the sizer
        if ( self.columnWidth === 0 && self.sizer !== null ) {
            self.columnWidth = self.sizer;
        }

        // If column width is a string, treat is as a selector and search for the
        // sizer element within the outermost container
        if ( typeof self.columnWidth === 'string' ) {
            self.$sizer = self.$container.find( self.columnWidth );

        // Check for an element
        } else if ( self.columnWidth && self.columnWidth.nodeType && self.columnWidth.nodeType === 1 ) {
            // Wrap it in jQuery
            self.$sizer = $( self.columnWidth );

        // Check for jQuery object
        } else if ( self.columnWidth && self.columnWidth.jquery ) {
            self.$sizer = self.columnWidth;
        }

        if ( self.$sizer && self.$sizer.length ) {
            self.useSizer = true;
            self.sizer = self.$sizer[0];
        }

        return self;
    },

    _filter : function( category, $collection ) {
        var self = this,
            isPartialSet = $collection !== undefined,
            $items = isPartialSet ? $collection : self.$items,
            $filtered = $();

        category = category || self.lastFilter;

        self._fire('filter');

        // Loop through each item and use provided function to determine
        // whether to hide it or not.
        if ( $.isFunction(category) ) {
            $items.each(function() {
                var $item = $(this),
                passes = category.call($item[0], $item, self);

                if ( passes ) {
                    $filtered = $filtered.add( $item );
                }
            });
        }

        // Otherwise we've been passed a category to filter by
        else {
            self.group = category;
            if (category !== 'all') {
                $items.each(function() {
                    var $this = $(this),
                    groups = $this.data('groups'),
                    keys = self.delimeter && !$.isArray( groups ) ? groups.split( self.delimeter ) : groups,
                    passes = $.inArray(category, keys) > -1;

                    if ( passes ) {
                        $filtered = $filtered.add( $this );
                    }
                });
            }

            // category === 'all', add filtered class to everything
            else {
                $filtered = $items;
            }
        }

        // Individually add/remove concealed/filtered classes
        self._toggleFilterClasses( $items, $filtered );

        $items = null;
        $collection = null;

        return $filtered;
    },


    _toggleFilterClasses : function( $items, $filtered ) {
        var concealed = 'concealed',
            filtered = 'filtered';

        $items.filter( $filtered ).each(function() {
            var $filteredItem = $(this);
            // Remove concealed if it's there
            if ( $filteredItem.hasClass( concealed ) ) {
                $filteredItem.removeClass( concealed );
            }
            // Add filtered class if it's not there
            if ( !$filteredItem.hasClass( filtered ) ) {
                $filteredItem.addClass( filtered );
            }
        });

        $items.not( $filtered ).each(function() {
            var $filteredItem = $(this);
            // Add concealed if it's not there
            if ( !$filteredItem.hasClass( concealed ) ) {
                $filteredItem.addClass( concealed );
            }
            // Remove filtered class if it's there
            if ( $filteredItem.hasClass( filtered ) ) {
                $filteredItem.removeClass( filtered );
            }
        });
    },

    /**
     * Set the initial css for each item
     * @param  {jQuery} $items optionally specifiy at set to initialize
     * @return {jQuery}        the items which were just set
     */
    _initItems : function( $items ) {
        $items = $items || this.$items;
        return $items.css( this.itemCss );
    },

    _updateItemCount : function() {
        this.visibleItems = this.$items.filter('.filtered').length;
        return this;
    },

    _setTransition : function( element ) {
        var self = this;
        element.style[ self.transitionName ] = self.transform + ' ' + self.speed + 'ms ' + self.easing + ', opacity ' + self.speed + 'ms ' + self.easing;
        return element;
    },

    _setTransitions : function( $items ) {
        var self = this;

        $items = $items || self.$items;
        $items.each(function() {
            self._setTransition( this );
        });
        return self;
    },

    _setSequentialDelay : function( $collection ) {
        var self = this;

        if ( !self.supported ) {
            return;
        }

        // $collection can be an array of dom elements or jquery object
        $.each( $collection, function(i) {
            // This works because the transition-property: transform, opacity;
            this.style[ self.transitionDelayName ] = '0ms,' + ((i + 1) * self.sequentialFadeDelay) + 'ms';

            // Set the delay back to zero after one transition
            $(this).one(self.transitionend, function() {
                this.style[ self.transitionDelayName ] = '0ms';
            });
        });
    },

    _getItems : function() {
        return this.$container.children( this.itemSelector );
    },

    _getPreciseDimension : function( element, style ) {
        var dimension;
        if ( window.getComputedStyle ) {
            dimension = window.getComputedStyle( element, null )[ style ];
        } else {
            dimension = $( element ).css( style );
        }
        return parseFloat( dimension );
    },

    // Calculate number of columns
    // Gets css if using sizer element
    _setColumns : function( theContainerWidth ) {
        var self = this,
            containerWidth = theContainerWidth || self.$container.width(),
            gutter = typeof self.gutterWidth === 'function' ?
                self.gutterWidth( containerWidth ) :
                self.useSizer ?
                    self._getPreciseDimension( self.sizer, 'marginLeft' ) :
                    self.gutterWidth,
            calculatedColumns;

        // use fluid columnWidth function if there
        self.colWidth = self.isFluid ? self.columnWidth( containerWidth ) :
            // columnWidth option isn't a function, are they using a sizing element?
            self.useSizer ? self._getPreciseDimension( self.sizer, 'width' ) :
            // if not, how about the explicitly set option?
            self.columnWidth ||
            // or use the size of the first item
            self.$items.outerWidth(true) ||
            // if there's no items, use size of container
            containerWidth;

        // Don't let them set a column width of zero.
        self.colWidth = self.colWidth || containerWidth;

        self.colWidth += gutter;

        calculatedColumns = (containerWidth + gutter) / self.colWidth;
        // Widths given from getComputedStyle are not precise enough...
        if ( Math.ceil(calculatedColumns) - calculatedColumns < 0.01 ) {
            // e.g. calculatedColumns = 11.998876
            calculatedColumns = Math.ceil( calculatedColumns );
        }
        self.cols = Math.floor( calculatedColumns );
        self.cols = Math.max( self.cols, 1 );

        self.containerWidth = containerWidth;
    },

    /**
     * Adjust the height of the grid
     */
    _setContainerSize : function() {
        var self = this,
        gridHeight = Math.max.apply( Math, self.colYs );
        self.$container.css( 'height', gridHeight + 'px' );
    },

    /**
     * Fire events with .shuffle namespace
     */
    _fire : function( name, args ) {
        this.$container.trigger( name + '.shuffle', args && args.length ? args : [ this ] );
    },


    /**
     * Loops through each item that should be shown
     * Calculates the x and y position and then transitions it
     * @param {array} items - array of items that will be shown/layed out in order in their array.
     *     Because jQuery collection are always ordered in DOM order, we can't pass a jq collection
     * @param {function} complete callback function
     * @param {boolean} isOnlyPosition set this to true to only trigger positioning of the items
     */
    _layout: function( items, fn, isOnlyPosition, isHide ) {
        var self = this;

        fn = fn || self.filterEnd;

        self.layoutTransitionEnded = false;
        $.each(items, function(index) {
            var $this = $(items[index]),
            //how many columns does this brick span
            colSpan = Math.ceil( $this.outerWidth(true) / self.colWidth );
            colSpan = Math.min( colSpan, self.cols );

            if ( colSpan === 1 ) {
                // if brick spans only one column, just like singleMode
                self._placeItem( $this, self.colYs, fn, isOnlyPosition, isHide );
            } else {
                // brick spans more than one column
                // how many different places could this brick fit horizontally
                var groupCount = self.cols + 1 - colSpan,
                    groupY = [],
                    groupColY,
                    i;

                // for each group potential horizontal position
                for ( i = 0; i < groupCount; i++ ) {
                    // make an array of colY values for that one group
                    groupColY = self.colYs.slice( i, i + colSpan );
                    // and get the max value of the array
                    groupY[i] = Math.max.apply( Math, groupColY );
                }

                self._placeItem( $this, groupY, fn, isOnlyPosition, isHide );
            }
        });

        // `_layout` always happens after `_shrink`, so it's safe to process the style
        // queue here with styles from the shrink method
        self._processStyleQueue();

        // Adjust the height of the container
        self._setContainerSize();
    },

    _resetCols : function() {
        // reset columns
        var i = this.cols;
        this.colYs = [];
        while (i--) {
            this.colYs.push( 0 );
        }
    },

    _reLayout : function( callback, isOnlyPosition ) {
        var self = this;
        callback = callback || self.filterEnd;
        self._resetCols();

        // If we've already sorted the elements, keep them sorted
        if ( self.keepSorted && self.lastSort ) {
            self.sort( self.lastSort, true, isOnlyPosition );
        } else {
            self._layout( self.$items.filter('.filtered').get(), self.filterEnd, isOnlyPosition );
        }
    },

    // worker method that places brick in the columnSet with the the minY
    _placeItem : function( $item, setY, callback, isOnlyPosition, isHide ) {
        // get the minimum Y value from the columns
        var self = this,
            minimumY = Math.min.apply( Math, setY ),
            shortCol = 0;

        // Find index of short column, the first from the left where this item will go
        // if ( setY[i] === minimumY ) requires items' height to be exact every time.
        // The buffer value is very useful when the height is a percentage of the width
        for (var i = 0, len = setY.length; i < len; i++) {
            if ( setY[i] >= minimumY - self.buffer && setY[i] <= minimumY + self.buffer ) {
                shortCol = i;
                break;
            }
        }

        // Position the item
        var x = self.colWidth * shortCol,
        y = minimumY;
        x = Math.round( x + self.offset.left );
        y = Math.round( y + self.offset.top );

        // Save data for shrink
        $item.data( {x: x, y: y} );

        // Apply setHeight to necessary columns
        var setHeight = minimumY + $item.outerHeight( true ),
        setSpan = self.cols + 1 - len;
        for ( i = 0; i < setSpan; i++ ) {
            self.colYs[ shortCol + i ] = setHeight;
        }

        var transitionObj = {
            from: 'layout',
            $this: $item,
            x: x,
            y: y,
            scale: 1
        };

        if ( isOnlyPosition ) {
            transitionObj.skipTransition = true;
        } else {
            transitionObj.opacity = 1;
            transitionObj.callback = callback;
        }

        if ( isHide ) {
            transitionObj.opacity = 0;
        }

        self.styleQueue.push( transitionObj );
    },

    /**
     * Hides the elements that don't match our filter
     */
    _shrink : function( $collection, fn ) {
        var self = this,
            $concealed = $collection || self.$items.filter('.concealed'),
            transitionObj = {},
            callback = fn || self.shrinkEnd;

        // Abort if no items
        if ( !$concealed.length ) {
            return;
        }

        self._fire('shrink');

        self.shrinkTransitionEnded = false;
        $concealed.each(function() {
            var $this = $(this),
                data = $this.data();

            transitionObj = {
                from: 'shrink',
                $this: $this,
                x: data.x,
                y: data.y,
                scale : 0.001,
                opacity: 0,
                callback: callback
            };

            self.styleQueue.push( transitionObj );
        });
    },

    _onResize : function() {
        var self = this,
            containerWidth;

        // If shuffle is disabled, destroyed, don't do anything
        if ( !self.enabled || self.destroyed ) {
            return;
        }

        // Will need to check height in the future if it's layed out horizontaly
        containerWidth = self.$container.width();

        // containerWidth hasn't changed, don't do anything
        if ( containerWidth === self.containerWidth ) {
            return;
        }

        self.resized();
    },


    /**
     * Uses Modernizr's prefixed() to get the correct vendor property name and sets it using jQuery .css()
     *
     * @param {jq} $el the jquery object to set the css on
     * @param {string} prop the property to set (e.g. 'transition')
     * @param {string} value the value of the prop
     */
    setPrefixedCss : function( $el, prop, value ) {
        $el.css( this.prefixed( prop ), value );
    },


    /**
     * Returns things like `-webkit-transition` or `box-sizing` from `transition` or `boxSizing`, respectively
     *
     * @param {string} property to be prefixed.
     * @return {string} the prefixed css property
     */
    getPrefixed : function( prop ) {
        var styleName = this.prefixed( prop );
        return styleName ? styleName.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-') : styleName;
    },

    /**
     * Transitions an item in the grid
     *
     * @param {object}  opts options
     * @param {jQuery}  opts.$this jQuery object representing the current item
     * @param {int}     opts.x translate's x
     * @param {int}     opts.y translate's y
     * @param {String}  opts.left left position (used when no transforms available)
     * @param {String}  opts.top top position (used when no transforms available)
     * @param {float}   opts.scale amount to scale the item
     * @param {float}   opts.opacity opacity of the item
     * @param {String}  opts.height the height of the item (used when no transforms available)
     * @param {String}  opts.width the width of the item (used when no transforms available)
     * @param {function} opts.callback complete function for the animation
     */
    transition: function(opts) {
        var self = this,
        transform,
        // Only fire callback once per collection's transition
        complete = function() {
            if ( !self.layoutTransitionEnded && opts.from === 'layout' ) {
                self._fire('layout');
                opts.callback.call( self );
                self.layoutTransitionEnded = true;
            } else if ( !self.shrinkTransitionEnded && opts.from === 'shrink' ) {
                opts.callback.call( self );
                self.shrinkTransitionEnded = true;
            }
        };

        opts.callback = opts.callback || $.noop;

        // Use CSS Transforms if we have them
        if ( self.supported ) {

            // Make scale one if it's not preset
            if ( opts.scale === undefined ) {
                opts.scale = 1;
            }

            if (self.threeD) {
                transform = 'translate3d(' + opts.x + 'px, ' + opts.y + 'px, 0) scale3d(' + opts.scale + ', ' + opts.scale + ', 1)';
            } else {
                transform = 'translate(' + opts.x + 'px, ' + opts.y + 'px) scale(' + opts.scale + ', ' + opts.scale + ')';
            }

            if ( opts.x !== undefined ) {
                self.setPrefixedCss(opts.$this, 'transform', transform);
            }

            if ( opts.opacity !== undefined ) {
                // Update css to trigger CSS Animation
                opts.$this.css('opacity' , opts.opacity);
            }

            opts.$this.one(self.transitionend, complete);
        } else {

            var cssObj = {
                left: opts.x,
                top: opts.y,
                opacity: opts.opacity
            };

            // Use jQuery to animate left/top
            opts.$this.stop( true ).animate( cssObj, self.speed, 'swing', complete);
        }
    },

    _processStyleQueue : function() {
        var self = this,
            queue = self.styleQueue;

        $.each( queue, function(i, transitionObj) {

            if ( transitionObj.skipTransition ) {
                self._skipTransition( transitionObj.$this[0], function() {
                    self.transition( transitionObj );
                });
            } else {
                self.transition( transitionObj );
            }
        });

        // Remove everything in the style queue
        self.styleQueue.length = 0;
    },

    shrinkEnd: function() {
        this._fire('shrunk');
    },

    filterEnd: function() {
        this._fire('filtered');
    },

    sortEnd: function() {
        this._fire('sorted');
    },

    /**
     * Change a property or execute a function which will not have a transition
     * @param  {Element}         element    DOM element that won't be transitioned
     * @param  {string|function} property   the new style property which will be set or a function which will be called
     * @param  {string}          [value]    the value that `property` should be.
     */
    _skipTransition : function( element, property, value ) {
        var self = this,
            reflow,
            durationName = self.transitionDuration,
            duration = element.style[ durationName ];

        // Set the duration to zero so it happens immediately
        element.style[ durationName ] = '0ms'; // ms needed for firefox!

        if ( $.isFunction( property ) ) {
            property();
        } else {
            element.style[ property ] = value;
        }

        // Force reflow
        reflow = element.offsetWidth;

        // Put the duration back
        element.style[ durationName ] = duration;
    },

    _addItems : function( $newItems, animateIn, isSequential ) {
        var self = this,
            $passed,
            passed;

        if ( !self.supported ) {
            animateIn = false;
        }

        $newItems.addClass('shuffle-item');
        self._initItems( $newItems );
        self._setTransitions( $newItems );
        self.$items = self._getItems();

        // Hide all items
        $newItems.css('opacity', 0);

        // Get ones that passed the current filter
        $passed = self._filter( undefined, $newItems );
        passed = $passed.get();

        // How many filtered elements?
        self._updateItemCount();

        if ( animateIn ) {
            self._layout( passed, null, true, true );

            if ( isSequential ) {
                self._setSequentialDelay( $passed );
            }

            self._revealAppended( $passed );
        } else {
            self._layout( passed );
        }
    },

    _revealAppended : function( $newFilteredItems ) {
        var self = this;

        setTimeout(function() {
            $newFilteredItems.each(function(i, el) {
                self.transition({
                    from: 'reveal',
                    $this: $(el),
                    opacity: 1
                });
            });
        }, self.revealAppendedDelay);
    },


    /**
     * Public Methods
     */

    /**
     * The magic. This is what makes the plugin 'shuffle'
     * @param  {String|Function} category category to filter by. Can be a function
     * @param {Object} [sortObj] A sort object which can sort the filtered set
     */
    shuffle : function( category, sortObj ) {
        var self = this;

        if ( !self.enabled ) {
            return;
        }

        if ( !category ) {
            category = 'all';
        }

        self._filter( category );
        // Save the last filter in case elements are appended.
        self.lastFilter = category;

        // How many filtered elements?
        self._updateItemCount();

        self._resetCols();

        // Shrink each concealed item
        self._shrink();

        // If given a valid sort object, save it so that _reLayout() will sort the items
        if ( sortObj ) {
            self.lastSort = sortObj;
        }
        // Update transforms on .filtered elements so they will animate to their new positions
        self._reLayout();
    },

    /**
     * Gets the .filtered elements, sorts them, and passes them to layout
     *
     * @param {object} opts the options object for the sorted plugin
     * @param {Boolean} [fromFilter] was called from Shuffle.filter method.
     */
    sort: function( opts, fromFilter, isOnlyPosition ) {
        var self = this,
            items = self.$items.filter('.filtered').sorted(opts);

        if ( !fromFilter ) {
            self._resetCols();
        }

        self._layout(items, function() {
            if (fromFilter) {
                self.filterEnd();
            }
            self.sortEnd();
        }, isOnlyPosition);

        self.lastSort = opts;
    },

    /**
     * Relayout everything
     */
    resized: function( isOnlyLayout ) {
        if ( this.enabled ) {

            if ( !isOnlyLayout ) {
                // Get updated colCount
                this._setColumns();
            }

            // Layout items
            this._reLayout();
        }
    },

    /**
     * Use this instead of `update()` if you don't need the columns and gutters updated
     * Maybe an image inside `shuffle` loaded (and now has a height), which means calculations
     * could be off.
     */
    layout : function() {
        this.update( true );
    },

    update : function( isOnlyLayout ) {
        this.resized( isOnlyLayout );
    },

    /**
     * New items have been appended to shuffle. Fade them in sequentially
     * @param  {jQuery}  $newItems    jQuery collection of new items
     * @param  {Boolean}  [animateIn]    If false, the new items won't animate in
     * @param  {Boolean} [isSequential] If false, new items won't sequentially fade in
     */
    appended : function( $newItems, animateIn, isSequential ) {
        // True if undefined
        animateIn = animateIn === false ? false : true;
        isSequential = isSequential === false ? false : true;

        this._addItems( $newItems, animateIn, isSequential );
    },

    /**
     * Disables shuffle from updating dimensions and layout on resize
     */
    disable : function() {
        this.enabled = false;
    },

    /**
     * Enables shuffle again
     * @param  {Boolean} isUpdateLayout if undefined, shuffle will update columns and gutters
     */
    enable : function( isUpdateLayout ) {
        this.enabled = true;
        if ( isUpdateLayout !== false ) {
            this.update();
        }
    },

    /**
     * Remove 1 or more shuffle items
     * @param  {jQuery} $collection a jQuery object containing one or more element in shuffle
     * @return {Shuffle}             the shuffle object
     */
    remove : function( $collection ) {

        // If this isn't a jquery object, exit
        if ( !$collection.length || !$collection.jquery ) {
            return;
        }

        var self = this;

        // Hide collection first
        self._shrink( $collection, function() {
            var shuffle = this;

            // Remove the collection in the callback
            $collection.remove();

            // Update the items, layout, count and fire off `removed` event
            setTimeout(function() {
                shuffle.$items = shuffle._getItems();
                shuffle.layout();
                shuffle._updateItemCount();
                shuffle._fire( 'removed', [ $collection, shuffle ] );

                // Let it get garbage collected
                $collection = null;
            }, 0);
        });

        // Process changes
        self._processStyleQueue();

        return self;
    },

    /**
     * Destroys shuffle, removes events, styles, and classes
     */
    destroy: function() {
        var self = this;

        // If there is more than one shuffle instance on the page,
        // removing the resize handler from the window would remove them
        // all. This is why a unique value is needed.
        self.$window.off('.' + self.unique);

        // Reset container styles
        self.$container
            .removeClass('shuffle')
            .removeAttr('style')
            .removeData('shuffle');

        // Reset individual item styles
        self.$items
            .removeAttr('style')
            .removeClass('concealed filtered shuffle-item');

        // Set a flag so if a debounced resize has been triggered,
        // it can first check if it is actually destroyed and not doing anything
        self.destroyed = true;
    }

};

// Overrideable options
Shuffle.options = {
    group: 'all', // Filter group
    speed: 250, // Transition/animation speed (milliseconds)
    easing: 'ease-out', // css easing function to use
    itemSelector: '', // e.g. '.picture-item'
    sizer: null, // sizer element. Can be anything columnWidth is
    gutterWidth: 0, // a static number or function that tells the plugin how wide the gutters between columns are (in pixels)
    columnWidth: 0, // a static number or function that returns a number which tells the plugin how wide the columns are (in pixels)
    delimeter: null, // if your group is not json, and is comma delimeted, you could set delimeter to ','
    buffer: 0, // useful for percentage based heights when they might not always be exactly the same (in pixels)
    initialSort: null, // Shuffle can be initialized with a sort object. It is the same object given to the sort method
    throttle: $.throttle || null, // By default, shuffle will try to throttle the resize event. This option will change the method it uses
    throttleTime: 300, // How often shuffle can be called on resize (in milliseconds)
    sequentialFadeDelay: 150, // Delay between each item that fades in when adding items
    supported: Modernizr.csstransforms && Modernizr.csstransitions // supports transitions and transforms
};

// Not overrideable
Shuffle.settings = {
    $sizer: null,
    useSizer: false,
    itemCss : { // default CSS for each item
        position: 'absolute',
        top: 0,
        left: 0
    },
    offset: { top: 0, left: 0 },
    revealAppendedDelay: 300,
    keepSorted : true, // Keep sorted when shuffling/layout
    enabled: true,
    destroyed: false,
    styleQueue: [],
    prefixed: Modernizr.prefixed,
    threeD: Modernizr.csstransforms3d // supports 3d transforms
};


// Plugin definition
$.fn.shuffle = function( opts ) {
    var args = Array.prototype.slice.call( arguments, 1 );
    return this.each(function() {
        var $this = $( this ),
            shuffle = $this.data( 'shuffle' );

        // If we don't have a stored shuffle, make a new one and save it
        if ( !shuffle ) {
            shuffle = new Shuffle( $this, opts );
            $this.data( 'shuffle', shuffle );
        }

        if ( typeof opts === 'string' && shuffle[ opts ] ) {
            shuffle[ opts ].apply( shuffle, args );
        }
    });
};

})(jQuery, Modernizr);

/* ugallery */
/*global ugalleries, Modernizr */
jQuery(function($){
	var throttle = function(a,b,c){var d,e,f,g=null,h=0;c||(c={});var i=function(){h=c.leading===!1?0:new Date().getTime(),g=null,f=a.apply(d,e),g||(d=e=null)};return function(){var j=new Date().getTime();h||c.leading!==!1||(h=j);var k=b-(j-h);return d=this,e=arguments,0>=k||k>b?(clearTimeout(g),g=null,h=j,f=a.apply(d,e),g||(d=e=null)):g||c.trailing===!1||(g=setTimeout(i,k)),f}};

	var resizedInDesktop = false;
	var initialized = false;

	var updateHorizonalPadding =  function(gallery, absolute) {
		var container = gallery.find('.ugallery_items').width(),
			items = gallery.find('.ugallery_labels').length ? gallery.find('.ugallery_item.filtered') : gallery.find('.ugallery_item'),
			itemWidth = items.outerWidth(),
			row = 0,
			columns,
			thumbPaddingData,
			thumbPadding,
			thumbSidePadding,
			thumbBottomPadding,
			lockPadding,
			itemsTotalWidth;

		thumbSidePadding = gallery.data('thumb-side-padding') ? gallery.data('thumb-side-padding') : 0;
		thumbBottomPadding = gallery.data('thumb-bottom-padding') ? gallery.data('thumb-bottom-padding') : 0;
		thumbPaddingData = gallery.data('thumb-padding');
		lockPadding = gallery.data('thumb-lock-padding');

		if(typeof lockPadding === 'undefined' || lockPadding === "") {
			sidePadding = thumbSidePadding;
			bottomPadding = thumbBottomPadding;
		} else {
			sidePadding = typeof thumbPaddingData === 'undefined' ? 15 : thumbPaddingData;
			bottomPadding = sidePadding;
		}

		columns = Math.floor(container / (itemWidth + sidePadding));
		columns++;// Increase for 1 besause upper calculation will always give one less
		itemsTotalWidth = columns * itemWidth + (columns - 1) * sidePadding;
		if (itemsTotalWidth > container) {// But check if got too much
			columns--;
		}

		items.each(function(item_index) {
			var $this = $(this);

			if (absolute) {
				// Set top margin for all thumbs that are not in first row
				if (item_index + 1 > columns && bottomPadding) {
					$this.css('top', parseInt($this.css('top'), 10) + bottomPadding * row);
				}

				if (item_index > 0 && (item_index + 1) % columns === 0) {
					row++;
					if (bottomPadding && !gallery.data('height-adjusted')) {
						gallery.css('height', parseInt(gallery.css('height'), 10) + bottomPadding);
					}
				}
			} else {
				// Set top margin for all thumbs that are not in first row
				if (item_index + 1 > columns && bottomPadding) {
					$this.css('margin-top', bottomPadding);
				}
			}
		});

		if (absolute && !gallery.data('height-adjusted')) {
			gallery.css('height', parseInt(gallery.css('height'), 10) - parseInt(items.css('margin-bottom'), 10));
		}

		gallery.data('height-adjusted', true);
	};

	var bindShuffle = function($ugallery_grid, force) {
		if (Modernizr.mq('only all and (max-width: 1079px)')) {
			return;
		}
		if (!force) {
			if (resizedInDesktop) {
				return;
			}
		}
		resizedInDesktop = true;

		var $grids = $ugallery_grid || $('.ugallery_grid');

		$grids.each(function(){
			var grid = $(this);
			var sidePadding;
			var thumbSidePadding = grid.parent().data('thumb-side-padding') ? grid.parent().data('thumb-side-padding') : 0;
			var thumbPaddingData = grid.parent().data('thumb-padding');
			var lockPadding = grid.parent().data('thumb-lock-padding');

			if(typeof lockPadding === 'undefined' || lockPadding === "") {
				sidePadding = thumbSidePadding;
			} else {
				sidePadding = typeof thumbPaddingData === 'undefined' ? 15 : thumbPaddingData;
			}

			grid.parent().data('height-adjusted', false);

			grid.on('layout.shuffle', function(){
				setTimeout(function(){
					updateHorizonalPadding(grid.parent(), true);
				}, 20);
			});

			grid.shuffle({
				itemSelector: '#' + $(this).attr('rel') + ' .ugallery_item',
				gutterWidth: sidePadding,
				supported: false
			});

			grid.siblings('.ugallery_labels').on('click', '.ugallery_label_filter', function(e) {
				var filter;

				e.preventDefault();
				$(e.delegateTarget).find('a.filter_selected').removeClass('filter_selected');
				filter = $(e.target).addClass('filter_selected').attr('rel');
				grid.shuffle('shuffle', filter);
			});
		});
	};

	$(document).on('upfront-load', function() {
		Upfront.frontFunctions = Upfront.frontFunctions || {};
		Upfront.frontFunctions.galleryBindShuffle = bindShuffle;
	});

	/**
		The following is being done so that the gallery
		items inside a lightbox can shuffle after
		the lightbox shows up, in order to expand
		around in the available space
	**/
	$(document).on('upfront-lightbox-open', function() {
		setTimeout(function(){
			$(window).trigger('resize');
		}, 300);
	});

	if (typeof ugalleries !== 'undefined') {
		var titleSrc = function(item) {
			var itemId = item.el.closest('.ugallery_item').attr('rel'),
				text = gallery.find('.ugallery_lb_text[rel=' + itemId + ']')
			;
			if (text.length) {
				return text.html();
			}
			return '';
		};

		var resizeWithText = function() {
			var caption = this.content.find('figcaption'),
				maxHeight = this.wH - 120 - caption.outerHeight(),
				maxWidth = $(window).width() - 200
			;

			this.content.find('img').css({
				'max-width': maxWidth,
				'max-height': maxHeight
			});
		};

		/**
		 * re-Resize Magnific Popup 100ms after MFP open (iPhone issue)
		 */
		var resizeMFP = function() {
			if(/i(Pad|Phone|Pod)/g.test(navigator.userAgent))
				setTimeout(function(){
					$.magnificPopup.instance.updateSize();
				}, 500);
		};

		var setupLightbox = function(galleryId) {
			var data = $('#' + galleryId).find('.ugallery').data();
			var containerClass ='gallery-' + galleryId + '-lightbox';

			if (data.lightboxShowClose === true) {
				$('.mfp-close').show();
			} else {
				$('.mfp-close').hide();
			}

			if (data.lightboxShowImageCount === true) {
				$('.mfp-counter').show();
			} else {
				$('.mfp-counter').hide();
			}

			$('.mfp-content').css('background', data.lightboxActiveAreaBg);
			$('.mfp-bg').css('background', data.lightboxOverlayBg);

			$('.mfp-wrap, .mfp-bg').addClass(containerClass);

			if ($('style#' + containerClass).length === 0) {
				$('body').append('<style id="' + containerClass + '"></style>');
			}
			$('style#' + containerClass).html(data.styles);
		};

		var markup, gallery, magOptions;
		markup = '<div class="mfp-close">&times;</div><div class="glb-content-container"><figure class="glb-image-container"><div class="mfp-img"></div></figure><div class="glb-caption-container"><div class="mfp-title"></div><div class="mfp-counter"></div></div></div>';

		var cleanUpMfpBg = function() {
			$('.mfp-ready.mfp-bg').removeAttr('style');
		};

		for (var galleryId in ugalleries) {
			var data = $('#' + galleryId).find('.ugallery').data(),
				gallery = false,
				magOptions = ugalleries[galleryId].magnific
				;
			if (magOptions){
				gallery = $('#' + galleryId).find('.ugallery_item_image');
				$.each(gallery, function() {
					// Remove added linking to larger image - it breaks links in image description
					$(this).find('.ugallery_lb_text .ugallery_lightbox_link').removeAttr('href');
				});
				if (ugalleries[galleryId].useLightbox) {
					magOptions.image = {
						titleSrc: titleSrc,
						markup: markup
					};
				}

				magOptions.callbacks = {
					resize: resizeWithText,
					afterChange: resizeWithText,
					open: function(item) {
						// Retrieve ID from current item
						var newGalleryId = this.currItem.el.closest('.upfront-gallery').attr("id");

						// If newGalleryId is undefined refer to galleryId
						if(typeof newGalleryId === "undefined") {
							newGalleryId = galleryId
						}

						// Open magnificPopup
						setupLightbox(newGalleryId);
						resizeMFP();
					},
					close: cleanUpMfpBg
				};
				magOptions.closeOnBgClick = data.lightboxClickOutClose;
				gallery.magnificPopup(magOptions);
			} else {
				gallery = $('#' + galleryId).find('.ugallery_lightbox_link'),
				magOptions = {
					closeOnBgClick: data.lightboxClickOutClose,
					type: 'image',
					gallery: {
						enabled: 'true',
						tCounter: '<span class="mfp-counter">%curr% / %total%</span>'
					},
					titleSrc: 'title',
					verticalFit: true,
					image: {
						markup: ugalleries[galleryId].template.markup,
						titleSrc: 'title',
						verticalFit: true
					},
					callbacks: {
						resize: resizeWithText,
						afterChange: resizeWithText,
						open: function() {
							setupLightbox(galleryId);
							resizeMFP();
						}
					}
				};
				gallery.magnificPopup(magOptions);
			}
		}

		setTimeout(function(){
			$(window).trigger('resize');
		}, 300);
	}

	var lazyBindShuffle = throttle(function(){
		if (initialized === false) {
			initialized = true;
			bindShuffle();
			return;
		}

		if (Modernizr.mq('only all and (max-width: 1079px)')) {
			return;
		}

		bindShuffle();
	}, 100);

	$(window).on('resize', lazyBindShuffle);

	// Properly bind caption hover events, as they don't even work otherwise
	$(document)
		.on("mouseenter", ".ugallery_item a", function (e) {
			var $title = $(this).find(".ugallery-thumb-title.ugallery-caption-over");
			if ($title.length && $title.is(".ugallery-caption-on-hover-1")) $title.show();
		})
		.on("mouseleave", ".ugallery_item a", function (e) {
			var $title = $(this).find(".ugallery-thumb-title.ugallery-caption-over");
			if ($title.length && $title.is(".ugallery-caption-on-hover-1") && $title.closest('.redactor-box').length === 0) $title.hide();
		})
	;

});

/* uslider-front */
jQuery(function($){
	var setHeight = function(texts){
		var max = 0;
		texts.find('.uslide-text').each(function(){
			max = Math.max(max, $(this).height());
		});
		texts.height(max);
	};

	setTimeout(function(){
		$('.uslider-below').each(function(){
			setHeight($(this).find('.uslider-texts'));
		});
		$('.uslider-above').each(function(){
			setHeight($(this).find('.uslider-texts'));
		});
	}, 300);

	var magOptions = {
		type: 'image',
		gallery: {
			enabled: 'true',
			tCounter: '<span class="mfp-counter">%curr% / %total%</span>'
		},
		titleSrc: 'title',
		verticalFit: true,
		image: {
			titleSrc: 'title',
			verticalFit: true
		}
	};
	$('.uslider').each( function() {
		$(this).find('.uslider_lightbox_link').magnificPopup(magOptions);
	});
});

jQuery(function($){
	$('.upfront-output-uslider').each( function() {
		var slider = $(this),
			options = slider.find('.uslider').data();

		/* if it is enclosed inside a lightbox,
		 * then set it up on first instance of
		 * the lightbox showing up. Also store a flag
		 * issetup in order to avoid repeating this process
		 */

		if(slider.closest('div.upfront-region-lightbox').length ) {

			// slider should stay hidden before the lightbox opens up,
			// or it kills the lightbox alignment because of its extra height
			slider.hide();

			var lightbox = slider.closest('div.upfront-region-lightbox');

			$(document).on("upfront-lightbox-open", function(e, which) {
				// no need to set it up again and again
				if(slider.data('issetup'))
					return;

				// identify that the event is triggered for the same lightbox
				if($(which).attr('id') !== lightbox.attr('id'))
					return;

				// do the thing
				slider.show();
				setupSlider(slider);

				slider.data('issetup', true);

			});

			return;
		}

		$(document).on("upfront-breakpoint-change", function (e, breakpoint) {
			onBreakpointChange(slider, breakpoint);
			updateSlider(slider);
		});

		setupSlider(slider);

		function setupSlider(slider) {
			slider.find('.uslides').upfront_default_slider(options);
			onBreakpointChange(slider, upfront_get_breakpoint());
			updateSlider(slider);
		}

		function updateSlider(slider) {
			var uslides = slider.find('.uslides'),
				caption_height = 0
			;
			slider.find('.uslide-above').each(function(){
				var slide = $(this);
				slide.find('.uslide-caption').remove().prependTo(slide);
				caption_height = 1;
			});
			slider.find('.uslide-below').each(function(){
				var slide = $(this);
				slide.find('.uslide-caption').remove().appendTo(slide);
				caption_height = 1;
			});
			slider.find('.uslide-left').each(function(){
				var slide = $(this);
				slide.find('.uslide-caption').remove().prependTo(slide);
			});
			slider.find('.uslide-right').each(function(){
				var slide = $(this);
				slide.find('.uslide-caption').remove().appendTo(slide);
			});
			slider.find('.uslide-bottomOver, .uslide-middleCover, .uslide-bottomCover, .uslide-topCover').each(function() {
				var slide = $(this);
				slide.find('.uslide-caption').remove().prependTo(slide.find('.uslide-image'));
			});
			uslides.attr('data-caption_height', caption_height).trigger('refresh');
		}

		function onBreakpointChange(slider, breakpoint) {
			breakpoint = !breakpoint ? 'desktop' : breakpoint;
			slider.find('.uslide').each(function(){
				var slide = $(this),
					breakpoint_data = slide.attr('data-breakpoint'),
					map = breakpoint_data ? JSON.parse(breakpoint_data) : {},
					default_style = slide.attr('data-style'),
					all_styles = ['uslide-' + default_style]
				;
				for ( var bp in map ) {
					if ( !map[bp]['style'] ) continue;
					all_styles.push('uslide-' + map[bp]['style']);
				}
				if ( 'desktop' == breakpoint ) {
					slide.removeClass(all_styles.join(' ')).addClass('uslide-' + default_style);
				}
				else if ( breakpoint in map && map[breakpoint]['style'] ) {
					slide.removeClass(all_styles.join(' ')).addClass('uslide-' + map[breakpoint]['style']);
				}
			});
		}
	});
	
	
	/**
	 * Fix DOM children responsive preset classes
	 *
	 * Legacy preset elements double up their preset classes in DOM children,
	 * which doesn't get pick up by the responsive preset processing in `layout.js`.
	 *
	 * This is where we handle those cases, for the current element
	 *
	 * @param {Object} e Event - ignore
	 * @param {String} breakpoint The current breakpoint to inherit
	 */
	$(document).on("upfront-responsive_presets-changed", function (e, breakpoint) {
		$(".upfront-uslider").each(function () {
			var $root = $(this),
				rmap = $root.attr("data-preset_map"),
				map = rmap ? JSON.parse(rmap) : {},
				$items
			;
			
			// we have to provide proper fallback here, mobile -> tablet -> desktop
			if ( breakpoint == 'mobile' ) {
				map[breakpoint] = map[breakpoint] || map['tablet'] || map['desktop'];
			} else if ( breakpoint == 'tablet' ) {
				map[breakpoint] = map[breakpoint] || map['desktop'];
			} else {
				map[breakpoint] = map[breakpoint];
			}
			
			$items = $root.find(".uslider-caption-background");
			$.each(map, function (bp, preset) {
				$items.removeClass('slider-preset-' + preset);
				if (bp === breakpoint && typeof preset !== "undefined") $items.addClass('slider-preset-' + preset);
			});

		});
	});
	
});

/* utext */
jQuery(function($){
	// Update "preload" attribute to make videos show up and autoplay videos that are
	// set to autoplay.
	$('.uinsert-video-insert video').attr('preload', 'auto').each( function() {
		if ($(this).attr('data-autoplay-video') === "true") {
			$(this).attr('autoplay', 'true');
		}
	});
});

/* unewnavigation_responsive */

;(function($,sr){

  // debouncing function from John Hann
  // http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
  var debounce = function (func, threshold, execAsap) {
	  var timeout;

	  return function debounced () {
		  var obj = this, args = arguments;
		  function delayed () {
			  if (!execAsap)
				  func.apply(obj, args);
			  timeout = null;
		  }

		  if (timeout)
			  clearTimeout(timeout);
		  else if (execAsap)
			  func.apply(obj, args);

		  timeout = setTimeout(delayed, threshold || 400);
	  };
  };
  // smartresize
  jQuery.fn[sr] = function(fn){  return fn ? this.bind('resize', debounce(fn)) : this.trigger(sr); };

})(jQuery,'smartresize');

jQuery(document).ready(function($) {

	var $win = $(window),
		_cache = {}
	;
	var FloatNav = function ($el) {
		var adminbarheight = ($('div#wpadminbar').length > 0)?$('div#wpadminbar').outerHeight():0;
		var start_position = {
			top: 0,
			left: 0
		};
		var start_size = {
			width: 0,
			height: 0
		};
		var $root = $el;

		var start_floating = function () {

			$current_offset = $root.offset();

			$root.attr("data-already_floating", "yes");

			$root.closest('.upfront-output-wrapper').css('z-index', 999);
			$root.closest('.upfront-output-region-container').css('z-index', 999);

			if($root.hasClass('responsive_nav_toggler'))
				$root.offset($current_offset);
			else
				$root.css(start_size);

			if(adminbarheight > 0)
				$root.css('margin-top', adminbarheight);
		};

		var stop_floating = function () {
			$root
				.attr("style", "")
				.attr("data-already_floating", "no")
			;
			$root.closest('.upfront-output-wrapper').css('z-index', '');
			$root.closest('.upfront-output-region-container').css('z-index', '');
			if(adminbarheight > 0)
				$root.css('margin-top', '');
		};

		var dispatch_movement = function () {
			var top = $win.scrollTop();

			if (top > (start_position.top-adminbarheight) && !$root.is('[data-already_floating="yes"]')) start_floating();
			else if (top <= (start_position.top-adminbarheight) && $root.is('[data-already_floating="yes"]')) stop_floating();
		};

		var destroy = function () {
			start_position = {
				top: 0,
				left: 0
			};
			start_size = {
				width: 0,
				height: 0
			};
			$root = false;
			$win.off("scroll", dispatch_movement);
		};

		var init = function () {

			start_position = $root.offset();
			start_size = {width: $root.width(), height: $root.height()};
			$win
				.off("scroll", dispatch_movement)
				.on("scroll", dispatch_movement)
			;
		};
		init();

		return {
			destroy: destroy
		};
	};

	function floatInit () {
		//lets do the clean up first
		$(".upfront-navigation").each(function () {
			var $me = $(this);

			if ($me.data('style') === 'burger' || $me.data('style') === 'burger') {
				$toggler = $me.children('.responsive_nav_toggler');
				$toggler.attr('id', $me.attr('id')+'-toggler');
				if (_cache[$toggler.attr("id")]) _cache[$toggler.attr("id")].destroy();
			} else {
				if (_cache[$me.attr("id")]) _cache[$me.attr("id")].destroy();
			}
		});

		$(".upfront-navigation.upfront-navigation-float").each(function () {
			var $me = $(this);

			if($me.data('style') === 'burger' || $me.data('style') == 'burger') {
				$toggler = $me.children('.responsive_nav_toggler');
				$toggler.attr('id', $me.attr('id')+'-toggler');
				//if (_cache[$toggler.attr("id")]) _cache[$toggler.attr("id")].destroy();
				_cache[$toggler.attr("id")] = new FloatNav($toggler);
			}
			else {
				//if (_cache[$me.attr("id")]) _cache[$me.attr("id")].destroy();
				_cache[$me.attr("id")] = new FloatNav($me);
			}
		});
	}

	$win.on('load', floatInit);
	
	function hasNavInit() {
		//Work around for having the region container have a higher z-index if it contains the nav, so that the dropdowns, if overlapping to the following regions should not loose "hover" when the mouse travels down to the next region.
		$('div.upfront-navigation').each(function() {
			if (
				$(this).find('ul.sub-menu').length > 0
				//Also fix issues with overlapping elements with expanded hamburger menu.
				|| $(this).find('ul#menu-top-nav-menu').length > 0
			) {
				$(this).closest('.upfront-output-region-container, .upfront-output-region-sub-container').each(function() {
					$(this).addClass('upfront-region-container-has-nav');
				});

				//Make sure parent wrapper have higher z-index
				$(this).closest('.upfront-output-module').css({'z-index': '9999', position: 'relative'});
			}
		});
	}
	
	hasNavInit();
	
	// Show burger nav on enter
	$('.responsive_nav_toggler, .burger_nav_close').keydown(function(e) {
		if (e.which == 13) {
			$(this).closest('.upfront-navigation').find('.responsive_nav_toggler').trigger('click');
		}
	});
	
	// Hide burger nav if latest link
	$('.menu li a').on('focusout', function() {
		if($(this).parent().is(":last-child")) {
			$(this).closest('.upfront-navigation').find('.responsive_nav_toggler').trigger('click');
		}
	});

	$('body').on('touchstart click', '.burger_nav_close, .burger_overlay', null, function() {
		$(this).closest('.upfront-navigation').find('.responsive_nav_toggler').trigger('click');
	});

	$('body').on('touchstart click', '.upfront-navigation .upfront-navigation .responsive_nav_toggler', null, function(e) {
		e.preventDefault();
		if($(this).parent().find('ul.menu').css('display') == 'none') {
			$(this).closest('div.upfront-output-wrapper').addClass('on_the_top');

			if($(this).parent().attr('data-burger_over') != 'pushes' && $(this).parent().attr('data-burger_alignment') != 'whole') {
				$('<div class="burger_overlay"></div>').insertBefore($(this).parent().find('ul.menu'));
			}

			$(this).parent().attr('data-burger_open', "1");

			$(this).parent().find('ul.menu').show();
			//$(this).parent().find('ul.sub-menu').show();


			var offset = $(this).parent().find('ul.menu').position();

			//$(e.target).closest('.responsive_nav_toggler').css({position: 'fixed', left: offset.left, top: offset.top+(($('div#wpadminbar').length && $('div#wpadminbar').css('display') == 'block')?$('div#wpadminbar').outerHeight():0)});
			//$(this).parent().find('ul.menu').css('padding-top', '60px');
			var close_icon = $('<button class="burger_nav_close"></button>');

			$(this).parent().find('ul.menu').prepend($('<li>').addClass('wrap_burger_nav_close').append(close_icon));

			//close_icon.css({position: 'fixed', left: offset.left+$(this).parent().find('ul.menu').width()-close_icon.width()-10, top: offset.top+(($('div#wpadminbar').length && $('div#wpadminbar').css('display') == 'block')?$('div#wpadminbar').outerHeight():0) + 10});

			/*

			if($(this).parent().attr('data-burger_over') == 'pushes')
				pushContent($(this).parent());
			*/


			if($(this).parent().attr('data-burger_over') == 'pushes' && $(this).parent().attr('data-burger_alignment') == 'top') {

				$('div#page').css('margin-top', $(this).parent().find('ul.menu').outerHeight());


				//var topbar_height = $('div#upfront-ui-topbar').outerHeight();
				var adminbar_height = ($('div#wpadminbar').length > 0)?$('div#wpadminbar').outerHeight():0;

				$(this).parent().find('ul.menu').offset({top:adminbar_height, left:$('div').offset().left});
				$(this).parent().find('ul.menu').css('width', $('div#page').width() + 'px');

			}


			$(this).closest('.upfront-output-region-container').each(function() {
				$(this).addClass('upfront-region-container-has-nav');
			});

			$(document).trigger('upfront-responsive-nav-open');

		}
		else {
			$(this).parent().find('ul.menu').hide();
			$(this).parent().find('ul.menu').siblings('.burger_overlay').remove();
			//$(this).parent().find('ul.sub-menu').hide();

			$(this).parent().removeAttr('data-burger_open');

			//$(e.target).closest('.responsive_nav_toggler').css({position: '', left: '', top: ''});
			$(this).parent().find('ul.menu').css({
				top: '',
				left: '',
				width: ''
			});

			$('.burger_nav_close').parent('li.wrap_burger_nav_close').remove();

			$(this).closest('div.upfront-output-wrapper').removeClass('on_the_top');

			/*
			if($(this).parent().attr('data-burger_over') == 'pushes')
				pullContent($(this).parent());
			*/

			if($(this).parent().attr('data-burger_over') == 'pushes')
				$('div#page').css('margin-top', '');


			$(this).closest('.upfront-output-region-container').each(function() {
				$(this).removeClass('upfront-region-container-has-nav');
			});

			$(document).trigger('upfront-responsive-nav-close');
		}
	});

	function pushContent(nav) {
		var currentwidth = $('div#page').width();
		var navwidth = nav.find('ul.menu').width();
		var navheight = nav.find('ul.menu').height();

		$('div#page').css('margin-'+nav.data('burger_alignment'), (nav.data('burger_alignment') == 'top' || nav.data('burger_alignment') == 'whole')?navheight:navwidth);

		if(nav.data('burger_alignment') == 'left' || nav.data('burger_alignment') == 'right') {
			$('div#page').css('width', currentwidth-navwidth);
			$('div#page').css('minWidth', currentwidth-navwidth);
		}
	}

	function pullContent(nav) {
		$('div#page').css('margin-'+nav.data('burger_alignment'), '');
		$('div#page').css('width', '');
		$('div#page').css('minWidth', '');
	}

	// the following is used to find the current breakpoint on resize
	var previous_breakpoint = '';
	var current_breakpoint = '';

	function get_breakpoint(){
		if (!window.getComputedStyle) {
				window.getComputedStyle = function(el, pseudo) {
				this.el = el;
				this.getPropertyValue = function(prop) {
					var re = /(\-([a-z]){1})/g;
					if (prop == 'float') prop = 'styleFloat';
					if (re.test(prop)) {
						prop = prop.replace(re, function () {
							return arguments[2].toUpperCase();
						});
					}
					return el.currentStyle[prop] ? el.currentStyle[prop] : null;
				};
				return this;
			};
		}

		var breakpoint = window.getComputedStyle(document.body,':after').getPropertyValue('content');

		if(breakpoint === null && $('html').hasClass('ie8')) {
			breakpoint = window.get_breakpoint_ie8($( window ).width());
			$(window).trigger('resize');
		}

		if(breakpoint) {
			breakpoint = breakpoint.replace(/['"]/g, '');
			if (current_breakpoint != breakpoint) {
				previous_breakpoint = current_breakpoint;
				current_breakpoint = breakpoint;
			}
			return breakpoint;
		}
	}

	var upfrontIsLoaded = function() {
		// Check if cssEditor is defined, than we have Upfront loaded
		if (typeof Upfront !== 'undefined' && typeof Upfront.Application !== 'undefined' && typeof Upfront.Application.cssEditor !== 'undefined') {
			return true;
		}

		return false;
	};


	function roll_responsive_nav(selector, bpwidth) {
		if (upfrontIsLoaded()) return;

		var elements = (typeof(selector) == 'object')?selector:$(selector);
		elements.each(function () {

			var breakpoints = $(this).data('breakpoints');

			var usingNewAppearance = $(this).data('new-appearance');

			var currentwidth = (typeof(bpwidth) != 'undefined') ? parseInt(bpwidth, 10) : $(window).width();

			var currentKey, preset, responsive_css;

			if (breakpoints.preset) {
				currentKey = get_breakpoint();
				if(currentKey === '')
					currentKey = 'desktop';

				preset = breakpoints.preset[currentKey];

				if (!preset) return;

				/** if breakpoint has menu_style set to burger, but no
				 burger_alignment is defined, set it to default
				 **/
				if(preset && preset.menu_style === 'burger' && !preset.burger_alignment ) {
					preset.burger_alignment= 'left';
				}

				if (preset.menu_style == 'burger') {
					$(this).attr('data-style', 'burger');
					$(this).attr('data-stylebk', 'burger');
					$(this).attr('data-alignment', ( preset.menu_alignment ? preset.menu_alignment : $(this).data('alignmentbk') ));
					$(this).attr('data-burger_alignment', preset.burger_alignment);
					$(this).attr('data-burger_over', preset.burger_over);

					// Add responsive nav toggler
					if(!$(this).find('.responsive_nav_toggler').length)
						$(this).prepend($('<button class="responsive_nav_toggler"><div></div><div></div><div></div></button>'));

					//offset a bit if admin bar or side bar is present
					if($('div#wpadminbar').length && $('div#wpadminbar').css('display') == 'block') {
						$(this).find('ul.menu').css('margin-top', $('div#wpadminbar').outerHeight());
					}

					/*if ($(this).hasClass('upfront-output-unewnavigation')) {
						$('head').find('style#responsive_nav_sidebar_offset').remove();
						responsive_css = 'div.upfront-navigation div[data-style="burger"][ data-burger_alignment="top"] ul.menu, div.upfront-navigation div[data-style="burger"][ data-burger_alignment="whole"] ul.menu {left:'+parseInt($('div.upfront-regions').offset().left)+'px !important; right:'+parseInt(($(window).width()-currentwidth-$('div#sidebar-ui').outerWidth()) / 2)+'px !important; } ';
						responsive_css = responsive_css + 'div.upfront-navigation div[data-style="burger"][ data-burger_alignment="left"] ul.menu {left:'+parseInt($('div.upfront-regions').offset().left)+'px !important; right:inherit !important; width:'+parseInt(30/100*$('div.upfront-regions').outerWidth())+'px !important;} ';
						responsive_css = responsive_css + 'div.upfront-navigation div[data-style="burger"][ data-burger_alignment="right"] ul.menu {left:inherit !important; right:'+parseInt(($(window).width()-currentwidth-$('div#sidebar-ui').outerWidth()) / 2)+'px !important; width:'+parseInt(30/100*$('div.upfront-regions').outerWidth())+'px !important; } ';
						responsive_css = responsive_css + 'div.upfront-navigation div[data-style="burger"] ul.menu {top:'+parseInt($('div#upfront-ui-topbar').outerHeight())+'px !important; } ';

						$('head').append($('<style id="responsive_nav_sidebar_offset">'+responsive_css+'</style>'));
					}
					//Z-index the container module to always be on top, in the layout edit mode
					$(this).closest('div.upfront-newnavigation_module').css('z-index', 3);*/


					$(this).find('ul.menu').hide();
				} else {
					if(typeof usingNewAppearance !== "undefined" && usingNewAppearance) {
						$(this).attr('data-style', ( preset.menu_style ? preset.menu_style : $(this).data('stylebk') ));
						$(this).attr('data-alignment', ( preset.menu_alignment ? preset.menu_alignment : $(this).data('alignmentbk') ));
					} else {
						//We should reset the data-style and data-alignment if element is not migrated
						if(typeof breakpoints[currentKey] !== "undefined" && typeof breakpoints[currentKey].menu_style !== "undefined") {
							$(this).attr('data-style', ( breakpoints[currentKey].menu_style ));
						}
						if(typeof breakpoints[currentKey] !== "undefined" && typeof breakpoints[currentKey].menu_alignment !== "undefined") {
							$(this).attr('data-alignment', ( breakpoints[currentKey].menu_alignment ));
						}
					}

					$(this).removeAttr('data-burger_alignment','');
					$(this).removeAttr('data-burger_over', '');

					// Remove responsive nav toggler
					$(this).find('.responsive_nav_toggler').remove();
					$(this).find('ul.menu').show();

					//remove any display:block|none specifications from the sub-menus
					$(this).find('ul.menu, ul.sub-menu').each(function() {
						$(this).css('display', '');
					});

					// remove any adjustments done because of the sidebar or the adminbar
					if($('div#wpadminbar').length) {
						$(this).find('ul.menu').css('margin-top', '');
					}


					//remove the z-index from the container module
					//$(this).closest('div.upfront-newnavigation_module').css('z-index', '');
				}

				$(this).find('ul.menu').siblings('.burger_overlay').remove();

				if(preset.is_floating && preset.is_floating == 'yes')
					$(this).addClass('upfront-navigation-float');
				else
					$(this).removeClass('upfront-navigation-float');
			} else {
				// Leave old code for backward compatibility
				var bparray = [];
				for (var key in breakpoints) {
					if (key !== 'preset') bparray.push(breakpoints[key]);
				}

				bparray.sort(function(a, b) {
					if (a && b && a.width && b.width) {
						return a.width - b.width;
					}
					return 0;
				});

				for (key in bparray) {
					if(bparray[key] && bparray[key]['width'] && parseInt(currentwidth, 10) >= parseInt(bparray[key]['width'], 10)) {

						if(bparray[key]['burger_menu'] == 'yes') {

							$(this).attr('data-style', 'burger');
							$(this).attr('data-alignment', ( bparray[key]['menu_alignment'] ? bparray[key]['menu_alignment'] : $(this).data('alignmentbk') ));
							$(this).attr('data-burger_alignment', bparray[key]['burger_alignment']);
							$(this).attr('data-burger_over', bparray[key]['burger_over']);

							// Add responsive nav toggler
							if(!$(this).find('.responsive_nav_toggler').length)
								$(this).prepend($('<button class="responsive_nav_toggler"><div></div><div></div><div></div></button>'));

							//offset a bit if admin bar or side bar is present
							if($('div#wpadminbar').length && $('div#wpadminbar').css('display') == 'block') {
								$(this).find('ul.menu').css('margin-top', $('div#wpadminbar').outerHeight());
								//$(this).find('div.responsive_nav_toggler').css('margin-top', $('div#wpadminbar').outerHeight());
							}

							/*if($(this).hasClass('upfront-output-unewnavigation')) {

								$('head').find('style#responsive_nav_sidebar_offset').remove();
								responsive_css = 'div.upfront-navigation div[data-style="burger"][ data-burger_alignment="top"] ul.menu, div.upfront-navigation div[data-style="burger"][ data-burger_alignment="whole"] ul.menu {left:'+parseInt($('div.upfront-regions').offset().left)+'px !important; right:'+parseInt(($(window).width()-currentwidth-$('div#sidebar-ui').outerWidth()) / 2)+'px !important; } ';

								responsive_css = responsive_css + 'div.upfront-navigation div[data-style="burger"][ data-burger_alignment="left"] ul.menu {left:'+parseInt($('div.upfront-regions').offset().left)+'px !important; right:inherit !important; width:'+parseInt(30/100*$('div.upfront-regions').outerWidth())+'px !important;} ';

								responsive_css = responsive_css + 'div.upfront-navigation div[data-style="burger"][ data-burger_alignment="right"] ul.menu {left:inherit !important; right:'+parseInt(($(window).width()-currentwidth-$('div#sidebar-ui').outerWidth()) / 2)+'px !important; width:'+parseInt(30/100*$('div.upfront-regions').outerWidth())+'px !important; } ';
								responsive_css = responsive_css + 'div.upfront-navigation div[data-style="burger"] ul.menu {top:'+parseInt($('div#upfront-ui-topbar').outerHeight())+'px !important; } ';

								$('head').append($('<style id="responsive_nav_sidebar_offset">'+responsive_css+'</style>'));
							}
							//Z-index the container module to always be on top, in the layout edit mode
							$(this).closest('div.upfront-newnavigation_module').css('z-index', 3);*/

							$(this).find('ul.menu').siblings('.burger_overlay').remove();
							$(this).find('ul.menu').hide();
						}
						else {
							$(this).attr('data-style', ( bparray[key]['menu_style'] ? bparray[key]['menu_style'] : $(this).data('stylebk') ));
							$(this).attr('data-alignment', ( bparray[key]['menu_alignment'] ? bparray[key]['menu_alignment'] : $(this).data('alignmentbk') ));
							$(this).removeAttr('data-burger_alignment','');
							$(this).removeAttr('data-burger_over', '');

							// Remove responsive nav toggler
							$(this).find('.responsive_nav_toggler').remove();
							$(this).find('ul.menu').show();

							//remove any display:block|none specifications from the sub-menus
							$(this).find('ul.menu, ul.sub-menu').each(function() {
								$(this).css('display', '');
							});

							// remove any adjustments done because of the sidebar or the adminbar
							if($('div#wpadminbar').length) {
								$(this).find('ul.menu').css('margin-top', '');
							}

							//remove the z-index from the container module
							//$(this).closest('div.upfront-newnavigation_module').css('z-index', '');
						}

						if(bparray[key]['is_floating'] && bparray[key]['is_floating'] == 'yes')
							$(this).addClass('upfront-navigation-float');
						else
							$(this).removeClass('upfront-navigation-float');
					}
				}
			}
		});
	}
	roll_responsive_nav(".upfront-output-unewnavigation > .upfront-navigation");

	$(window).smartresize(function() {
		$('div#page').css('margin-top', '');
		$('.responsive_nav_toggler').css({position: '', left: '', top: ''});
		$('ul.menu').css('padding-top', '');
		$('.burger_nav_close').parent('li.wrap_burger_nav_close').remove();

		roll_responsive_nav(".upfront-output-unewnavigation > .upfront-navigation");
		floatInit();
	});

	$(document).on('changed_breakpoint', function(e) {
		roll_responsive_nav( e.selector, e.width);
	});
	
	/**
		TOGGLING BREAKPOINT MENU
	**/
	$(document).on('upfront-breakpoint-change', function(e, breakpoint) {
		hasNavInit();
		toggle_breakpoint_menu(breakpoint);
	});
	function toggle_breakpoint_menu(breakpoint) {
		breakpoint = breakpoint || 'desktop';
		$('.upfront-output-object.upfront-output-unewnavigation').each(function(){
			var $this = $(this),
				$target = get_target_breakpoint_menu($this, breakpoint)
			;
			if ( $target.length ) {
				$this.find('.upfront-breakpoint-navigation').hide();
				$target.show();
			}
		});
	}
	// proper fallback to higher menu if target breakpoint menu not set
	function get_target_breakpoint_menu(parent, breakpoint) {
		var $target = parent.find('.upfront-'+ breakpoint +'-breakpoint-navigation');
		if ( breakpoint == 'mobile' ) {
			// fallback to tablet menu
			if ( $target.length == 0 ) $target = parent.find('.upfront-tablet-breakpoint-navigation');
			// fallback to desktop menu
			if ( $target.length == 0 ) $target = parent.find('.upfront-desktop-breakpoint-navigation');
		} else if ( breakpoint == 'tablet' ) {
			// fallback to desktop menu
			if ( $target.length == 0 ) $target = parent.find('.upfront-desktop-breakpoint-navigation');
		} 
		return $target;
	}
	toggle_breakpoint_menu(window.upfront_get_breakpoint());
});

/* ubutton_script */
;(function($){

	/**
	 * Fix DOM children responsive preset classes
	 *
	 * Legacy preset elements double up their preset classes in DOM children,
	 * which doesn't get pick up by the responsive preset processing in `layout.js`.
	 *
	 * This is where we handle those cases, for the current element
	 *
	 * @param {Object} e Event - ignore
	 * @param {String} breakpoint The current breakpoint to inherit
	 */
	$(document).on("upfront-responsive_presets-changed", function (e, breakpoint) {
		$(".upfront-button").each(function () {
			var $root = $(this),
				rmap = $root.attr("data-preset_map"),
				map = rmap ? JSON.parse(rmap) : {},
				$items
			;
			// we have to provide proper fallback here, mobile -> tablet -> desktop
			if ( breakpoint == 'mobile' ) {
				map[breakpoint] = map[breakpoint] || map['tablet'] || map['desktop'];
			} else if ( breakpoint == 'tablet' ) {
				map[breakpoint] = map[breakpoint] || map['desktop'];
			} else {
				map[breakpoint] = map[breakpoint];
			}

			$items = $root.find(".upfront_cta");
			$.each(map, function (bp, preset) {
				$items.removeClass('button-preset-' + preset);
				if (bp === breakpoint && typeof preset !== "undefined") $items.addClass('button-preset-' + preset);
			});

		});
	});
})(jQuery);

/* uaccordion_script */
;(function($){
	$(function () {
		$('.accordion-panel:not(.accordion-panel-active) .accordion-panel-content').hide();	
		
		$('body').on('touchstart click', '.accordion-panel', function(event) {
			var $panel = $(event.currentTarget);
			var contentId;

			if ($panel.hasClass('accordion-panel-active')) {
				return;
			}
			$panel.addClass('accordion-panel-active').find('.accordion-panel-content').slideDown();
			$panel.siblings().removeClass('accordion-panel-active').find('.accordion-panel-content').slideUp();
		});
		
		/**
		 * Activate focused panel with Enter keydown
		 */
		$('.accordion-panel-title').keydown(function(e) {
			if (e.which == 13) {
				$(this).click();
			}

			if (e.which == 38 || e.which == 37) {
				$(this).parent().prev('.accordion-panel').find('.accordion-panel-title').focus().click();
			}
			
			if (e.which == 40 || e.which == 39) {
				$(this).parent().next('.accordion-panel').find('.accordion-panel-title').focus().click();
			}
		});
	});

	/**
	 * Fix DOM children responsive preset classes
	 *
	 * Legacy preset elements double up their preset classes in DOM children,
	 * which doesn't get pick up by the responsive preset processing in `layout.js`.
	 *
	 * This is where we handle those cases, for the current element
	 *
	 * @param {Object} e Event - ignore
	 * @param {String} breakpoint The current breakpoint to inherit
	 */
	$(document).on("upfront-responsive_presets-changed", function (e, breakpoint) {
		$(".upfront-accordion").each(function () {
			var $root = $(this),
				rmap = $root.attr("data-preset_map"),
				map = rmap ? JSON.parse(rmap) : {},
				$items
			;
			// we have to provide proper fallback here, mobile -> tablet -> desktop
			if ( breakpoint == 'mobile' ) {
				map[breakpoint] = map[breakpoint] || map['tablet'] || map['desktop'];
			} else if ( breakpoint == 'tablet' ) {
				map[breakpoint] = map[breakpoint] || map['desktop'];
			} else {
				map[breakpoint] = map[breakpoint];
			}

			$items = $root.find(".upfront-accordion-container");
			$.each(map, function (bp, preset) {
				$items.removeClass('accordion-preset-' + preset);
				if (bp === breakpoint && typeof preset !== "undefined") $items.addClass('accordion-preset-' + preset);
			});

		});
	});
})(jQuery);

