| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311 | /*! * # Semantic UI 2.4.2 - Visibility * http://github.com/semantic-org/semantic-ui/ * * * Released under the MIT license * http://opensource.org/licenses/MIT * */;(function ($, window, document, undefined) {'use strict';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,        selector        = $module.selector || '',        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(),            amountInPixels          ;          // 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($.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 : 'placeholder',    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 );
 |