wishthis/node_modules/fomantic-ui/dist/components/visibility.js

1282 lines
53 KiB
JavaScript
Raw Normal View History

2022-01-13 13:00:31 +00:00
/*!
2023-08-17 09:47:40 +00:00
* # Fomantic-UI 2.9.2 - Visibility
* https://github.com/fomantic/Fomantic-UI/
2022-01-13 13:00:31 +00:00
*
*
* Released under the MIT license
2023-08-17 09:47:40 +00:00
* https://opensource.org/licenses/MIT
2022-01-13 13:00:31 +00:00
*
*/
2023-08-17 09:47:40 +00:00
(function ($, window, document) {
'use strict';
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
function isFunction(obj) {
return typeof obj === 'function' && typeof obj.nodeType !== 'number';
}
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
window = window !== undefined && window.Math === Math
? window
: globalThis;
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
$.fn.visibility = function (parameters) {
var
$allModules = $(this),
moduleSelector = $allModules.selector || '',
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
time = Date.now(),
performance = [],
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
query = arguments[0],
methodInvoked = typeof query === 'string',
queryArguments = [].slice.call(arguments, 1),
returnedValue,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
moduleCount = $allModules.length,
loadedCount = 0
;
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
$allModules.each(function () {
var
settings = $.isPlainObject(parameters)
? $.extend(true, {}, $.fn.visibility.settings, parameters)
: $.extend({}, $.fn.visibility.settings),
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
className = settings.className,
namespace = settings.namespace,
error = settings.error,
metadata = settings.metadata,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
eventNamespace = '.' + namespace,
moduleNamespace = 'module-' + namespace,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
$window = $(window),
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
$module = $(this),
$context = [window, document].indexOf(settings.context) < 0 ? $(document).find(settings.context) : $(settings.context),
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
$placeholder,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
instance = $module.data(moduleNamespace),
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
element = this,
disabled = false,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
contextObserver,
observer,
module
2022-01-13 13:00:31 +00:00
;
2023-08-17 09:47:40 +00:00
module = {
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
initialize: function () {
module.debug('Initializing', settings);
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
module.setup.cache();
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
if (module.should.trackChanges()) {
if (settings.type === 'image') {
module.setup.image();
}
if (settings.type === 'fixed') {
module.setup.fixed();
}
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
if (settings.observeChanges) {
module.observeChanges();
}
module.bind.events();
}
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
module.save.position();
if (!module.is.visible()) {
module.error(error.visible, $module);
2022-01-13 13:00:31 +00:00
}
2023-08-17 09:47:40 +00:00
if (settings.initialCheck) {
module.checkVisibility();
}
module.instantiate();
},
instantiate: function () {
module.debug('Storing instance', module);
$module
.data(moduleNamespace, module)
;
instance = module;
},
destroy: function () {
module.verbose('Destroying previous module');
if (observer) {
observer.disconnect();
}
if (contextObserver) {
contextObserver.disconnect();
}
$window
.off('load' + eventNamespace, module.event.load)
.off('resize' + eventNamespace, module.event.resize)
;
$context
.off('scroll' + eventNamespace, module.event.scroll)
.off('scrollchange' + eventNamespace, module.event.scrollchange)
;
if (settings.type === 'fixed') {
module.resetFixed();
module.remove.placeholder();
}
$module
.off(eventNamespace)
.removeData(moduleNamespace)
;
},
observeChanges: function () {
if ('MutationObserver' in window) {
contextObserver = new MutationObserver(module.event.contextChanged);
observer = new MutationObserver(module.event.changed);
contextObserver.observe(document, {
childList: true,
subtree: true,
});
observer.observe(element, {
childList: true,
subtree: true,
});
module.debug('Setting up mutation observer', observer);
}
},
bind: {
events: function () {
module.verbose('Binding visibility events to scroll and resize');
if (settings.refreshOnLoad) {
$window
.on('load' + eventNamespace, module.event.load)
;
}
$window
.on('resize' + eventNamespace, module.event.resize)
;
// pub/sub pattern
$context
.off('scroll' + eventNamespace)
.on('scroll' + eventNamespace, module.event.scroll)
.on('scrollchange' + eventNamespace, module.event.scrollchange)
;
},
},
event: {
changed: function (mutations) {
module.verbose('DOM tree modified, updating visibility calculations');
module.timer = setTimeout(function () {
module.verbose('DOM tree modified, updating sticky menu');
module.refresh();
}, 100);
},
contextChanged: function (mutations) {
[].forEach.call(mutations, function (mutation) {
if (mutation.removedNodes) {
[].forEach.call(mutation.removedNodes, function (node) {
if (node === element || $(node).find(element).length > 0) {
module.debug('Element removed from DOM, tearing down events');
module.destroy();
}
});
}
});
},
resize: function () {
module.debug('Window resized');
if (settings.refreshOnResize) {
requestAnimationFrame(module.refresh);
}
},
load: function () {
module.debug('Page finished loading');
requestAnimationFrame(module.refresh);
},
// publishes scrollchange event on one scroll
scroll: function () {
if (settings.throttle) {
clearTimeout(module.timer);
module.timer = setTimeout(function () {
$context.triggerHandler('scrollchange' + eventNamespace, [$context.scrollTop()]);
}, settings.throttle);
} else {
requestAnimationFrame(function () {
$context.triggerHandler('scrollchange' + eventNamespace, [$context.scrollTop()]);
});
}
},
// subscribes to scrollchange
scrollchange: function (event, scrollPosition) {
module.checkVisibility(scrollPosition);
},
},
precache: function (images, callback) {
if (!Array.isArray(images)) {
images = [images];
}
var
imagesLength = images.length,
loadedCounter = 0,
cache = [],
cacheImage = document.createElement('img'),
handleLoad = function () {
loadedCounter++;
if (loadedCounter >= images.length) {
if (isFunction(callback)) {
callback();
}
}
}
;
while (imagesLength--) {
cacheImage = document.createElement('img');
cacheImage.addEventListener('load', handleLoad);
cacheImage.addEventListener('error', handleLoad);
cacheImage.src = images[imagesLength];
cache.push(cacheImage);
}
},
enableCallbacks: function () {
module.debug('Allowing callbacks to occur');
disabled = false;
},
disableCallbacks: function () {
module.debug('Disabling all callbacks temporarily');
disabled = true;
},
should: {
trackChanges: function () {
if (methodInvoked) {
module.debug('One time query, no need to bind events');
return false;
}
module.debug('Callbacks being attached');
return true;
},
},
setup: {
cache: function () {
module.cache = {
occurred: {},
screen: {},
element: {},
};
},
image: function () {
var
src = $module.data(metadata.src)
;
if (src) {
module.verbose('Lazy loading image', src);
settings.once = true;
settings.observeChanges = false;
// show when top visible
settings.onOnScreen = function () {
module.debug('Image on screen', element);
module.precache(src, function () {
module.set.image(src, function () {
loadedCount++;
if (loadedCount === moduleCount) {
settings.onAllLoaded.call(this);
}
settings.onLoad.call(this);
});
});
};
}
},
fixed: function () {
module.debug('Setting up fixed');
settings.once = false;
settings.observeChanges = false;
settings.initialCheck = true;
settings.refreshOnLoad = true;
if (!parameters.transition) {
settings.transition = false;
}
module.create.placeholder();
module.debug('Added placeholder', $placeholder);
settings.onTopPassed = function () {
module.debug('Element passed, adding fixed position', $module);
module.show.placeholder();
module.set.fixed();
if (settings.transition) {
if ($.fn.transition !== undefined) {
$module.transition(settings.transition, settings.duration);
}
}
};
settings.onTopPassedReverse = function () {
module.debug('Element returned to position, removing fixed', $module);
module.hide.placeholder();
module.remove.fixed();
};
},
},
create: {
placeholder: function () {
module.verbose('Creating fixed position placeholder');
$placeholder = $module
.clone(false)
.css('display', 'none')
.addClass(className.placeholder)
.insertAfter($module)
;
},
},
show: {
placeholder: function () {
module.verbose('Showing placeholder');
$placeholder
.css('display', 'block')
.css('visibility', 'hidden')
;
},
},
hide: {
placeholder: function () {
module.verbose('Hiding placeholder');
$placeholder
.css('display', 'none')
.css('visibility', '')
;
},
},
set: {
fixed: function () {
module.verbose('Setting element to fixed position');
$module
.addClass(className.fixed)
.css({
position: 'fixed',
top: settings.offset + 'px',
left: 'auto',
zIndex: settings.zIndex,
})
;
settings.onFixed.call(element);
},
image: function (src, callback) {
$module
.attr('src', src)
;
if (settings.transition) {
if ($.fn.transition !== undefined) {
if ($module.hasClass(className.visible)) {
module.debug('Transition already occurred on this image, skipping animation');
return;
}
$module.transition(settings.transition, settings.duration, callback);
} else {
$module.fadeIn(settings.duration, callback);
}
} else {
$module.show();
}
},
},
is: {
onScreen: function () {
var
calculations = module.get.elementCalculations()
;
return calculations.onScreen;
},
offScreen: function () {
var
calculations = module.get.elementCalculations()
;
return calculations.offScreen;
},
visible: function () {
if (module.cache && module.cache.element) {
return !(module.cache.element.width === 0 && module.cache.element.offset.top === 0);
}
return false;
},
verticallyScrollableContext: function () {
var
overflowY = $context[0] !== window
? $context.css('overflow-y')
: false
;
return overflowY === 'auto' || overflowY === 'scroll';
},
horizontallyScrollableContext: function () {
var
overflowX = $context[0] !== window
? $context.css('overflow-x')
: false
;
return overflowX === 'auto' || overflowX === 'scroll';
},
},
refresh: function () {
module.debug('Refreshing constants (width/height)');
if (settings.type === 'fixed') {
module.resetFixed();
}
module.reset();
module.save.position();
if (settings.checkOnRefresh) {
module.checkVisibility();
}
settings.onRefresh.call(element);
},
resetFixed: function () {
module.remove.fixed();
module.remove.occurred();
},
reset: function () {
module.verbose('Resetting all cached values');
if ($.isPlainObject(module.cache)) {
module.cache.screen = {};
module.cache.element = {};
}
},
checkVisibility: function (scroll) {
module.verbose('Checking visibility of element', module.cache.element);
if (!disabled && module.is.visible()) {
// save scroll position
module.save.scroll(scroll);
// update calculations derived from scroll
module.save.calculations();
// percentage
module.passed();
// reverse (must be first)
module.passingReverse();
module.topVisibleReverse();
module.bottomVisibleReverse();
module.topPassedReverse();
module.bottomPassedReverse();
// one time
module.onScreen();
module.offScreen();
module.passing();
module.topVisible();
module.bottomVisible();
module.topPassed();
module.bottomPassed();
// on update callback
if (settings.onUpdate) {
settings.onUpdate.call(element, module.get.elementCalculations());
}
}
},
passed: function (amount, newCallback) {
var
calculations = module.get.elementCalculations()
;
// assign callback
if (amount && newCallback) {
settings.onPassed[amount] = newCallback;
} else if (amount !== undefined) {
return module.get.pixelsPassed(amount) > calculations.pixelsPassed;
} else if (calculations.passing) {
$.each(settings.onPassed, function (amount, callback) {
if (calculations.bottomVisible || calculations.pixelsPassed > module.get.pixelsPassed(amount)) {
module.execute(callback, amount);
} else if (!settings.once) {
module.remove.occurred(callback);
}
});
}
},
onScreen: function (newCallback) {
var
calculations = module.get.elementCalculations(),
callback = newCallback || settings.onOnScreen,
callbackName = 'onScreen'
;
if (newCallback) {
module.debug('Adding callback for onScreen', newCallback);
settings.onOnScreen = newCallback;
}
if (calculations.onScreen) {
module.execute(callback, callbackName);
} else if (!settings.once) {
module.remove.occurred(callbackName);
}
if (newCallback !== undefined) {
return calculations.onOnScreen;
}
},
offScreen: function (newCallback) {
var
calculations = module.get.elementCalculations(),
callback = newCallback || settings.onOffScreen,
callbackName = 'offScreen'
;
if (newCallback) {
module.debug('Adding callback for offScreen', newCallback);
settings.onOffScreen = newCallback;
}
if (calculations.offScreen) {
module.execute(callback, callbackName);
} else if (!settings.once) {
module.remove.occurred(callbackName);
}
if (newCallback !== undefined) {
return calculations.onOffScreen;
}
},
passing: function (newCallback) {
var
calculations = module.get.elementCalculations(),
callback = newCallback || settings.onPassing,
callbackName = 'passing'
;
if (newCallback) {
module.debug('Adding callback for passing', newCallback);
settings.onPassing = newCallback;
}
if (calculations.passing) {
module.execute(callback, callbackName);
} else if (!settings.once) {
module.remove.occurred(callbackName);
}
if (newCallback !== undefined) {
return calculations.passing;
}
},
topVisible: function (newCallback) {
var
calculations = module.get.elementCalculations(),
callback = newCallback || settings.onTopVisible,
callbackName = 'topVisible'
;
if (newCallback) {
module.debug('Adding callback for top visible', newCallback);
settings.onTopVisible = newCallback;
}
if (calculations.topVisible) {
module.execute(callback, callbackName);
} else if (!settings.once) {
module.remove.occurred(callbackName);
}
if (newCallback === undefined) {
return calculations.topVisible;
}
},
bottomVisible: function (newCallback) {
var
calculations = module.get.elementCalculations(),
callback = newCallback || settings.onBottomVisible,
callbackName = 'bottomVisible'
;
if (newCallback) {
module.debug('Adding callback for bottom visible', newCallback);
settings.onBottomVisible = newCallback;
}
if (calculations.bottomVisible) {
module.execute(callback, callbackName);
} else if (!settings.once) {
module.remove.occurred(callbackName);
}
if (newCallback === undefined) {
return calculations.bottomVisible;
}
},
topPassed: function (newCallback) {
var
calculations = module.get.elementCalculations(),
callback = newCallback || settings.onTopPassed,
callbackName = 'topPassed'
;
if (newCallback) {
module.debug('Adding callback for top passed', newCallback);
settings.onTopPassed = newCallback;
}
if (calculations.topPassed) {
module.execute(callback, callbackName);
} else if (!settings.once) {
module.remove.occurred(callbackName);
}
if (newCallback === undefined) {
return calculations.topPassed;
}
},
bottomPassed: function (newCallback) {
var
calculations = module.get.elementCalculations(),
callback = newCallback || settings.onBottomPassed,
callbackName = 'bottomPassed'
;
if (newCallback) {
module.debug('Adding callback for bottom passed', newCallback);
settings.onBottomPassed = newCallback;
}
if (calculations.bottomPassed) {
module.execute(callback, callbackName);
} else if (!settings.once) {
module.remove.occurred(callbackName);
}
if (newCallback === undefined) {
return calculations.bottomPassed;
}
},
passingReverse: function (newCallback) {
var
calculations = module.get.elementCalculations(),
callback = newCallback || settings.onPassingReverse,
callbackName = 'passingReverse'
;
if (newCallback) {
module.debug('Adding callback for passing reverse', newCallback);
settings.onPassingReverse = newCallback;
}
if (!calculations.passing) {
if (module.get.occurred('passing')) {
module.execute(callback, callbackName);
}
} else if (!settings.once) {
module.remove.occurred(callbackName);
}
if (newCallback !== undefined) {
return !calculations.passing;
}
},
topVisibleReverse: function (newCallback) {
var
calculations = module.get.elementCalculations(),
callback = newCallback || settings.onTopVisibleReverse,
callbackName = 'topVisibleReverse'
;
if (newCallback) {
module.debug('Adding callback for top visible reverse', newCallback);
settings.onTopVisibleReverse = newCallback;
}
if (!calculations.topVisible) {
if (module.get.occurred('topVisible')) {
module.execute(callback, callbackName);
}
} else if (!settings.once) {
module.remove.occurred(callbackName);
}
if (newCallback === undefined) {
return !calculations.topVisible;
}
},
bottomVisibleReverse: function (newCallback) {
var
calculations = module.get.elementCalculations(),
callback = newCallback || settings.onBottomVisibleReverse,
callbackName = 'bottomVisibleReverse'
;
if (newCallback) {
module.debug('Adding callback for bottom visible reverse', newCallback);
settings.onBottomVisibleReverse = newCallback;
}
if (!calculations.bottomVisible) {
if (module.get.occurred('bottomVisible')) {
module.execute(callback, callbackName);
}
} else if (!settings.once) {
module.remove.occurred(callbackName);
}
if (newCallback === undefined) {
return !calculations.bottomVisible;
}
},
topPassedReverse: function (newCallback) {
var
calculations = module.get.elementCalculations(),
callback = newCallback || settings.onTopPassedReverse,
callbackName = 'topPassedReverse'
;
if (newCallback) {
module.debug('Adding callback for top passed reverse', newCallback);
settings.onTopPassedReverse = newCallback;
}
if (!calculations.topPassed) {
if (module.get.occurred('topPassed')) {
module.execute(callback, callbackName);
}
} else if (!settings.once) {
module.remove.occurred(callbackName);
}
if (newCallback === undefined) {
return !calculations.onTopPassed;
}
},
bottomPassedReverse: function (newCallback) {
var
calculations = module.get.elementCalculations(),
callback = newCallback || settings.onBottomPassedReverse,
callbackName = 'bottomPassedReverse'
;
if (newCallback) {
module.debug('Adding callback for bottom passed reverse', newCallback);
settings.onBottomPassedReverse = newCallback;
}
if (!calculations.bottomPassed) {
if (module.get.occurred('bottomPassed')) {
module.execute(callback, callbackName);
}
} else if (!settings.once) {
module.remove.occurred(callbackName);
}
if (newCallback === undefined) {
return !calculations.bottomPassed;
}
},
execute: function (callback, callbackName) {
var
calculations = module.get.elementCalculations(),
screen = module.get.screenCalculations()
;
callback = callback || false;
if (callback) {
if (settings.continuous) {
module.debug('Callback being called continuously', callbackName, calculations);
callback.call(element, calculations, screen);
} else if (!module.get.occurred(callbackName)) {
module.debug('Conditions met', callbackName, calculations);
callback.call(element, calculations, screen);
}
}
module.save.occurred(callbackName);
},
remove: {
fixed: function () {
module.debug('Removing fixed position');
$module
.removeClass(className.fixed)
.css({
position: '',
top: '',
left: '',
zIndex: '',
})
;
settings.onUnfixed.call(element);
},
placeholder: function () {
module.debug('Removing placeholder content');
if ($placeholder) {
$placeholder.remove();
}
},
occurred: function (callback) {
if (callback) {
var
occurred = module.cache.occurred
;
if (occurred[callback] !== undefined && occurred[callback] === true) {
module.debug('Callback can now be called again', callback);
module.cache.occurred[callback] = false;
}
} else {
module.cache.occurred = {};
}
},
},
save: {
calculations: function () {
module.verbose('Saving all calculations necessary to determine positioning');
module.save.direction();
module.save.screenCalculations();
module.save.elementCalculations();
},
occurred: function (callback) {
if (callback) {
if (module.cache.occurred[callback] === undefined || (module.cache.occurred[callback] !== true)) {
module.verbose('Saving callback occurred', callback);
module.cache.occurred[callback] = true;
}
}
},
scroll: function (scrollPosition) {
scrollPosition = scrollPosition + settings.offset || $context.scrollTop() + settings.offset;
module.cache.scroll = scrollPosition;
},
direction: function () {
var
scroll = module.get.scroll(),
lastScroll = module.get.lastScroll(),
direction
;
if (scroll > lastScroll && lastScroll) {
direction = 'down';
} else if (scroll < lastScroll && lastScroll) {
direction = 'up';
} else {
direction = 'static';
}
module.cache.direction = direction;
return module.cache.direction;
},
elementPosition: function () {
var
element = module.cache.element,
screen = module.get.screenSize()
;
module.verbose('Saving element position');
// (quicker than $.extend)
element.fits = element.height < screen.height;
element.offset = $module.offset();
element.width = $module.outerWidth();
element.height = $module.outerHeight();
// compensate for scroll in context
if (module.is.verticallyScrollableContext()) {
element.offset.top += $context.scrollTop() - $context.offset().top;
}
if (module.is.horizontallyScrollableContext()) {
element.offset.left += $context.scrollLeft() - $context.offset().left;
}
// store
module.cache.element = element;
return element;
},
elementCalculations: function () {
var
screen = module.get.screenCalculations(),
element = module.get.elementPosition()
;
// offset
if (settings.includeMargin) {
element.margin = {};
element.margin.top = parseInt($module.css('margin-top'), 10);
element.margin.bottom = parseInt($module.css('margin-bottom'), 10);
element.top = element.offset.top - element.margin.top;
element.bottom = element.offset.top + element.height + element.margin.bottom;
} else {
element.top = element.offset.top;
element.bottom = element.offset.top + element.height;
}
// visibility
element.topPassed = screen.top >= element.top;
element.bottomPassed = screen.top >= element.bottom;
element.topVisible = (screen.bottom >= element.top) && !element.topPassed;
element.bottomVisible = (screen.bottom >= element.bottom) && !element.bottomPassed;
element.pixelsPassed = 0;
element.percentagePassed = 0;
// meta calculations
element.onScreen = (element.topVisible || element.passing) && !element.bottomPassed;
element.passing = element.topPassed && !element.bottomPassed;
element.offScreen = !element.onScreen;
// passing calculations
if (element.passing) {
element.pixelsPassed = screen.top - element.top;
element.percentagePassed = (screen.top - element.top) / element.height;
}
module.cache.element = element;
module.verbose('Updated element calculations', element);
return element;
},
screenCalculations: function () {
var
scroll = module.get.scroll()
;
module.save.direction();
module.cache.screen.top = scroll;
module.cache.screen.bottom = scroll + module.cache.screen.height;
return module.cache.screen;
},
screenSize: function () {
module.verbose('Saving window position');
module.cache.screen = {
height: $context.height(),
};
},
position: function () {
module.save.screenSize();
module.save.elementPosition();
},
},
get: {
pixelsPassed: function (amount) {
var
element = module.get.elementCalculations()
;
if (amount.search('%') > -1) {
return element.height * (parseInt(amount, 10) / 100);
}
return parseInt(amount, 10);
},
occurred: function (callback) {
return module.cache.occurred !== undefined
? module.cache.occurred[callback] || false
: false;
},
direction: function () {
if (module.cache.direction === undefined) {
module.save.direction();
}
return module.cache.direction;
},
elementPosition: function () {
if (module.cache.element === undefined) {
module.save.elementPosition();
}
return module.cache.element;
},
elementCalculations: function () {
if (module.cache.element === undefined) {
module.save.elementCalculations();
}
return module.cache.element;
},
screenCalculations: function () {
if (module.cache.screen === undefined) {
module.save.screenCalculations();
}
return module.cache.screen;
},
screenSize: function () {
if (module.cache.screen === undefined) {
module.save.screenSize();
}
return module.cache.screen;
},
scroll: function () {
if (module.cache.scroll === undefined) {
module.save.scroll();
}
return module.cache.scroll;
},
lastScroll: function () {
if (module.cache.screen === undefined) {
module.debug('First scroll event, no last scroll could be found');
return false;
}
return module.cache.screen.top;
},
},
setting: function (name, value) {
if ($.isPlainObject(name)) {
$.extend(true, settings, name);
} else if (value !== undefined) {
settings[name] = value;
} else {
return settings[name];
}
},
internal: function (name, value) {
if ($.isPlainObject(name)) {
$.extend(true, module, name);
} else if (value !== undefined) {
module[name] = value;
} else {
return module[name];
}
},
debug: function () {
if (!settings.silent && settings.debug) {
if (settings.performance) {
module.performance.log(arguments);
} else {
module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
module.debug.apply(console, arguments);
}
}
},
verbose: function () {
if (!settings.silent && settings.verbose && settings.debug) {
if (settings.performance) {
module.performance.log(arguments);
} else {
module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
module.verbose.apply(console, arguments);
}
}
},
error: function () {
if (!settings.silent) {
module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
module.error.apply(console, arguments);
}
},
performance: {
log: function (message) {
var
currentTime,
executionTime,
previousTime
;
if (settings.performance) {
currentTime = Date.now();
previousTime = time || currentTime;
executionTime = currentTime - previousTime;
time = currentTime;
performance.push({
Name: message[0],
Arguments: [].slice.call(message, 1) || '',
Element: element,
'Execution Time': executionTime,
});
}
clearTimeout(module.performance.timer);
module.performance.timer = setTimeout(module.performance.display, 500);
},
display: function () {
var
title = settings.name + ':',
totalTime = 0
;
time = false;
clearTimeout(module.performance.timer);
$.each(performance, function (index, data) {
totalTime += data['Execution Time'];
});
title += ' ' + totalTime + 'ms';
if (moduleSelector) {
title += ' \'' + moduleSelector + '\'';
}
if (performance.length > 0) {
console.groupCollapsed(title);
if (console.table) {
console.table(performance);
} else {
$.each(performance, function (index, data) {
console.log(data.Name + ': ' + data['Execution Time'] + 'ms');
});
}
console.groupEnd();
}
performance = [];
},
},
invoke: function (query, passedArguments, context) {
var
object = instance,
maxDepth,
found,
response
;
passedArguments = passedArguments || queryArguments;
context = context || element;
if (typeof query === 'string' && object !== undefined) {
query = query.split(/[ .]/);
maxDepth = query.length - 1;
$.each(query, function (depth, value) {
var camelCaseValue = depth !== maxDepth
? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
: query
;
if ($.isPlainObject(object[camelCaseValue]) && (depth !== maxDepth)) {
object = object[camelCaseValue];
} else if (object[camelCaseValue] !== undefined) {
found = object[camelCaseValue];
return false;
} else if ($.isPlainObject(object[value]) && (depth !== maxDepth)) {
object = object[value];
} else if (object[value] !== undefined) {
found = object[value];
return false;
} else {
module.error(error.method, query);
return false;
}
});
}
if (isFunction(found)) {
response = found.apply(context, passedArguments);
} else if (found !== undefined) {
response = found;
}
if (Array.isArray(returnedValue)) {
returnedValue.push(response);
} else if (returnedValue !== undefined) {
returnedValue = [returnedValue, response];
} else if (response !== undefined) {
returnedValue = response;
}
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
return found;
},
};
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
if (methodInvoked) {
if (instance === undefined) {
module.initialize();
2022-01-13 13:00:31 +00:00
}
2023-08-17 09:47:40 +00:00
instance.save.scroll();
instance.save.calculations();
module.invoke(query);
} else {
if (instance !== undefined) {
instance.invoke('destroy');
}
module.initialize();
2022-01-13 13:00:31 +00:00
}
2023-08-17 09:47:40 +00:00
});
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
return returnedValue !== undefined
? returnedValue
: this;
};
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
$.fn.visibility.settings = {
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
name: 'Visibility',
namespace: 'visibility',
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
debug: false,
verbose: false,
performance: true,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// whether to use mutation observers to follow changes
observeChanges: true,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// check position immediately on init
initialCheck: true,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// whether to refresh calculations after all page images load
refreshOnLoad: true,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// whether to refresh calculations after page resize event
refreshOnResize: true,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// should call callbacks on refresh event (resize, etc)
checkOnRefresh: true,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// callback should only occur one time
once: true,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// callback should fire continuously when evaluates to true
continuous: false,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// offset to use with scroll top
offset: 0,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// whether to include margin in elements position
includeMargin: false,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// scroll context for visibility checks
context: window,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// visibility check delay in ms (defaults to animationFrame)
throttle: false,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// special visibility type (image, fixed)
type: false,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// z-index to use with visibility 'fixed'
zIndex: '10',
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// image only animation settings
transition: 'fade in',
duration: 1000,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// array of callbacks for percentage
onPassed: {},
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// standard callbacks
onOnScreen: false,
onOffScreen: false,
onPassing: false,
onTopVisible: false,
onBottomVisible: false,
onTopPassed: false,
onBottomPassed: false,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// reverse callbacks
onPassingReverse: false,
onTopVisibleReverse: false,
onBottomVisibleReverse: false,
onTopPassedReverse: false,
onBottomPassedReverse: false,
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// special callbacks for image
onLoad: function () {},
onAllLoaded: function () {},
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// special callbacks for fixed position
onFixed: function () {},
onUnfixed: function () {},
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
// utility callbacks
onUpdate: false, // disabled by default for performance
onRefresh: function () {},
2022-01-13 13:00:31 +00:00
2023-08-17 09:47:40 +00:00
metadata: {
src: 'src',
2022-01-13 13:00:31 +00:00
},
2023-08-17 09:47:40 +00:00
className: {
fixed: 'fixed',
placeholder: 'constraint',
visible: 'visible',
2022-01-13 13:00:31 +00:00
},
2023-08-17 09:47:40 +00:00
error: {
method: 'The method you called is not defined.',
visible: 'Element is hidden, you must call refresh after element becomes visible',
2022-01-13 13:00:31 +00:00
},
2023-08-17 09:47:40 +00:00
};
})(jQuery, window, document);