Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in /home/oliver1/public_html/grandprairiecomputerrepair.com/wp-content/plugins/essential-grid/includes/item-skin.class.php on line 1142
Deprecated: Function create_function() is deprecated in /home/oliver1/public_html/grandprairiecomputerrepair.com/wp-content/plugins/essential-grid/essential-grid.php on line 98
Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; flickrRSS has a deprecated constructor in /home/oliver1/public_html/grandprairiecomputerrepair.com/wp-content/plugins/flickr-rss/flickrrss.php on line 13
Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; SEOLinks has a deprecated constructor in /home/oliver1/public_html/grandprairiecomputerrepair.com/wp-content/plugins/seo-automatic-links/seo-links.php on line 13
Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; udesignShortcodeInsert has a deprecated constructor in /home/oliver1/public_html/grandprairiecomputerrepair.com/wp-content/plugins/udesign-shortcode-insert-button/udesignShortcodeInsert.php on line 27
Deprecated: Function create_function() is deprecated in /home/oliver1/public_html/grandprairiecomputerrepair.com/wp-content/plugins/udesign-shortcode-insert-button/udesignShortcodeInsert.php on line 55
Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; add_udesignShortcodeInsert_button has a deprecated constructor in /home/oliver1/public_html/grandprairiecomputerrepair.com/wp-content/plugins/udesign-shortcode-insert-button/tinymce/tinymce.php on line 3
Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/oliver1/public_html/grandprairiecomputerrepair.com/wp-content/plugins/js_composer/include/classes/core/class-vc-mapper.php on line 111
Warning: Cannot modify header information - headers already sent by (output started at /home/oliver1/public_html/grandprairiecomputerrepair.com/wp-content/plugins/essential-grid/includes/item-skin.class.php:1142) in /home/oliver1/public_html/grandprairiecomputerrepair.com/wp-content/themes/upfront/library/class_upfront_server.php on line 73
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 = $(''),
close= $(''),
close_icon= $('');
$("[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($('
'+lightbox.data('closetext')+'
'));
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');
$('').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');
$('')
.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('')
;
this.opts = data;
this.index = 0;
this.pause = false;
this.timer = false;
this.update_configs();
this.update_items($items);
this.$slider.append($(''));
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 = $('');
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(''+index+'');
});
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('')
.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 xyz
produces $.xyz and $.fn.xyz. */
_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:
data-<plugin name>="<setting name>: '<value>', ...".
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 inst.options[name], new value in options[name].
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 _preDestroy 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 _postAttach or _optionsChanged 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.
Displays a challenge to confirm that the viewer is a real person.
Expects HTML like:
<input...>
Provide inline configuration like:
<input data-realperson="name: 'value'">...>
@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('');
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 = '
' +
'
';
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, ' ').replace(/\*/g, inst.options.dot) +
' ';
}
html += ' ';
}
html += '
' +
inst.options.regenerate + '
';
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(
$('
').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(' '));
} 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 = '
',cursor:"mfp-zoom-out-cur",titleSrc:"title",verticalFit:!0,tError:'The image 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:'',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('').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=["",'"].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
* @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#' + containerClass).html(data.styles);
};
var markup, gallery, magOptions;
markup = '
×
';
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: '%curr% / %total%'
},
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: '%curr% / %total%'
},
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');
}
});
});
/* 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);
/* upfront_youtube */
;(function($){
/*
* Replace main video placeholder image+button with actual main video.
*/
function replace_ph_with_video(ph) {
if (ph.size() === 0) return;
var video_id = ph.data('video-id') || 'none';
var loop = ph.data('loop');
var width = ph.data('width') || parseInt(ph.width(), 10);
var height = ph.data('height') || parseInt(ph.height(), 10);
if (loop) loop = '&' + loop;
ph.after('');
ph.remove();
}
/**
* Take data from list item and load video in player.
* @param {Object} - jQuery object of selected list item
*/
function load_video_from_list(list_item) {
var el = list_item.parents('.upfront-youtube-container');
var video_id = list_item.data('video-id') || 'none';
// Make sure iframe is present and initialized properly
if (el.find('iframe').size() === 0) {
replace_ph_with_video(el.find('.ufyt_main-video-placeholder'));
}
// Setup ifram and title for selected video
var videoUrl = 'https://www.youtube.com/embed/' + video_id + '?modestbranding=1';
el.find('iframe').attr('src', videoUrl);
el.find('.ufyt_main-video-title').html(list_item.find('h4').html());
// Handle hidding active video thumbnail
if(el.data('first-hidden')) {
list_item.siblings().css('display', 'inline-block');
list_item.hide();
}
}
$('.uyoutube-gallery-item, .uyoutube-list-item').on('click', function(event) {
load_video_from_list($(this));
});
$('.ufyt_main-video-placeholder').on('click', function(event) {
replace_ph_with_video($(this));
});
})(jQuery);