first commit
This commit is contained in:
@@ -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));
|
||||
|
||||
|
||||
+1
@@ -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));
|
||||
+1
@@ -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));
|
||||
+1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user