first commit

This commit is contained in:
CHIEFSOFT\ameye
2023-12-28 16:20:07 -05:00
commit b114fdf4fa
5377 changed files with 1850677 additions and 0 deletions
@@ -0,0 +1,69 @@
// global sekFrontLocalized, nimbleListenTo
/* ------------------------------------------------------------------------- *
* ACCORDION MODULE
/* ------------------------------------------------------------------------- */
(function(w, d){
var callbackFunc = function() {
jQuery( function($){
$( 'body' ).on( 'click sek-expand-accord-item', '.sek-accord-item > .sek-accord-title', function( evt ) {
//evt.preventDefault();
//evt.stopPropagation();
var $item = $(this).closest( '.sek-accord-item'),
$accordion = $(this).closest( '.sek-accord-wrapper');
// Note : cast the boolean to a string by adding +''
if ( "true" == $accordion.data('sek-one-expanded')+'' ) {
$accordion.find('.sek-accord-item').not( $item ).each( function() {
var $current_item = $(this);
$current_item.find('.sek-accord-content').stop( true, true ).slideUp( {
duration : 200,
start : function() {
// If already expanded, make sure inline style display:block is set
// otherwise, the CSS style display:none will apply first, making the transition brutal.
if ( "true" == $current_item.attr('data-sek-expanded')+'' ) {
$current_item.find('.sek-accord-content').css('display', 'block');
}
$current_item.attr('data-sek-expanded', "false" );
}
});
});
}
if ( 'sek-expand-accord-item' === evt.type && "true" == $item.attr('data-sek-expanded')+'' ) {
return;
} else {
$item.find('.sek-accord-content').stop( true, true ).slideToggle({
duration : 200,
start : function() {
// If already expanded, make sure inline style display:block is set
// otherwise, the CSS style display:none will apply first, making the transition brutal.
if ( "true" == $item.attr('data-sek-expanded')+'' ) {
$item.find('.sek-accord-content').css('display', 'block');
}
$item.attr('data-sek-expanded', "false" == $item.attr('data-sek-expanded')+'' ? "true" : "false" );
$item.trigger( "true" == $item.attr('data-sek-expanded') ? 'sek-accordion-expanded' : 'sek-accordion-collapsed' );
}
});
}
});// on 'click'
// When customizing, expand the currently edited item
// @see CZRItemConstructor in api.czrModuleMap.czr_img_slider_collection_child
if ( window.wp && ! nb_.isUndefined( wp.customize ) ) {
wp.customize.preview.bind('sek-item-focus', function( params ) {
var $itemEl = $('[data-sek-item-id="' + params.item_id +'"]', '.sek-accord-wrapper').first();
if ( 1 > $itemEl.length )
return;
$itemEl.find('.sek-accord-title').trigger('sek-expand-accord-item');
});
}
});//jQuery()
};/////////////// callbackFunc
// on 'nb-app-ready', jQuery is loaded
nb_.listenTo('nb-app-ready', callbackFunc );
}(window, document));
@@ -0,0 +1 @@
window,document,nb_.listenTo("nb-app-ready",function(){jQuery(function(d){d("body").on("click sek-expand-accord-item",".sek-accord-item > .sek-accord-title",function(e){var t=d(this).closest(".sek-accord-item"),a=d(this).closest(".sek-accord-wrapper");"true"==a.data("sek-one-expanded")+""&&a.find(".sek-accord-item").not(t).each(function(){var e=d(this);e.find(".sek-accord-content").stop(!0,!0).slideUp({duration:200,start:function(){"true"==e.attr("data-sek-expanded")+""&&e.find(".sek-accord-content").css("display","block"),e.attr("data-sek-expanded","false")}})}),"sek-expand-accord-item"===e.type&&"true"==t.attr("data-sek-expanded")+""||t.find(".sek-accord-content").stop(!0,!0).slideToggle({duration:200,start:function(){"true"==t.attr("data-sek-expanded")+""&&t.find(".sek-accord-content").css("display","block"),t.attr("data-sek-expanded","false"==t.attr("data-sek-expanded")+""?"true":"false"),t.trigger("true"==t.attr("data-sek-expanded")?"sek-accordion-expanded":"sek-accordion-collapsed")}})}),window.wp&&!nb_.isUndefined(wp.customize)&&wp.customize.preview.bind("sek-item-focus",function(e){var t=d('[data-sek-item-id="'+e.item_id+'"]',".sek-accord-wrapper").first();t.length<1||t.find(".sek-accord-title").trigger("sek-expand-accord-item")})})});
@@ -0,0 +1,160 @@
// global sekFrontLocalized, nimbleListenTo
/* ===================================================
* jquery.fn.parallaxBg v1.0.0
* Created in October 2018.
* Inspired from https://github.com/presscustomizr/front-jquery-plugins/blob/master/jqueryParallax.js
* ===================================================
*/
(function(w, d){
var callbackFunc = function() {
(function ( $, window ) {
//defaults
var pluginName = 'parallaxBg',
defaults = {
parallaxForce : 40,
oncustom : [],//list of event here
matchMedia : 'only screen and (max-width: 800px)'
};
function Plugin( element, options ) {
this.element = $(element);
//this.element_wrapper = this.element.closest( '.parallax-wrapper' );
this.options = $.extend( {}, defaults, options, this.parseElementDataOptions() ) ;
this._defaults = defaults;
this._name = pluginName;
this.init();
}
Plugin.prototype.parseElementDataOptions = function () {
return this.element.data();
};
//can access this.element and this.option
//@return void
Plugin.prototype.init = function () {
var self = this;
//cache some element
this.$_window = nb_.cachedElements.$window;
this.doingAnimation = false;
this.isVisible = false;
this.isBefore = false;//the element is before the scroll point
this.isAfter = true;// the element is after the scroll point
// normalize the parallax ratio
// must be a number 0 > ratio > 100
if ( 'number' !== typeof( self.options.parallaxForce ) || self.options.parallaxForce < 0 ) {
if ( sekFrontLocalized.isDevMode ) {
console.log('parallaxBg => the provided parallaxForce is invalid => ' + self.options.parallaxForce );
}
self.options.parallaxForce = this._defaults.parallaxForce;
}
if ( self.options.parallaxForce > 100 ) {
self.options.parallaxForce = 100;
}
//the scroll event gets throttled with the requestAnimationFrame
this.$_window.on( 'scroll', function(_evt) { self.maybeParallaxMe(_evt); } );
//debounced resize event
this.$_window.on( 'resize', nb_.debounce( function(_evt) {
self.maybeParallaxMe(_evt);
}, 100 ) );
//on load
this.checkIfIsVisibleAndCacheProperties();
this.setTopPositionAndBackgroundSize();
};
//@see https://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/
Plugin.prototype.setTopPositionAndBackgroundSize = function() {
var self = this;
// options.matchMedia is set to 'only screen and (max-width: 768px)' by default
// if a match is found, then reset the top position
if ( nb_.isFunction( window.matchMedia ) && matchMedia( self.options.matchMedia ).matches ) {
this.element.css({'background-position-y' : '', 'background-attachment' : '' });
return;
}
var $element = this.element,
elemHeight = $element.outerHeight(),
winHeight = this.$_window.height(),
offsetTop = $element.offset().top,
scrollTop = this.$_window.scrollTop(),
percentOfPage = 100;
// the percentOfPage can vary from -1 to 1
if ( this.isVisible ) {
//percentOfPage = currentDistanceToMiddleScreen / maxDistanceToMiddleScreen;
percentOfPage = ( offsetTop - scrollTop ) / winHeight;
} else if ( this.isBefore ) {
percentOfPage = 1;
} else if ( this.isAfter ) {
percentOfPage = - 1;
}
var maxBGYMove = this.options.parallaxForce > 0 ? winHeight * ( 100 - this.options.parallaxForce ) / 100 : winHeight,
bgPositionY = Math.round( percentOfPage * maxBGYMove );
this.element.css({
'background-position-y' : [
'calc(50% ',
bgPositionY > 0 ? '+ ' : '- ',
Math.abs( bgPositionY ) + 'px)'
].join('')
});
};
// When does the image enter the viewport ?
Plugin.prototype.checkIfIsVisibleAndCacheProperties = function( _evt ) {
var $element = this.element;
// bail if the level is display:none;
// because $.offset() won't work
// see because of https://github.com/presscustomizr/nimble-builder/issues/363
if ( ! $element.is(':visible') )
return false;
var scrollTop = this.$_window.scrollTop(),
wb = scrollTop + this.$_window.height(),
offsetTop = $element.offset().top,
ib = offsetTop + $element.outerHeight();
// Cache now
this.isVisible = ib >= scrollTop && offsetTop <= wb;
this.isBefore = offsetTop > wb ;//the element is before the scroll point
this.isAfter = ib < scrollTop;// the element is after the scroll point
return this.isVisible;
};
// a throttle is implemented with window.requestAnimationFrame
Plugin.prototype.maybeParallaxMe = function(evt) {
var self = this;
if ( ! this.checkIfIsVisibleAndCacheProperties() )
return;
if ( ! this.doingAnimation ) {
this.doingAnimation = true;
window.requestAnimationFrame(function() {
self.setTopPositionAndBackgroundSize();
self.doingAnimation = false;
});
}
};
// prevents against multiple instantiations
$.fn[pluginName] = function ( options ) {
return this.each(function () {
if (!$.data(this, 'plugin_' + pluginName)) {
$.data(this, 'plugin_' + pluginName,
new Plugin( this, options ));
}
});
};
})( jQuery, window );
};/////////////// callbackFunc
// on 'nb-app-ready', jQuery is loaded
nb_.listenTo('nb-app-ready', function(){
callbackFunc();
nb_.emit('nb-parallax-parsed');
});
}(window, document));
@@ -0,0 +1 @@
window,document,nb_.listenTo("nb-app-ready",function(){!function(e,r){var o="parallaxBg",n={parallaxForce:40,oncustom:[],matchMedia:"only screen and (max-width: 800px)"};function t(i,t){this.element=e(i),this.options=e.extend({},n,t,this.parseElementDataOptions()),this._defaults=n,this._name=o,this.init()}t.prototype.parseElementDataOptions=function(){return this.element.data()},t.prototype.init=function(){var t=this;this.$_window=nb_.cachedElements.$window,this.doingAnimation=!1,this.isVisible=!1,this.isBefore=!1,this.isAfter=!0,("number"!=typeof t.options.parallaxForce||t.options.parallaxForce<0)&&(sekFrontLocalized.isDevMode&&console.log("parallaxBg => the provided parallaxForce is invalid => "+t.options.parallaxForce),t.options.parallaxForce=this._defaults.parallaxForce),100<t.options.parallaxForce&&(t.options.parallaxForce=100),this.$_window.on("scroll",function(i){t.maybeParallaxMe(i)}),this.$_window.on("resize",nb_.debounce(function(i){t.maybeParallaxMe(i)},100)),this.checkIfIsVisibleAndCacheProperties(),this.setTopPositionAndBackgroundSize()},t.prototype.setTopPositionAndBackgroundSize=function(){if(nb_.isFunction(r.matchMedia)&&matchMedia(this.options.matchMedia).matches)this.element.css({"background-position-y":"","background-attachment":""});else{var i=this.element,t=(i.outerHeight(),this.$_window.height()),e=i.offset().top,o=this.$_window.scrollTop(),n=100;this.isVisible?n=(e-o)/t:this.isBefore?n=1:this.isAfter&&(n=-1);var s=0<this.options.parallaxForce?t*(100-this.options.parallaxForce)/100:t,a=Math.round(n*s);this.element.css({"background-position-y":["calc(50% ",0<a?"+ ":"- ",Math.abs(a)+"px)"].join("")})}},t.prototype.checkIfIsVisibleAndCacheProperties=function(i){var t=this.element;if(!t.is(":visible"))return!1;var e=this.$_window.scrollTop(),o=e+this.$_window.height(),n=t.offset().top,s=n+t.outerHeight();return this.isVisible=e<=s&&n<=o,this.isBefore=o<n,this.isAfter=s<e,this.isVisible},t.prototype.maybeParallaxMe=function(i){var t=this;this.checkIfIsVisibleAndCacheProperties()&&(this.doingAnimation||(this.doingAnimation=!0,r.requestAnimationFrame(function(){t.setTopPositionAndBackgroundSize(),t.doingAnimation=!1})))},e.fn[o]=function(i){return this.each(function(){e.data(this,"plugin_"+o)||e.data(this,"plugin_"+o,new t(this,i))})}}(jQuery,window),nb_.emit("nb-parallax-parsed")});
@@ -0,0 +1,712 @@
// global sekFrontLocalized, nimbleListenTo
/* ------------------------------------------------------------------------- *
* MENU
/* ------------------------------------------------------------------------- */
(function(w, d){
var callbackFunc = function() {
jQuery( function($){
// Set the attribute data-sek-is-mobile-vertical-menu on page load and dynamically set on resize
var _setVerticalMobileBooleanAttribute = function() {
// Set vertical mobile boolean attribute
var breakpoint = 768, deviceWidth;
$('nav.sek-nav-wrap').each( function() {
breakpoint = $(this).data('sek-mobile-menu-breakpoint') || breakpoint;
// cast to integer
breakpoint = parseInt( breakpoint, 10 );
deviceWidth = window.innerWidth > 0 ? window.innerWidth : screen.width;
// console.log('window.innerWidth ??', window.innerWidth, window.innerWidth > 0 );
// console.log('SOO ? breakpoint | device width', breakpoint + ' | ' + deviceWidth );
// add a data attribute so we can target the mobile menu with dynamic css rules
// @needed when coding : https://github.com/presscustomizr/nimble-builder/issues/491
$(this).attr('data-sek-is-mobile-vertical-menu', deviceWidth < breakpoint ? 'yes' : 'no');
});
};
_setVerticalMobileBooleanAttribute();
nb_.cachedElements.$window.on('resize', nb_.debounce( _setVerticalMobileBooleanAttribute, 100) );
// HELPER TO DETERMINE IF A NODE BELONGS TO A MOBILE MENU
// this is the element
var nodeBelongsToAMobileMenu = function() {
if ( this.length && this.length > 0 ) {
// Note that [data-sek-is-mobile-vertical-menu] value is set on page load and dynamically on window resize
return "yes" === this.closest('[data-sek-is-mobile-vertical-menu]').attr('data-sek-is-mobile-vertical-menu');
}
return false;
};
//DESKTOP DROPDOWN
var desktopDropdownOnHover = function() {
//dropdown
var DATA_KEY = 'sek.sekDropdown',
EVENT_KEY = '.' + DATA_KEY,
Event = {
PLACE_ME : 'placeme'+ EVENT_KEY,
PLACE_ALL : 'placeall' + EVENT_KEY,
SHOWN : 'shown' + EVENT_KEY,
SHOW : 'show' + EVENT_KEY,
HIDDEN : 'hidden' + EVENT_KEY,
HIDE : 'hide' + EVENT_KEY,
CLICK : 'click' + EVENT_KEY,
TAP : 'tap' + EVENT_KEY,
},
ClassName = {
DROPDOWN : 'sek-dropdown-menu',
DROPDOWN_SUBMENU : 'sek-dropdown-submenu',
SHOW : 'show',
PARENTS : 'menu-item-has-children',
ALLOW_POINTER_ON_SCROLL : 'allow-pointer-events-on-scroll'
},
Selector = {
DATA_SHOWN_TOGGLE_LINK : '.' +ClassName.SHOW+ '> a',
HOVER_MENU : '.sek-nav-wrap',
HOVER_PARENT : '.sek-nav-wrap .menu-item-has-children',
PARENTS : '.sek-nav-wrap .menu-item-has-children',
SNAKE_PARENTS : '.sek-nav-wrap .menu-item-has-children',
CHILD_DROPDOWN : 'ul.sek-dropdown-menu'
};
// unify all the dropdowns classes whether the menu is a proper menu or the all pages fall-back
$( '.sek-nav .children, .sek-nav .sub-menu' ).addClass( ClassName.DROPDOWN );
$( '.sek-nav-wrap .page_item_has_children' ).addClass( ClassName.PARENTS );
$( '.sek-nav' + ' .' + ClassName.DROPDOWN + ' .' + ClassName.PARENTS ).addClass( ClassName.DROPDOWN_SUBMENU );
//Handle dropdown on hover via js
var dropdownMenuOnHover = function() {
var _dropdown_selector = Selector.HOVER_PARENT;
bindEvents();
function _addOpenClass( evt ) {
var $_el = $(this),
$_child_dropdown = $_el.find( Selector.CHILD_DROPDOWN ).first();
// Jan 2021 : start of a fix for https://github.com/presscustomizr/nimble-builder/issues/772
if ( nb_.cachedElements.$body.hasClass('is-touch-device') ) {
// When navigating the regular menu ( horizontal ) on a mobile touch device, typically a tablet in landscape orientation
// we want to prevent opening the link of a parent menu if the children are not displayed yet
if ( "true" != $_child_dropdown.attr('aria-expanded') && !nodeBelongsToAMobileMenu.call($_child_dropdown) ) {
evt.preventDefault();
}
}
//a little delay to balance the one added in removing the open class
var _debounced_addOpenClass = nb_.debounce( function() {
//do nothing if menu is mobile
if( 'static' == $_el.find( '.'+ClassName.DROPDOWN ).css( 'position' ) ) {
return false;
}
var $_child_dropdown = $_el.find( Selector.CHILD_DROPDOWN ).first();
if ( !$_el.hasClass(ClassName.SHOW) ) {
nb_.cachedElements.$body.addClass( ClassName.ALLOW_POINTER_ON_SCROLL );
$_el.trigger( Event.SHOW )
.addClass(ClassName.SHOW)
.trigger( Event.SHOWN);
if ( $_child_dropdown.length > 0 ) {
$_child_dropdown[0].setAttribute('aria-expanded', 'true');
}
}
}, 30);
_debounced_addOpenClass();
}
function _removeOpenClass() {
var $_el = $(this),
$_child_dropdown = $_el.find( Selector.CHILD_DROPDOWN ).first();
//a little delay before closing to avoid closing a parent before accessing the child
var _debounced_removeOpenClass = nb_.debounce( function() {
if ( $_el.find("ul li:hover").length < 1 && ! $_el.closest('ul').find('li:hover').is( $_el ) ) {
// april 2020 => some actions should be only done when not on a "touch" device
// otherwise we have a bug on submenu expansion
// see : https://github.com/presscustomizr/customizr/issues/1824
//if ( !nb_.cachedElements.$body.hasClass('is-touch-device') ) {
// $_el.trigger( Event.HIDE )
// .removeClass( ClassName.SHOW)
// .trigger( Event.HIDDEN );
//}
$_el.trigger( Event.HIDE )
.removeClass( ClassName.SHOW)
.trigger( Event.HIDDEN );
//make sure pointer events on scroll are still allowed if there's at least one submenu opened
if ( $_el.closest( Selector.HOVER_MENU ).find( '.' + ClassName.SHOW ).length < 1 ) {
nb_.cachedElements.$body.removeClass( ClassName.ALLOW_POINTER_ON_SCROLL );
}
if ( $_child_dropdown.length > 0 ) {
$_child_dropdown[0].setAttribute('aria-expanded', 'false');
}
}
}, 30 );
_debounced_removeOpenClass();
}
function bindEvents() {
// april 2020 : is-touch-device class is added on body on the first touch
// This way, we can prevent the problem reported on https://github.com/presscustomizr/customizr/issues/1824
// ( two touches needed to reveal submenus on touch devices )
nb_.cachedElements.$body.on('touchstart', function() {
if ( !$(this).hasClass('is-touch-device') ) {
$(this).addClass('is-touch-device');
}
});
//BIND
nb_.cachedElements.$body
.on( 'mouseenter', _dropdown_selector, function(evt) {
if ( !nodeBelongsToAMobileMenu.call($(this)) ) {
_addOpenClass.call($(this), evt );
}
})
.on( 'mouseleave', _dropdown_selector , function(evt) {
if ( !nodeBelongsToAMobileMenu.call($(this)) ) {
_removeOpenClass.call($(this), evt );
}
})
.on( 'click', _dropdown_selector, function(evt) {
if ( !nodeBelongsToAMobileMenu.call($(this)) ) {
_addOpenClass.call($(this), evt );
}
});
}
},
// DESKTOP SNAKE
dropdownPlacement = function() {
var isRTL = 'rtl' === $('html').attr('dir'),
doingAnimation = false;
nb_.cachedElements.$window
//on resize trigger Event.PLACE on active dropdowns
.on( 'resize', function() {
if ( ! doingAnimation ) {
doingAnimation = true;
window.requestAnimationFrame(function() {
//trigger a placement on the open dropdowns
$( Selector.SNAKE_PARENTS+'.'+ClassName.SHOW)
.trigger(Event.PLACE_ME);
doingAnimation = false;
});
}
});
$( document )
.on( Event.PLACE_ALL, function() {
//trigger a placement on all
$( Selector.SNAKE_PARENTS )
.trigger(Event.PLACE_ME);
})
//snake bound on menu-item shown and place
.on( Event.SHOWN+' '+Event.PLACE_ME, Selector.SNAKE_PARENTS, function(evt) {
evt.stopPropagation();
_do_snake( $(this), evt );
});
//snake
//$_el is the menu item with children whose submenu will be 'snaked'
function _do_snake( $_el, evt ) {
if ( !( evt && evt.namespace && DATA_KEY === evt.namespace ) ) {
return;
}
var $_this = $_el,
$_dropdown = $_this.children( '.'+ClassName.DROPDOWN );
if ( !$_dropdown.length ) {
return;
}
//stage
/*
* we display the dropdown so that jQuery is able to retrieve exact size and positioning
* we also hide whatever overflows the menu item with children whose submenu will be 'snaked'
* this to avoid some glitches that would made it lose the focus:
* During RTL testing when a menu item with children reached the left edge of the window
* it happened that while the submenu was showing (because of the show class added, so not depending on the snake)
* this submenu (ul) stole the focus and then released it in a very short time making the mouseleave callback
* defined in dropdownMenuOnHover react, hence closing the whole submenu tree.
* This might be a false positive, as we don't really test RTL with RTL browsers (only the html direction changes),
* but since the 'cure' has no side effects, let's be pedantic!
*/
$_el.css( 'overflow', 'hidden' );
$_dropdown.css( {
'zIndex' : '-100',
'display' : 'block'
});
_maybe_move( $_dropdown, $_el );
//unstage
$_dropdown.css({
'zIndex' : '',
'display' : ''
});
$_el.css( 'overflow', '' );
}//_so_snake
function _maybe_move( $_dropdown, $_el ) {
var Direction = isRTL ? {
//when in RTL we open the submenu by default on the left side
_DEFAULT : 'left',
_OPPOSITE : 'right'
} : {
//when in LTR we open the submenu by default on the right side
_DEFAULT : 'right',
_OPPOSITE : 'left'
},
ClassName = {
OPEN_PREFIX : 'open-',
DD_SUBMENU : 'sek-dropdown-submenu',
CARET_TITLE_FLIP : 'sek-menu-link__row-reverse',
//CARET : 'caret__dropdown-toggler',
DROPDOWN : 'sek-dropdown-menu'
},
_caret_title_maybe_flip = function( $_el, _direction, _old_direction ) {
$.each( $_el, function() {
var $_el = $(this),
$_a = $_el.find( 'a' ).first();
if ( 1 == $_a.length ) {
$_a.toggleClass( ClassName.CARET_TITLE_FLIP, _direction == Direction._OPPOSITE );
}
});
},
_setOpenDirection = function( _direction ) {
//retrieve the old direction => used to remove the old direction class
var _old_direction = _direction == Direction._OPPOSITE ? Direction._DEFAULT : Direction._OPPOSITE;
//tell the dropdown to open on the direction _direction (hence remove the old direction class)
$_dropdown.removeClass( ClassName.OPEN_PREFIX + _old_direction ).addClass( ClassName.OPEN_PREFIX + _direction );
if ( $_el.hasClass( ClassName.DD_SUBMENU ) ) {
_caret_title_maybe_flip( $_el, _direction, _old_direction );
//make the first level submenus caret inherit this
_caret_title_maybe_flip( $_dropdown.children( '.' + ClassName.DD_SUBMENU ), _direction, _old_direction );
}
};
//snake inheritance
if ( $_dropdown.parent().closest( '.'+ClassName.DROPDOWN ).hasClass( ClassName.OPEN_PREFIX + Direction._OPPOSITE ) ) {
//open on the opposite direction
_setOpenDirection( Direction._OPPOSITE );
} else {
//open on the default direction
_setOpenDirection( Direction._DEFAULT );
}
//let's compute on which side open the dropdown
if ( $_dropdown.offset().left + $_dropdown.width() > nb_.cachedElements.$window.width() ) {
//open on the left
_setOpenDirection( 'left' );
} else if ( $_dropdown.offset().left < 0 ) {
//open on the right
_setOpenDirection( 'right' );
}
}//_maybe_move
};//dropdownPlacement
//FireAll
dropdownMenuOnHover();
dropdownPlacement();
};//desktopDropdownOnHover
// FIRE DESKTOP MENU METHODS
desktopDropdownOnHover();
// MOBILE MENU HAMBURGER BUTTON
// handle the mobile hamburger hover effect
$( document )
.on( 'mouseenter', '.sek-nav-toggler', function(){ $(this).addClass( 'hovering' ); } )
.on( 'mouseleave', '.sek-nav-toggler', function(){ $(this).removeClass( 'hovering' ); } )
.on( 'show.sek.sekCollapse hide.sek.sekCollapse', '.sek-nav-collapse', function() {
$('[data-target="#'+$(this).attr('id')+'"]').removeClass( 'hovering' );
nb_.cachedElements.$window.trigger('scroll');
});
// MOBILE MENU VISIBILITY
toggleMobileMenuVisibility = function() {
var EVENT_KEY = ".nbMobMenuBtn",
TRANSITION_DURATION = 400,
Event = {
SHOW: "show" + EVENT_KEY,
SHOWN: "shown" + EVENT_KEY,
HIDE: "hide" + EVENT_KEY,
HIDDEN: "hidden" + EVENT_KEY,
CLICK_EVENT: "click" + EVENT_KEY
},
ClassName = {
COLLAPSING: 'sek-collapsing',
COLLAPSED: 'sek-collapsed'
},
Selector = {
MM_TOGGLER: '.sek-nav-toggler'
};
// attach click event
nb_.cachedElements.$body.on( Event.CLICK_EVENT, Selector.MM_TOGGLER, function (event, params) {
// preventDefault only for <a> elements (which change the URL) not inside the collapsible element
if (event.currentTarget.tagName === 'A') {
event.preventDefault();
}
var $toggler = $(this),
//get the data toggle
_mob_menu_selector = $toggler.data('target');
$(_mob_menu_selector).each( function () {
var $mobMenuWrapper = $(this),
mobMenuIsExpanded = "expanded" === $mobMenuWrapper.attr('data-sek-mm-state'),
$maybeHeaderParentEl = $mobMenuWrapper.closest('#nimble-header');
// console.log('"$mobMenuWrapper ?', $mobMenuWrapper );
// console.log('mobMenuIsExpanded ?', mobMenuIsExpanded );
$mobMenuWrapper.stop()[ mobMenuIsExpanded ? 'slideUp' : 'slideDown' ]({
duration: (params && params.close_fast) ? 0 : TRANSITION_DURATION,
start : function() {
$mobMenuWrapper.addClass(ClassName.COLLAPSING).trigger( mobMenuIsExpanded ? Event.HIDE : Event.SHOW );
if ( mobMenuIsExpanded ) {
$toggler.addClass( ClassName.COLLAPSED ).attr( 'aria-expanded', 'false' );
if ( $maybeHeaderParentEl.length > 0 ) {
$maybeHeaderParentEl.removeClass('sek-header-mobile-menu-expanded');
}
} else {
$toggler.removeClass( ClassName.COLLAPSED ).attr( 'aria-expanded', 'true' );
$mobMenuWrapper.attr('data-sek-mm-state', 'expanded');
if ( $maybeHeaderParentEl.length > 0 ) {
$maybeHeaderParentEl.addClass('sek-header-mobile-menu-expanded');
}
}
},
complete: function() {
// console.log('SOO DATA ?', mobMenuIsExpanded, $mobMenuWrapper.attr('data-sek-mm-state') );
if ( mobMenuIsExpanded ) {
$mobMenuWrapper.removeClass(ClassName.COLLAPSING).trigger(Event.HIDDEN);
$mobMenuWrapper.attr('data-sek-mm-state', 'collapsed');
} else {
$mobMenuWrapper.removeClass(ClassName.COLLAPSING).trigger(Event.SHOWN);
}
//remove all the inline style added by the slideUp/Down methods
$mobMenuWrapper.css({
'display' : '',
'paddingTop' : '',
'marginTop' : '',
'paddingBottom' : '',
'marginBottom' : '',
'height' : ''
});
}
});//end slideUp/slideDown
});//end each
});//end attach click event
// close mobile menu on resize event
nb_.cachedElements.$window.on('resize', nb_.debounce( function() {
$(Selector.MM_TOGGLER).each(function() {
var associated_mob_menu_selector = $(this).data('target');
if ( 'true' == $(this).attr( 'aria-expanded' ) ) {
if ( $(associated_mob_menu_selector).length && !nodeBelongsToAMobileMenu.call( $(associated_mob_menu_selector) ) ) {
$(this).trigger(Event.CLICK_EVENT, {close_fast:true});
}
}
});
}, 100) );
};//toggleMobileMenuVisibility()
toggleMobileMenuVisibility();
////////////////////////////////////////////////////////////////////////
//////////// COLLAPSIBLE MENU ( janv 2021 )
//hueman theme inspired
var maybeApplyCollapsibleMenu = function() {
var $mobMenuWrapper = this;
if ( 'true' == $mobMenuWrapper.data('nb-mm-menu-is-instantiated') )
return;
// Flag so we don't instantiate twice ( typically when previewing)
$mobMenuWrapper.data('nb-mm-menu-is-instantiated', 'true');
//specific class added to this mobile menu which tells its submenus have to be expanded on click (purpose: style)
$mobMenuWrapper.addClass( 'nb-collapsible-mobile-menu' );
var EVENT_KEY = '.nb.submenu',
Event = {
SHOW : 'show' + EVENT_KEY,
HIDE : 'hide' + EVENT_KEY,
CLICK : 'mousedown' + EVENT_KEY,
FOCUSIN : 'focusin' + EVENT_KEY,
FOCUSOUT : 'focusout' + EVENT_KEY
},
Classname = {
DD_TOGGLE_ON_CLICK : 'nb-collapsible-mobile-menu',
SHOWN : 'expanded',
DD_TOGGLE : 'nb-dd-mm-toggle',
DD_TOGGLE_WRAPPER : 'nb-dd-mm-toggle-wrapper',
SCREEN_READER : 'screen-reader-text',
},
Selector = {
DD_TOGGLE_PARENT : '.menu-item-has-children, .page_item_has_children',
CURRENT_ITEM_ANCESTOR : '.current-menu-ancestor',
SUBMENU : '.sub-menu'
},
// Add dropdown toggle that displays child menu items.
dropdownToggle = $( '<button />', { 'class': Classname.DD_TOGGLE, 'aria-expanded': false })
.append(' <i class="nb-arrow-for-mobile-menu"></i>' )
.append( $( '<span />', { 'class': Classname.SCREEN_READER, text: 'Expand' } ) ),
dropdownToggleWrapper = $( '<span />', { 'class': Classname.DD_TOGGLE_WRAPPER })
.append( dropdownToggle );
//add dropdown toggler button to each submenu parent item (li)
$mobMenuWrapper.find( Selector.DD_TOGGLE_PARENT ).children('a').after( dropdownToggleWrapper );
// Set the active submenu dropdown toggle button initial state.
// $mobMenuWrapper.find( Selector.CURRENT_ITEM_ANCESTOR +'>.'+ Classname.DD_TOGGLE_WRAPPER +' .'+ Classname.DD_TOGGLE )
// .addClass( Classname.SHOWN )
// .attr( 'aria-expanded', 'true' )
// .find( '.'+Classname.SCREEN_READER )
// .text( 'Collapse' );
// Set the active submenu initial state.
// $mobMenuWrapper.find( Selector.CURRENT_ITEM_ANCESTOR +'>'+ Selector.SUBMENU ).addClass( Classname.SHOWN );
// $mobMenuWrapper.find( Selector.CURRENT_ITEM_ANCESTOR ).addClass( Classname.SHOWN );
$( $mobMenuWrapper )
//when clicking on a menu item whose href is just a "#", let's emulate a click on the caret dropdown
.on( Event.CLICK, 'a[href="#"]', function(evt) {
if ( !nodeBelongsToAMobileMenu.call( $mobMenuWrapper ) )
return;
evt.preventDefault();
evt.stopPropagation();
$(this).next('.'+Classname.DD_TOGGLE_WRAPPER).find('.'+Classname.DD_TOGGLE).trigger( Event.CLICK );
})
//when clicking on the toggle button
//1) trigger the appropriate "internal" event: hide or show
//2) maybe collapse all other open submenus within this menu
.on( Event.CLICK, '.'+Classname.DD_TOGGLE, function( e ) {
e.preventDefault();
var $_this = $( this );
$_this.trigger( $_this.closest( Selector.DD_TOGGLE_PARENT ).hasClass( Classname.SHOWN ) ? Event.HIDE: Event.SHOW );
//close other submenus
_clearMenus( $_this );
})
//when the hide/show event is triggered
//1) toggle the toggle parent menu item (li) expanded class
//2) expand/collapse the submenu(ul)
//2.1) on expansion/collapse completed change aria attribute and screenreader text
//2.2) toggle the subemnu (ul.sub-menu) expanded class
//2.3) clear any inline CSS applied by the slideDown/slideUp jQuery functions : the visibility is completely handled via CSS (expanded class)
// we use the aforementioned method only for the animations
.on( Event.SHOW+' '+Event.HIDE, '.'+Classname.DD_TOGGLE, function( e ) {
var $_this = $( this );
$_this.closest( Selector.DD_TOGGLE_PARENT ).toggleClass( Classname.SHOWN );
$_this.closest('.'+Classname.DD_TOGGLE_WRAPPER).next( Selector.SUBMENU )
.stop()[Event.SHOW == e.type + '.' + e.namespace ? 'slideDown' : 'slideUp']( {
duration: 300,
complete: function() {
var _to_expand = 'false' === $_this.attr( 'aria-expanded' );
$submenu = $(this);
$_this.attr( 'aria-expanded', _to_expand )
.find( '.'+Classname.SCREEN_READER )
.text( _to_expand ? 'collapse' : 'expand' );
$submenu.toggleClass( Classname.SHOWN );
//resets remaining inline CSS rules
$submenu.css({
'display' : '',
'paddingTop' : '',
'marginTop' : '',
'paddingBottom' : '',
'marginBottom' : '',
'height' : ''
});
}
});
})
// Keyboard navigation ( August 2019 )
// https://github.com/presscustomizr/hueman/issues/819
//when focusin on a menu item whose href is just a "#", let's emulate a click on the caret dropdown
.on( Event.FOCUSIN, 'a[href="#"]', function(evt) {
if ( !nodeBelongsToAMobileMenu.call( $mobMenuWrapper ) )
return;
evt.preventDefault();
evt.stopPropagation();
$(this).next('.'+Classname.DD_TOGGLE_WRAPPER).find('.'+Classname.DD_TOGGLE).trigger( Event.FOCUSIN );
})
.on( Event.FOCUSOUT, 'a[href="#"]', function(evt) {
if ( !nodeBelongsToAMobileMenu.call( $mobMenuWrapper ) )
return;
evt.preventDefault();
evt.stopPropagation();
nb_.delay( function() {
$(this).next('.'+Classname.DD_TOGGLE_WRAPPER).find('.'+Classname.DD_TOGGLE).trigger( Event.FOCUSOUT );
}, 250 );
})
//when focusin on the toggle button
//1) trigger the appropriate "internal" event: hide or show
//2) maybe collapse all other open submenus within this menu
.on( Event.FOCUSIN, '.'+Classname.DD_TOGGLE, function( e ) {
e.preventDefault();
var $_this = $( this );
$_this.trigger( Event.SHOW );
//close other submenus
//_clearMenus( mobMenu, $_this );
})
.on( Event.FOCUSIN, function( evt ) {
evt.preventDefault();
if ( $(evt.target).length > 0 ) {
$(evt.target).addClass( 'nb-mm-focused');
}
})
.on( Event.FOCUSOUT,function( evt ) {
evt.preventDefault();
var $_this = $( this );
nb_.delay( function() {
if ( $(evt.target).length > 0 ) {
$(evt.target).removeClass( 'nb-mm-focused');
}
// if ( $mobMenuWrapper.find('.nb-mm-focused').length < 1 ) {
// console.log('TOP DO => TRIGGER MOBILE MENU COLLAPSE NOW');
// //mobMenu( 'collapsed');
// }
}, 200 );
});
//bs dropdown inspired
var _clearMenus = function( $_toggle ) {
var _parentsToNotClear = $.makeArray( $_toggle.parents( Selector.DD_TOGGLE_PARENT ) ),
_toggles = $.makeArray( $( '.'+Classname.DD_TOGGLE, $mobMenuWrapper ) );
for (var i = 0; i < _toggles.length; i++) {
var _parent = $(_toggles[i]).closest( Selector.DD_TOGGLE_PARENT )[0];
if (!$(_parent).hasClass( Classname.SHOWN ) || $.inArray(_parent, _parentsToNotClear ) > -1 ){
continue;
}
$(_toggles[i]).trigger( Event.HIDE );
}
};
};//maybeApplyCollapsibleMenu()
// Instanciate collabsible menu
$('.sek-nav-wrap').each( function() {
try { maybeApplyCollapsibleMenu.call($(this) ); } catch( er ) {
console.log('NB error => collapsible menu', er );
}
});
// When previewing, react to level refresh
// This can occur to any level. We listen to the bubbling event on 'body' tag
nb_.cachedElements.$body.on('sek-level-refreshed sek-modules-refreshed sek-columns-refreshed sek-section-added', function( evt ){
$('.sek-nav-wrap').each( function() {
try { maybeApplyCollapsibleMenu.call($(this) ); } catch( er ) {
console.log('NB error => collapsible menu', er );
}
});
});
// How to have a logo plus an hamburger in mobiles on the same line?
// => clone the menu module, and append it to the closest sektion-inner wrapper
// => this way it will occupy 100% of the width
// => and also the clone inherits the style of the module
// https://github.com/presscustomizr/nimble-builder/issues/368
var mayBeCloneMobileMenu = function() {
$( '[data-sek-module-type="czr_menu_module"]' ).find('[data-sek-expand-below="yes"]').each( function() {
// make sure we don't do the setup twice when customizing
if ( true === $(this).data('sek-setup-menu-mobile-expanded-below-done') )
return;
var $_mobile_menu_module = $(this).closest('[data-sek-module-type="czr_menu_module"]').clone(true),
//create a new id for the mobile menu nav collapse that will used by the button toggler too
_new_id = $( '.sek-nav-collapse', this ).attr('id') + '-mobile';
$_mobile_menu_module
/// place the mobile menu at the end of this sektion inner
.appendTo( $(this).closest( '.sek-sektion-inner' ) )
//wrap in a convenient div for styling and targeting
.wrap( '<div class="sek-col-base sek-mobile-menu-expanded-below" id="'+_new_id+'-wrapper"></div>');
// assign the new id to the mobile nav collapse
$( '.sek-nav-collapse', '#'+_new_id+'-wrapper' ).attr( 'id', _new_id );
// remove the duplicate button
$( '.sek-nav-toggler', '#'+_new_id+'-wrapper' ).detach();
// update the toggler button so that will now refer to the "cloned" mobile menu
$( '.sek-nav-toggler', this ).data( 'target', '#' + _new_id )
.attr( 'aria-controls', _new_id );
// flag setup done
$(this).data('sek-setup-menu-mobile-expanded-below-done', true );
});//$.each()
};
mayBeCloneMobileMenu();
// When previewing, react to level refresh
// This can occur to any level. We listen to the bubbling event on 'body' tag
nb_.cachedElements.$body.on('sek-level-refreshed sek-modules-refreshed sek-columns-refreshed sek-section-added', function( evt ){
// clean the previously duplicated menu if any
$('.sek-mobile-menu-expanded-below').remove();
mayBeCloneMobileMenu();
});
});//jQuery( function($){})
};/////////////// callbackFunc
// on 'nb-app-ready', jQuery is loaded
nb_.listenTo('nb-app-ready', callbackFunc );
}(window, document));
File diff suppressed because one or more lines are too long
@@ -0,0 +1,573 @@
// global sekFrontLocalized, nimbleListenTo
/* ------------------------------------------------------------------------- *
* SWIPER CAROUSEL implemented for the simple slider module czr_img_slider_module
* doc : https://swiperjs.com/api/
* dependency : $.fn.nimbleCenterImages()
/* ------------------------------------------------------------------------- */
(function(w, d){
var callbackFunc = function() {
jQuery( function($){
var mySwipers = [];
var triggerSimpleLoad = function( $_imgs ) {
if ( 0 === $_imgs.length )
return;
$_imgs.map( function( _ind, _img ) {
$(_img).load( function () {
$(_img).trigger('simple_load');
});//end load
if ( $(_img)[0] && $(_img)[0].complete )
$(_img).load();
} );//end map
};//end of fn
// Each swiper is instantiated with a unique id
// so that if we have several instance on the same page, they are totally independant.
// If we don't use a unique Id for swiper + navigation buttons, a click on a button, make all slider move synchronously.
var doSingleSwiperInstantiation = function() {
var $swiperWrapper = $(this), swiperClass = 'sek-swiper' + $swiperWrapper.data('sek-swiper-id');
var swiperParams = {
// slidesPerView: 3,
// spaceBetween: 30,
loop : true === $swiperWrapper.data('sek-loop') && true === $swiperWrapper.data('sek-is-multislide'),//Set to true to enable continuous loop mode
grabCursor : true === $swiperWrapper.data('sek-is-multislide'),
on : {
init : function() {
// remove the .sek-swiper-loading class from the wrapper => remove the display:none rule
$swiperWrapper.removeClass('sek-swiper-loading');
// remove the css loader
$swiperWrapper.parent().find('.sek-css-loader').remove();
// lazy load the first slider image with Nimble if not done already
// the other images will be lazy loaded by swiper if the option is activated
// if ( sekFrontLocalized.lazyload_enabled && $.fn.nimbleLazyLoad ) {
// }
$swiperWrapper.trigger('nb-trigger-lazyload');
// center images with Nimble wizard when needed
if ( 'nimble-wizard' === $swiperWrapper.data('sek-image-layout') ) {
$swiperWrapper.find('.sek-carousel-img').each( function() {
var $_imgsToSimpleLoad = $(this).nimbleCenterImages({
enableCentering : 1,
zeroTopAdjust: 0,
setOpacityWhenCentered : false,//will set the opacity to 1
oncustom : [ 'simple_load', 'smartload', 'sek-nimble-refreshed', 'recenter']
})
//images with src which starts with "data" are our smartload placeholders
//we don't want to trigger the simple_load on them
//the centering, will be done on the smartload event (see onCustom above)
.find( 'img:not([src^="data"])' );
//trigger the simple load
nb_.delay( function() {
triggerSimpleLoad( $_imgsToSimpleLoad );
}, 50 );
});//each()
}
},// init
// make sure slides are always lazyloaded
slideChange : function(params) {
// when lazy load is active, we want to lazy load the first image of the slider if offscreen
// img to be lazy loaded looks like data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
$swiperWrapper.trigger('nb-trigger-lazyload');
if ( $swiperWrapper.find('[src*="data:image/gif;"]').length > 0 ) {
// Make sure we load clean lazy loaded slides on change
// for https://github.com/presscustomizr/nimble-builder/issues/677
$swiperWrapper.find('[src*="data:image/gif;"]').each( function() {
var $img = $(this);
if ( $img.attr('data-sek-img-sizes') ) {
$img.attr('sizes', $img.attr('data-sek-img-sizes') );
$img.removeAttr('data-sek-img-sizes');
}
if ( $img.attr('data-src') ) {
$img.attr('src', $img.attr('data-src') );
$img.removeAttr('data-src');
}
if ( $img.attr('data-sek-src') ) {
$img.attr('src', $img.attr('data-sek-src') );
$img.removeAttr('data-sek-src');
}
if ( $img.attr('data-srcset') ) {
$img.attr('srcset', $img.attr('data-srcset') );
$img.removeAttr('data-srcset');
}
});
}
}
}//on
};
// AUTOPLAY
if ( true === $swiperWrapper.data('sek-autoplay') ) {
$.extend( swiperParams, {
autoplay : {
delay : $swiperWrapper.data('sek-autoplay-delay'),
disableOnInteraction : $swiperWrapper.data('sek-pause-on-hover')
}
});
} else {
$.extend( swiperParams, {
autoplay : {
delay : 999999999//<= the autoplay:false doesn't seem to work...
}
});
}
// NAVIGATION ARROWS && PAGINATION DOTS
if ( true === $swiperWrapper.data('sek-is-multislide') ) {
var navType = $swiperWrapper.data('sek-navtype');
if ( 'arrows_dots' === navType || 'arrows' === navType ) {
$.extend( swiperParams, {
navigation: {
nextEl: '.sek-swiper-next' + $swiperWrapper.data('sek-swiper-id'),
prevEl: '.sek-swiper-prev' + $swiperWrapper.data('sek-swiper-id')
}
});
}
if ( 'arrows_dots' === navType || 'dots' === navType ) {
$.extend( swiperParams, {
pagination: {
el: '.swiper-pagination' + $swiperWrapper.data('sek-swiper-id'),
clickable: true,
}
});
}
}
// LAZYLOAD @see https://swiperjs.com/api/#lazy
if ( true === $swiperWrapper.data('sek-lazyload') ) {
$.extend( swiperParams, {
// Disable preloading of all images
preloadImages: false,
lazy : {
// By default, Swiper will load lazy images after transition to this slide, so you may enable this parameter if you need it to start loading of new image in the beginning of transition
loadOnTransitionStart : true
}
});
}
// Prepare Pro slider effects
var _effect = '',
_duration = 300;//default Swiper value
if ( $swiperWrapper && $swiperWrapper.length > 0 ) {
_effect = $swiperWrapper.data('sek-slider-effect');
_duration = parseInt( $swiperWrapper.data('sek-effect-duration'), 10 );
}
if ( _duration > 0 ) {
$.extend( swiperParams, {
speed : _duration
});
}
if ( nb_.isString( _effect) && 0 !== _effect.length ) {
$.extend( swiperParams, {
effect: _effect
});
// See doc here : https://swiperjs.com/swiper-api#fade-effect
switch (_effect) {
case 'fade':
swiperParams[_effect + 'Effect'] = {
crossFade: true
};
break;
case 'coverflow':
swiperParams[_effect + 'Effect'] = {
rotate: 30,
slideShadows: false
};
break;
case 'flip':
case 'cube':
swiperParams[_effect + 'Effect'] = {
slideShadows: false
};
break;
case 'cards':
swiperParams[_effect + 'Effect'] = {};
break;
}
}
mySwipers.push( new Swiper(
'.' + swiperClass,//$(this)[0],
swiperParams
));
// On Swiper Lazy Loading
// https://swiperjs.com/api/#lazy
$.each( mySwipers, function( ind, _swiperInstance ){
_swiperInstance.on( 'lazyImageReady', function( slideEl, imageEl ) {
$(imageEl).trigger('recenter');
});
_swiperInstance.on( 'lazyImageLoad', function( slideEl, imageEl ) {
// clean the extra attribute added when preprocessing for lazy loading
var $img = $(imageEl);
if ( $img.attr('data-sek-img-sizes') ) {
$img.attr('sizes', $img.attr('data-sek-img-sizes') );
$img.removeAttr('data-sek-img-sizes');
}
// add 'recenter' events to fix https://github.com/presscustomizr/nimble-builder/issues/855
nb_.delay( function() {$img.trigger('recenter');}, 200 );
nb_.delay( function() {$img.trigger('recenter');}, 800 );
});
});
};
var doAllSwiperInstanciation = function() {
$('.sektion-wrapper').find('[data-sek-swiper-id]').each( function() {
doSingleSwiperInstantiation.call($(this));
});
};
// On custom events
nb_.cachedElements.$body.on( 'sek-columns-refreshed sek-modules-refreshed sek-section-added sek-level-refreshed', '[data-sek-level="location"]',
function(evt) {
if ( 0 !== mySwipers.length ) {
$.each( mySwipers, function( ind, _swiperInstance ){
_swiperInstance.destroy();
});
}
mySwipers = [];
doAllSwiperInstanciation();
$(this).find('.swiper img').each( function() {
$(this).trigger('sek-nimble-refreshed');
});
}
);
// When the stylesheet is refreshed, update the centering with a custom event
// this is needed when setting the custom height of the slider wrapper
nb_.cachedElements.$body.on( 'sek-stylesheet-refreshed', '[data-sek-module-type="czr_img_slider_module"]',
function() {
$(this).find('.swiper img').each( function() {
$(this).trigger('sek-nimble-refreshed');
});
}
);
// on load
$('.sektion-wrapper').find('.swiper').each( function() {
doAllSwiperInstanciation();
});
// Action on click
// $( 'body').on( 'click', '[data-sek-module-type="czr_img_slider_module"]', function(evt ) {
// // $(this).find('[data-sek-swiper-id]').each( function() {
// // $(this).trigger('sek-nimble-refreshed');
// // });
// }
// );
// Behaviour on mouse hover
// @seehttps://stackoverflow.com/questions/53028089/swiper-autoplay-stop-the-swiper-when-you-move-the-mouse-cursor-and-start-playba
$('.swiper-slide').on('mouseover mouseout', function( evt ) {
var swiperInstance = $(this).closest('.swiper')[0].swiper;
if ( ! nb_.isUndefined( swiperInstance ) && true === swiperInstance.params.autoplay.disableOnInteraction ) {
switch( evt.type ) {
case 'mouseover' :
swiperInstance.autoplay.stop();
break;
case 'mouseout' :
swiperInstance.autoplay.start();
break;
}
}
});
// When customizing, focus on the currently expanded / edited item
// @see CZRItemConstructor in api.czrModuleMap.czr_img_slider_collection_child
if ( window.wp && ! nb_.isUndefined( wp.customize ) ) {
wp.customize.preview.bind('sek-item-focus', function( params ) {
var $itemEl = $('[data-sek-item-id="' + params.item_id +'"]', '.swiper').first();
if ( 1 > $itemEl.length )
return;
var $swiperContainer = $itemEl.closest('.swiper');
if ( 1 > $swiperContainer.length )
return;
var activeSwiperInstance = $itemEl.closest('.swiper')[0].swiper;
if ( nb_.isUndefined( activeSwiperInstance ) )
return;
// we can't rely on internal indexing system of swipe, because it uses duplicate item when infinite looping is enabled
// jQuery is our friend
var slideIndex = $( '.swiper-slide', $swiperContainer ).index( $itemEl );
//http://idangero.us/swiper/api/#methods
//mySwiper.slideTo(index, speed, runCallbacks);
activeSwiperInstance.slideTo( slideIndex, 100 );
});
// Trigger a window resize when control send a 'sek-preview-device-changed'
// wp.customize.preview.bind('sek-preview-device-changed', nb_.debounce( function( params ) {
// nb_.cachedElements.$window.trigger('resize');
// }, 1000 ));
}
});
/* ===================================================
* jquerynimbleCenterImages.js v1.0.0
* ( inspired by Customizr theme jQuery plugin )
* ===================================================
* (c) 2019 Nicolas Guillaume, Nice, France
* CenterImages plugin may be freely distributed under the terms of the GNU GPL v2.0 or later license.
*
* License URI: http://www.gnu.org/licenses/gpl-2.0.html
*
* Center images in a specified container
*
* =================================================== */
(function ( $, window ) {
//defaults
var pluginName = 'nimbleCenterImages',
defaults = {
enableCentering : true,
onresize : true,
onInit : true,//<= shall we smartload on init or wait for a custom event, typically smartload ?
oncustom : [],//list of event here
$containerToListen : null,//<= we might want to listen to custom event trigger to a parent container.Should be a jQuery obj
imgSel : 'img',
defaultCSSVal : { width : 'auto' , height : 'auto' },
leftAdjust : 0,
zeroLeftAdjust : 0,
topAdjust : 0,
zeroTopAdjust : -2,//<= top ajustement for sek-h-centrd
useImgAttr:false,//uses the img height and width attributes if not visible (typically used for the customizr slider hidden images)
setOpacityWhenCentered : false,//this can be used to hide the image during the time it is centered
addCenteredClassWithDelay : 0,//<= a small delay can be required when we rely on the sek-v-centrd or sek-h-centrd css classes to set the opacity for example
opacity : 1
};
function Plugin( element, options ) {
var self = this;
this.container = element;
this.options = $.extend( {}, defaults, options) ;
this._defaults = defaults;
this._name = pluginName;
this._customEvt = nb_.isArray(self.options.oncustom) ? self.options.oncustom : self.options.oncustom.split(' ');
this.init();
}
//can access this.element and this.option
//@return void
Plugin.prototype.init = function () {
var self = this,
_do = function( _event_ ) {
_event_ = _event_ || 'init';
//parses imgs ( if any ) in current container
var $_imgs = $( self.options.imgSel , self.container );
//if no images or centering is not active, only handle the golden ratio on resize event
if ( 1 <= $_imgs.length && self.options.enableCentering ) {
self._parse_imgs( $_imgs, _event_ );
}
};
//fire
if ( self.options.onInit ) {
_do();
}
//bind the container element with custom events if any
//( the images will also be bound )
if ( nb_.isArray( self._customEvt ) ) {
self._customEvt.map( function( evt ) {
var $_containerToListen = ( self.options.$containerToListen instanceof $ && 1 < self.options.$containerToListen.length ) ? self.options.$containerToListen : $( self.container );
$_containerToListen.bind( evt, {} , function() {
_do( evt );
});
} );
}
};
//@return void
Plugin.prototype._parse_imgs = function( $_imgs, _event_ ) {
var self = this;
$_imgs.each(function ( ind, img ) {
var $_img = $(img);
self._pre_img_cent( $_img, _event_ );
// IMG CENTERING FN ON RESIZE ?
// Parse Img can be fired several times, so bind once
if ( self.options.onresize && ! $_img.data('resize-react-bound' ) ) {
$_img.data('resize-react-bound', true );
nb_.cachedElements.$window.on('resize', nb_.debounce( function() {
self._pre_img_cent( $_img, 'resize');
}, 100 ) );
}
});//$_imgs.each()
// Mainly designed to check if a container is not getting parsed too many times
if ( $(self.container).attr('data-img-centered-in-container') ) {
var _n = parseInt( $(self.container).attr('data-img-centered-in-container'), 10 ) + 1;
$(self.container).attr('data-img-centered-in-container', _n );
} else {
$(self.container).attr('data-img-centered-in-container', 1 );
}
};
//@return void
Plugin.prototype._pre_img_cent = function( $_img ) {
var _state = this._get_current_state( $_img ),
self = this,
_case = _state.current,
_p = _state.prop[_case],
_not_p = _state.prop[ 'h' == _case ? 'v' : 'h'],
_not_p_dir_val = 'h' == _case ? ( this.options.zeroTopAdjust || 0 ) : ( this.options.zeroLeftAdjust || 0 );
var _centerImg = function( $_img ) {
$_img
.css( _p.dim.name , _p.dim.val )
.css( _not_p.dim.name , self.options.defaultCSSVal[ _not_p.dim.name ] || 'auto' )
.css( _p.dir.name, _p.dir.val ).css( _not_p.dir.name, _not_p_dir_val );
if ( 0 !== self.options.addCenteredClassWithDelay && nb_.isNumber( self.options.addCenteredClassWithDelay ) ) {
nb_.delay( function() {
$_img.addClass( _p._class ).removeClass( _not_p._class );
}, self.options.addCenteredClassWithDelay );
} else {
$_img.addClass( _p._class ).removeClass( _not_p._class );
}
// Mainly designed to check if a single image is not getting parsed too many times
if ( $_img.attr('data-img-centered') ) {
var _n = parseInt( $_img.attr('data-img-centered'), 10 ) + 1;
$_img.attr('data-img-centered', _n );
} else {
$_img.attr('data-img-centered', 1 );
}
return $_img;
};
if ( this.options.setOpacityWhenCentered ) {
$.when( _centerImg( $_img ) ).done( function( $_img ) {
$_img.css( 'opacity', self.options.opacity );
});
} else {
nb_.delay(function() { _centerImg( $_img ); }, 0 );
}
};
/********
* HELPERS
*********/
//@return object with initial conditions : { current : 'h' or 'v', prop : {} }
Plugin.prototype._get_current_state = function( $_img ) {
var c_x = $_img.closest(this.container).outerWidth(),
c_y = $(this.container).outerHeight(),
i_x = this._get_img_dim( $_img , 'x'),
i_y = this._get_img_dim( $_img , 'y'),
up_i_x = i_y * c_y !== 0 ? Math.round( i_x / i_y * c_y ) : c_x,
up_i_y = i_x * c_x !== 0 ? Math.round( i_y / i_x * c_x ) : c_y,
current = 'h';
//avoid dividing by zero if c_x or i_x === 0
if ( 0 !== c_x * i_x ) {
current = ( c_y / c_x ) >= ( i_y / i_x ) ? 'h' : 'v';
}
var prop = {
h : {
dim : { name : 'height', val : c_y },
dir : { name : 'left', val : ( c_x - up_i_x ) / 2 + ( this.options.leftAdjust || 0 ) },
_class : 'sek-h-centrd'
},
v : {
dim : { name : 'width', val : c_x },
dir : { name : 'top', val : ( c_y - up_i_y ) / 2 + ( this.options.topAdjust || 0 ) },
_class : 'sek-v-centrd'
}
};
return { current : current , prop : prop };
};
//@return img height or width
//uses the img height and width if not visible and set in options
Plugin.prototype._get_img_dim = function( $_img, _dim ) {
if ( ! this.options.useImgAttr )
return 'x' == _dim ? $_img.outerWidth() : $_img.outerHeight();
if ( $_img.is(":visible") ) {
return 'x' == _dim ? $_img.outerWidth() : $_img.outerHeight();
} else {
if ( 'x' == _dim ){
var _width = $_img.originalWidth();
return typeof _width === undefined ? 0 : _width;
}
if ( 'y' == _dim ){
var _height = $_img.originalHeight();
return typeof _height === undefined ? 0 : _height;
}
}
};
/*
* @params string : ids or classes
* @return boolean
*/
Plugin.prototype._is_selector_allowed = function() {
//has requested sel ?
if ( ! $(this.container).attr( 'class' ) )
return true;
var _elSels = $(this.container).attr( 'class' ).split(' '),
_selsToSkip = [],
_filtered = _elSels.filter( function(classe) { return -1 != $.inArray( classe , _selsToSkip ) ;});
//check if the filtered selectors array with the non authorized selectors is empty or not
//if empty => all selectors are allowed
//if not, at least one is not allowed
return 0 === _filtered.length;
};
// prevents against multiple instantiations
$.fn[pluginName] = function ( options ) {
return this.each(function () {
if (!$.data(this, 'plugin_' + pluginName)) {
$.data(this, 'plugin_' + pluginName,
new Plugin( this, options ));
}
});
};
})( jQuery, window );
};/////////////// callbackFunc
// When loaded with defer, we can not be sure that jQuery will be loaded before
// so let's make sure that we have both the plugin and jQuery loaded
nb_.listenTo( 'nb-app-ready', function() {
// on 'nb-app-ready', jQuery is loaded
nb_.listenTo( 'nb-main-swiper-parsed', callbackFunc );
});
}(window, document));
File diff suppressed because one or more lines are too long