diff options
Diffstat (limited to 'src/wwwroot/libraries/fomantic/dist/components/visibility.js')
| -rw-r--r-- | src/wwwroot/libraries/fomantic/dist/components/visibility.js | 1313 |
1 files changed, 1313 insertions, 0 deletions
diff --git a/src/wwwroot/libraries/fomantic/dist/components/visibility.js b/src/wwwroot/libraries/fomantic/dist/components/visibility.js new file mode 100644 index 0000000..97a96e2 --- /dev/null +++ b/src/wwwroot/libraries/fomantic/dist/components/visibility.js @@ -0,0 +1,1313 @@ +/*! + * # Fomantic-UI - Visibility + * http://github.com/fomantic/Fomantic-UI/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ($, window, document, undefined) { + +'use strict'; + +$.isFunction = $.isFunction || function(obj) { + return typeof obj === "function" && typeof obj.nodeType !== "number"; +}; + +window = (typeof window != 'undefined' && window.Math == Math) + ? window + : (typeof self != 'undefined' && self.Math == Math) + ? self + : Function('return this')() +; + +$.fn.visibility = function(parameters) { + var + $allModules = $(this), + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + returnedValue, + + moduleCount = $allModules.length, + loadedCount = 0 + ; + + $allModules + .each(function() { + var + settings = ( $.isPlainObject(parameters) ) + ? $.extend(true, {}, $.fn.visibility.settings, parameters) + : $.extend({}, $.fn.visibility.settings), + + className = settings.className, + namespace = settings.namespace, + error = settings.error, + metadata = settings.metadata, + + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + + $window = $(window), + + $module = $(this), + $context = $(settings.context), + + $placeholder, + + instance = $module.data(moduleNamespace), + + requestAnimationFrame = window.requestAnimationFrame + || window.mozRequestAnimationFrame + || window.webkitRequestAnimationFrame + || window.msRequestAnimationFrame + || function(callback) { setTimeout(callback, 0); }, + + element = this, + disabled = false, + + contextObserver, + observer, + module + ; + + module = { + + initialize: function() { + module.debug('Initializing', settings); + + module.setup.cache(); + + if( module.should.trackChanges() ) { + + if(settings.type == 'image') { + module.setup.image(); + } + if(settings.type == 'fixed') { + module.setup.fixed(); + } + + if(settings.observeChanges) { + module.observeChanges(); + } + module.bind.events(); + } + + module.save.position(); + if( !module.is.visible() ) { + module.error(error.visible, $module); + } + + 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 (!(images instanceof Array)) { + 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.onload = handleLoad; + cacheImage.onerror = 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.get(0) !== window) + ? $context.css('overflow-y') + : false + ; + return (overflowY == 'auto' || overflowY == 'scroll'); + }, + horizontallyScrollableContext: function() { + var + overflowX = ($context.get(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 = new Date().getTime(); + 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( (console.group !== undefined || console.table !== undefined) && 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 = element || context; + 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; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + instance.save.scroll(); + instance.save.calculations(); + module.invoke(query); + } + else { + if(instance !== undefined) { + instance.invoke('destroy'); + } + module.initialize(); + } + }) + ; + + return (returnedValue !== undefined) + ? returnedValue + : this + ; +}; + +$.fn.visibility.settings = { + + name : 'Visibility', + namespace : 'visibility', + + debug : false, + verbose : false, + performance : true, + + // whether to use mutation observers to follow changes + observeChanges : true, + + // check position immediately on init + initialCheck : true, + + // whether to refresh calculations after all page images load + refreshOnLoad : true, + + // whether to refresh calculations after page resize event + refreshOnResize : true, + + // should call callbacks on refresh event (resize, etc) + checkOnRefresh : true, + + // callback should only occur one time + once : true, + + // callback should fire continuously whe evaluates to true + continuous : false, + + // offset to use with scroll top + offset : 0, + + // whether to include margin in elements position + includeMargin : false, + + // scroll context for visibility checks + context : window, + + // visibility check delay in ms (defaults to animationFrame) + throttle : false, + + // special visibility type (image, fixed) + type : false, + + // z-index to use with visibility 'fixed' + zIndex : '10', + + // image only animation settings + transition : 'fade in', + duration : 1000, + + // array of callbacks for percentage + onPassed : {}, + + // standard callbacks + onOnScreen : false, + onOffScreen : false, + onPassing : false, + onTopVisible : false, + onBottomVisible : false, + onTopPassed : false, + onBottomPassed : false, + + // reverse callbacks + onPassingReverse : false, + onTopVisibleReverse : false, + onBottomVisibleReverse : false, + onTopPassedReverse : false, + onBottomPassedReverse : false, + + // special callbacks for image + onLoad : function() {}, + onAllLoaded : function() {}, + + // special callbacks for fixed position + onFixed : function() {}, + onUnfixed : function() {}, + + // utility callbacks + onUpdate : false, // disabled by default for performance + onRefresh : function(){}, + + metadata : { + src: 'src' + }, + + className: { + fixed : 'fixed', + placeholder : 'constraint', + visible : 'visible' + }, + + error : { + method : 'The method you called is not defined.', + visible : 'Element is hidden, you must call refresh after element becomes visible' + } + +}; + +})( jQuery, window, document ); |
