@@ 21583-22883 (lines=1301) @@ | ||
21580 | * |
|
21581 | */ |
|
21582 | ||
21583 | ;(function ($, window, document, undefined) { |
|
21584 | ||
21585 | "use strict"; |
|
21586 | ||
21587 | window = (typeof window != 'undefined' && window.Math == Math) |
|
21588 | ? window |
|
21589 | : (typeof self != 'undefined' && self.Math == Math) |
|
21590 | ? self |
|
21591 | : Function('return this')() |
|
21592 | ; |
|
21593 | ||
21594 | $.fn.visibility = function(parameters) { |
|
21595 | var |
|
21596 | $allModules = $(this), |
|
21597 | moduleSelector = $allModules.selector || '', |
|
21598 | ||
21599 | time = new Date().getTime(), |
|
21600 | performance = [], |
|
21601 | ||
21602 | query = arguments[0], |
|
21603 | methodInvoked = (typeof query == 'string'), |
|
21604 | queryArguments = [].slice.call(arguments, 1), |
|
21605 | returnedValue, |
|
21606 | ||
21607 | moduleCount = $allModules.length, |
|
21608 | loadedCount = 0 |
|
21609 | ; |
|
21610 | ||
21611 | $allModules |
|
21612 | .each(function() { |
|
21613 | var |
|
21614 | settings = ( $.isPlainObject(parameters) ) |
|
21615 | ? $.extend(true, {}, $.fn.visibility.settings, parameters) |
|
21616 | : $.extend({}, $.fn.visibility.settings), |
|
21617 | ||
21618 | className = settings.className, |
|
21619 | namespace = settings.namespace, |
|
21620 | error = settings.error, |
|
21621 | metadata = settings.metadata, |
|
21622 | ||
21623 | eventNamespace = '.' + namespace, |
|
21624 | moduleNamespace = 'module-' + namespace, |
|
21625 | ||
21626 | $window = $(window), |
|
21627 | ||
21628 | $module = $(this), |
|
21629 | $context = $(settings.context), |
|
21630 | ||
21631 | $placeholder, |
|
21632 | ||
21633 | selector = $module.selector || '', |
|
21634 | instance = $module.data(moduleNamespace), |
|
21635 | ||
21636 | requestAnimationFrame = window.requestAnimationFrame |
|
21637 | || window.mozRequestAnimationFrame |
|
21638 | || window.webkitRequestAnimationFrame |
|
21639 | || window.msRequestAnimationFrame |
|
21640 | || function(callback) { setTimeout(callback, 0); }, |
|
21641 | ||
21642 | element = this, |
|
21643 | disabled = false, |
|
21644 | ||
21645 | contextObserver, |
|
21646 | observer, |
|
21647 | module |
|
21648 | ; |
|
21649 | ||
21650 | module = { |
|
21651 | ||
21652 | initialize: function() { |
|
21653 | module.debug('Initializing', settings); |
|
21654 | ||
21655 | module.setup.cache(); |
|
21656 | ||
21657 | if( module.should.trackChanges() ) { |
|
21658 | ||
21659 | if(settings.type == 'image') { |
|
21660 | module.setup.image(); |
|
21661 | } |
|
21662 | if(settings.type == 'fixed') { |
|
21663 | module.setup.fixed(); |
|
21664 | } |
|
21665 | ||
21666 | if(settings.observeChanges) { |
|
21667 | module.observeChanges(); |
|
21668 | } |
|
21669 | module.bind.events(); |
|
21670 | } |
|
21671 | ||
21672 | module.save.position(); |
|
21673 | if( !module.is.visible() ) { |
|
21674 | module.error(error.visible, $module); |
|
21675 | } |
|
21676 | ||
21677 | if(settings.initialCheck) { |
|
21678 | module.checkVisibility(); |
|
21679 | } |
|
21680 | module.instantiate(); |
|
21681 | }, |
|
21682 | ||
21683 | instantiate: function() { |
|
21684 | module.debug('Storing instance', module); |
|
21685 | $module |
|
21686 | .data(moduleNamespace, module) |
|
21687 | ; |
|
21688 | instance = module; |
|
21689 | }, |
|
21690 | ||
21691 | destroy: function() { |
|
21692 | module.verbose('Destroying previous module'); |
|
21693 | if(observer) { |
|
21694 | observer.disconnect(); |
|
21695 | } |
|
21696 | if(contextObserver) { |
|
21697 | contextObserver.disconnect(); |
|
21698 | } |
|
21699 | $window |
|
21700 | .off('load' + eventNamespace, module.event.load) |
|
21701 | .off('resize' + eventNamespace, module.event.resize) |
|
21702 | ; |
|
21703 | $context |
|
21704 | .off('scroll' + eventNamespace, module.event.scroll) |
|
21705 | .off('scrollchange' + eventNamespace, module.event.scrollchange) |
|
21706 | ; |
|
21707 | if(settings.type == 'fixed') { |
|
21708 | module.resetFixed(); |
|
21709 | module.remove.placeholder(); |
|
21710 | } |
|
21711 | $module |
|
21712 | .off(eventNamespace) |
|
21713 | .removeData(moduleNamespace) |
|
21714 | ; |
|
21715 | }, |
|
21716 | ||
21717 | observeChanges: function() { |
|
21718 | if('MutationObserver' in window) { |
|
21719 | contextObserver = new MutationObserver(module.event.contextChanged); |
|
21720 | observer = new MutationObserver(module.event.changed); |
|
21721 | contextObserver.observe(document, { |
|
21722 | childList : true, |
|
21723 | subtree : true |
|
21724 | }); |
|
21725 | observer.observe(element, { |
|
21726 | childList : true, |
|
21727 | subtree : true |
|
21728 | }); |
|
21729 | module.debug('Setting up mutation observer', observer); |
|
21730 | } |
|
21731 | }, |
|
21732 | ||
21733 | bind: { |
|
21734 | events: function() { |
|
21735 | module.verbose('Binding visibility events to scroll and resize'); |
|
21736 | if(settings.refreshOnLoad) { |
|
21737 | $window |
|
21738 | .on('load' + eventNamespace, module.event.load) |
|
21739 | ; |
|
21740 | } |
|
21741 | $window |
|
21742 | .on('resize' + eventNamespace, module.event.resize) |
|
21743 | ; |
|
21744 | // pub/sub pattern |
|
21745 | $context |
|
21746 | .off('scroll' + eventNamespace) |
|
21747 | .on('scroll' + eventNamespace, module.event.scroll) |
|
21748 | .on('scrollchange' + eventNamespace, module.event.scrollchange) |
|
21749 | ; |
|
21750 | } |
|
21751 | }, |
|
21752 | ||
21753 | event: { |
|
21754 | changed: function(mutations) { |
|
21755 | module.verbose('DOM tree modified, updating visibility calculations'); |
|
21756 | module.timer = setTimeout(function() { |
|
21757 | module.verbose('DOM tree modified, updating sticky menu'); |
|
21758 | module.refresh(); |
|
21759 | }, 100); |
|
21760 | }, |
|
21761 | contextChanged: function(mutations) { |
|
21762 | [].forEach.call(mutations, function(mutation) { |
|
21763 | if(mutation.removedNodes) { |
|
21764 | [].forEach.call(mutation.removedNodes, function(node) { |
|
21765 | if(node == element || $(node).find(element).length > 0) { |
|
21766 | module.debug('Element removed from DOM, tearing down events'); |
|
21767 | module.destroy(); |
|
21768 | } |
|
21769 | }); |
|
21770 | } |
|
21771 | }); |
|
21772 | }, |
|
21773 | resize: function() { |
|
21774 | module.debug('Window resized'); |
|
21775 | if(settings.refreshOnResize) { |
|
21776 | requestAnimationFrame(module.refresh); |
|
21777 | } |
|
21778 | }, |
|
21779 | load: function() { |
|
21780 | module.debug('Page finished loading'); |
|
21781 | requestAnimationFrame(module.refresh); |
|
21782 | }, |
|
21783 | // publishes scrollchange event on one scroll |
|
21784 | scroll: function() { |
|
21785 | if(settings.throttle) { |
|
21786 | clearTimeout(module.timer); |
|
21787 | module.timer = setTimeout(function() { |
|
21788 | $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]); |
|
21789 | }, settings.throttle); |
|
21790 | } |
|
21791 | else { |
|
21792 | requestAnimationFrame(function() { |
|
21793 | $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]); |
|
21794 | }); |
|
21795 | } |
|
21796 | }, |
|
21797 | // subscribes to scrollchange |
|
21798 | scrollchange: function(event, scrollPosition) { |
|
21799 | module.checkVisibility(scrollPosition); |
|
21800 | }, |
|
21801 | }, |
|
21802 | ||
21803 | precache: function(images, callback) { |
|
21804 | if (!(images instanceof Array)) { |
|
21805 | images = [images]; |
|
21806 | } |
|
21807 | var |
|
21808 | imagesLength = images.length, |
|
21809 | loadedCounter = 0, |
|
21810 | cache = [], |
|
21811 | cacheImage = document.createElement('img'), |
|
21812 | handleLoad = function() { |
|
21813 | loadedCounter++; |
|
21814 | if (loadedCounter >= images.length) { |
|
21815 | if ($.isFunction(callback)) { |
|
21816 | callback(); |
|
21817 | } |
|
21818 | } |
|
21819 | } |
|
21820 | ; |
|
21821 | while (imagesLength--) { |
|
21822 | cacheImage = document.createElement('img'); |
|
21823 | cacheImage.onload = handleLoad; |
|
21824 | cacheImage.onerror = handleLoad; |
|
21825 | cacheImage.src = images[imagesLength]; |
|
21826 | cache.push(cacheImage); |
|
21827 | } |
|
21828 | }, |
|
21829 | ||
21830 | enableCallbacks: function() { |
|
21831 | module.debug('Allowing callbacks to occur'); |
|
21832 | disabled = false; |
|
21833 | }, |
|
21834 | ||
21835 | disableCallbacks: function() { |
|
21836 | module.debug('Disabling all callbacks temporarily'); |
|
21837 | disabled = true; |
|
21838 | }, |
|
21839 | ||
21840 | should: { |
|
21841 | trackChanges: function() { |
|
21842 | if(methodInvoked) { |
|
21843 | module.debug('One time query, no need to bind events'); |
|
21844 | return false; |
|
21845 | } |
|
21846 | module.debug('Callbacks being attached'); |
|
21847 | return true; |
|
21848 | } |
|
21849 | }, |
|
21850 | ||
21851 | setup: { |
|
21852 | cache: function() { |
|
21853 | module.cache = { |
|
21854 | occurred : {}, |
|
21855 | screen : {}, |
|
21856 | element : {}, |
|
21857 | }; |
|
21858 | }, |
|
21859 | image: function() { |
|
21860 | var |
|
21861 | src = $module.data(metadata.src) |
|
21862 | ; |
|
21863 | if(src) { |
|
21864 | module.verbose('Lazy loading image', src); |
|
21865 | settings.once = true; |
|
21866 | settings.observeChanges = false; |
|
21867 | ||
21868 | // show when top visible |
|
21869 | settings.onOnScreen = function() { |
|
21870 | module.debug('Image on screen', element); |
|
21871 | module.precache(src, function() { |
|
21872 | module.set.image(src, function() { |
|
21873 | loadedCount++; |
|
21874 | if(loadedCount == moduleCount) { |
|
21875 | settings.onAllLoaded.call(this); |
|
21876 | } |
|
21877 | settings.onLoad.call(this); |
|
21878 | }); |
|
21879 | }); |
|
21880 | }; |
|
21881 | } |
|
21882 | }, |
|
21883 | fixed: function() { |
|
21884 | module.debug('Setting up fixed'); |
|
21885 | settings.once = false; |
|
21886 | settings.observeChanges = false; |
|
21887 | settings.initialCheck = true; |
|
21888 | settings.refreshOnLoad = true; |
|
21889 | if(!parameters.transition) { |
|
21890 | settings.transition = false; |
|
21891 | } |
|
21892 | module.create.placeholder(); |
|
21893 | module.debug('Added placeholder', $placeholder); |
|
21894 | settings.onTopPassed = function() { |
|
21895 | module.debug('Element passed, adding fixed position', $module); |
|
21896 | module.show.placeholder(); |
|
21897 | module.set.fixed(); |
|
21898 | if(settings.transition) { |
|
21899 | if($.fn.transition !== undefined) { |
|
21900 | $module.transition(settings.transition, settings.duration); |
|
21901 | } |
|
21902 | } |
|
21903 | }; |
|
21904 | settings.onTopPassedReverse = function() { |
|
21905 | module.debug('Element returned to position, removing fixed', $module); |
|
21906 | module.hide.placeholder(); |
|
21907 | module.remove.fixed(); |
|
21908 | }; |
|
21909 | } |
|
21910 | }, |
|
21911 | ||
21912 | create: { |
|
21913 | placeholder: function() { |
|
21914 | module.verbose('Creating fixed position placeholder'); |
|
21915 | $placeholder = $module |
|
21916 | .clone(false) |
|
21917 | .css('display', 'none') |
|
21918 | .addClass(className.placeholder) |
|
21919 | .insertAfter($module) |
|
21920 | ; |
|
21921 | } |
|
21922 | }, |
|
21923 | ||
21924 | show: { |
|
21925 | placeholder: function() { |
|
21926 | module.verbose('Showing placeholder'); |
|
21927 | $placeholder |
|
21928 | .css('display', 'block') |
|
21929 | .css('visibility', 'hidden') |
|
21930 | ; |
|
21931 | } |
|
21932 | }, |
|
21933 | hide: { |
|
21934 | placeholder: function() { |
|
21935 | module.verbose('Hiding placeholder'); |
|
21936 | $placeholder |
|
21937 | .css('display', 'none') |
|
21938 | .css('visibility', '') |
|
21939 | ; |
|
21940 | } |
|
21941 | }, |
|
21942 | ||
21943 | set: { |
|
21944 | fixed: function() { |
|
21945 | module.verbose('Setting element to fixed position'); |
|
21946 | $module |
|
21947 | .addClass(className.fixed) |
|
21948 | .css({ |
|
21949 | position : 'fixed', |
|
21950 | top : settings.offset + 'px', |
|
21951 | left : 'auto', |
|
21952 | zIndex : settings.zIndex |
|
21953 | }) |
|
21954 | ; |
|
21955 | settings.onFixed.call(element); |
|
21956 | }, |
|
21957 | image: function(src, callback) { |
|
21958 | $module |
|
21959 | .attr('src', src) |
|
21960 | ; |
|
21961 | if(settings.transition) { |
|
21962 | if( $.fn.transition !== undefined) { |
|
21963 | if($module.hasClass(className.visible)) { |
|
21964 | module.debug('Transition already occurred on this image, skipping animation'); |
|
21965 | return; |
|
21966 | } |
|
21967 | $module.transition(settings.transition, settings.duration, callback); |
|
21968 | } |
|
21969 | else { |
|
21970 | $module.fadeIn(settings.duration, callback); |
|
21971 | } |
|
21972 | } |
|
21973 | else { |
|
21974 | $module.show(); |
|
21975 | } |
|
21976 | } |
|
21977 | }, |
|
21978 | ||
21979 | is: { |
|
21980 | onScreen: function() { |
|
21981 | var |
|
21982 | calculations = module.get.elementCalculations() |
|
21983 | ; |
|
21984 | return calculations.onScreen; |
|
21985 | }, |
|
21986 | offScreen: function() { |
|
21987 | var |
|
21988 | calculations = module.get.elementCalculations() |
|
21989 | ; |
|
21990 | return calculations.offScreen; |
|
21991 | }, |
|
21992 | visible: function() { |
|
21993 | if(module.cache && module.cache.element) { |
|
21994 | return !(module.cache.element.width === 0 && module.cache.element.offset.top === 0); |
|
21995 | } |
|
21996 | return false; |
|
21997 | }, |
|
21998 | verticallyScrollableContext: function() { |
|
21999 | var |
|
22000 | overflowY = ($context.get(0) !== window) |
|
22001 | ? $context.css('overflow-y') |
|
22002 | : false |
|
22003 | ; |
|
22004 | return (overflowY == 'auto' || overflowY == 'scroll'); |
|
22005 | }, |
|
22006 | horizontallyScrollableContext: function() { |
|
22007 | var |
|
22008 | overflowX = ($context.get(0) !== window) |
|
22009 | ? $context.css('overflow-x') |
|
22010 | : false |
|
22011 | ; |
|
22012 | return (overflowX == 'auto' || overflowX == 'scroll'); |
|
22013 | } |
|
22014 | }, |
|
22015 | ||
22016 | refresh: function() { |
|
22017 | module.debug('Refreshing constants (width/height)'); |
|
22018 | if(settings.type == 'fixed') { |
|
22019 | module.resetFixed(); |
|
22020 | } |
|
22021 | module.reset(); |
|
22022 | module.save.position(); |
|
22023 | if(settings.checkOnRefresh) { |
|
22024 | module.checkVisibility(); |
|
22025 | } |
|
22026 | settings.onRefresh.call(element); |
|
22027 | }, |
|
22028 | ||
22029 | resetFixed: function () { |
|
22030 | module.remove.fixed(); |
|
22031 | module.remove.occurred(); |
|
22032 | }, |
|
22033 | ||
22034 | reset: function() { |
|
22035 | module.verbose('Resetting all cached values'); |
|
22036 | if( $.isPlainObject(module.cache) ) { |
|
22037 | module.cache.screen = {}; |
|
22038 | module.cache.element = {}; |
|
22039 | } |
|
22040 | }, |
|
22041 | ||
22042 | checkVisibility: function(scroll) { |
|
22043 | module.verbose('Checking visibility of element', module.cache.element); |
|
22044 | ||
22045 | if( !disabled && module.is.visible() ) { |
|
22046 | ||
22047 | // save scroll position |
|
22048 | module.save.scroll(scroll); |
|
22049 | ||
22050 | // update calculations derived from scroll |
|
22051 | module.save.calculations(); |
|
22052 | ||
22053 | // percentage |
|
22054 | module.passed(); |
|
22055 | ||
22056 | // reverse (must be first) |
|
22057 | module.passingReverse(); |
|
22058 | module.topVisibleReverse(); |
|
22059 | module.bottomVisibleReverse(); |
|
22060 | module.topPassedReverse(); |
|
22061 | module.bottomPassedReverse(); |
|
22062 | ||
22063 | // one time |
|
22064 | module.onScreen(); |
|
22065 | module.offScreen(); |
|
22066 | module.passing(); |
|
22067 | module.topVisible(); |
|
22068 | module.bottomVisible(); |
|
22069 | module.topPassed(); |
|
22070 | module.bottomPassed(); |
|
22071 | ||
22072 | // on update callback |
|
22073 | if(settings.onUpdate) { |
|
22074 | settings.onUpdate.call(element, module.get.elementCalculations()); |
|
22075 | } |
|
22076 | } |
|
22077 | }, |
|
22078 | ||
22079 | passed: function(amount, newCallback) { |
|
22080 | var |
|
22081 | calculations = module.get.elementCalculations(), |
|
22082 | amountInPixels |
|
22083 | ; |
|
22084 | // assign callback |
|
22085 | if(amount && newCallback) { |
|
22086 | settings.onPassed[amount] = newCallback; |
|
22087 | } |
|
22088 | else if(amount !== undefined) { |
|
22089 | return (module.get.pixelsPassed(amount) > calculations.pixelsPassed); |
|
22090 | } |
|
22091 | else if(calculations.passing) { |
|
22092 | $.each(settings.onPassed, function(amount, callback) { |
|
22093 | if(calculations.bottomVisible || calculations.pixelsPassed > module.get.pixelsPassed(amount)) { |
|
22094 | module.execute(callback, amount); |
|
22095 | } |
|
22096 | else if(!settings.once) { |
|
22097 | module.remove.occurred(callback); |
|
22098 | } |
|
22099 | }); |
|
22100 | } |
|
22101 | }, |
|
22102 | ||
22103 | onScreen: function(newCallback) { |
|
22104 | var |
|
22105 | calculations = module.get.elementCalculations(), |
|
22106 | callback = newCallback || settings.onOnScreen, |
|
22107 | callbackName = 'onScreen' |
|
22108 | ; |
|
22109 | if(newCallback) { |
|
22110 | module.debug('Adding callback for onScreen', newCallback); |
|
22111 | settings.onOnScreen = newCallback; |
|
22112 | } |
|
22113 | if(calculations.onScreen) { |
|
22114 | module.execute(callback, callbackName); |
|
22115 | } |
|
22116 | else if(!settings.once) { |
|
22117 | module.remove.occurred(callbackName); |
|
22118 | } |
|
22119 | if(newCallback !== undefined) { |
|
22120 | return calculations.onOnScreen; |
|
22121 | } |
|
22122 | }, |
|
22123 | ||
22124 | offScreen: function(newCallback) { |
|
22125 | var |
|
22126 | calculations = module.get.elementCalculations(), |
|
22127 | callback = newCallback || settings.onOffScreen, |
|
22128 | callbackName = 'offScreen' |
|
22129 | ; |
|
22130 | if(newCallback) { |
|
22131 | module.debug('Adding callback for offScreen', newCallback); |
|
22132 | settings.onOffScreen = newCallback; |
|
22133 | } |
|
22134 | if(calculations.offScreen) { |
|
22135 | module.execute(callback, callbackName); |
|
22136 | } |
|
22137 | else if(!settings.once) { |
|
22138 | module.remove.occurred(callbackName); |
|
22139 | } |
|
22140 | if(newCallback !== undefined) { |
|
22141 | return calculations.onOffScreen; |
|
22142 | } |
|
22143 | }, |
|
22144 | ||
22145 | passing: function(newCallback) { |
|
22146 | var |
|
22147 | calculations = module.get.elementCalculations(), |
|
22148 | callback = newCallback || settings.onPassing, |
|
22149 | callbackName = 'passing' |
|
22150 | ; |
|
22151 | if(newCallback) { |
|
22152 | module.debug('Adding callback for passing', newCallback); |
|
22153 | settings.onPassing = newCallback; |
|
22154 | } |
|
22155 | if(calculations.passing) { |
|
22156 | module.execute(callback, callbackName); |
|
22157 | } |
|
22158 | else if(!settings.once) { |
|
22159 | module.remove.occurred(callbackName); |
|
22160 | } |
|
22161 | if(newCallback !== undefined) { |
|
22162 | return calculations.passing; |
|
22163 | } |
|
22164 | }, |
|
22165 | ||
22166 | ||
22167 | topVisible: function(newCallback) { |
|
22168 | var |
|
22169 | calculations = module.get.elementCalculations(), |
|
22170 | callback = newCallback || settings.onTopVisible, |
|
22171 | callbackName = 'topVisible' |
|
22172 | ; |
|
22173 | if(newCallback) { |
|
22174 | module.debug('Adding callback for top visible', newCallback); |
|
22175 | settings.onTopVisible = newCallback; |
|
22176 | } |
|
22177 | if(calculations.topVisible) { |
|
22178 | module.execute(callback, callbackName); |
|
22179 | } |
|
22180 | else if(!settings.once) { |
|
22181 | module.remove.occurred(callbackName); |
|
22182 | } |
|
22183 | if(newCallback === undefined) { |
|
22184 | return calculations.topVisible; |
|
22185 | } |
|
22186 | }, |
|
22187 | ||
22188 | bottomVisible: function(newCallback) { |
|
22189 | var |
|
22190 | calculations = module.get.elementCalculations(), |
|
22191 | callback = newCallback || settings.onBottomVisible, |
|
22192 | callbackName = 'bottomVisible' |
|
22193 | ; |
|
22194 | if(newCallback) { |
|
22195 | module.debug('Adding callback for bottom visible', newCallback); |
|
22196 | settings.onBottomVisible = newCallback; |
|
22197 | } |
|
22198 | if(calculations.bottomVisible) { |
|
22199 | module.execute(callback, callbackName); |
|
22200 | } |
|
22201 | else if(!settings.once) { |
|
22202 | module.remove.occurred(callbackName); |
|
22203 | } |
|
22204 | if(newCallback === undefined) { |
|
22205 | return calculations.bottomVisible; |
|
22206 | } |
|
22207 | }, |
|
22208 | ||
22209 | topPassed: function(newCallback) { |
|
22210 | var |
|
22211 | calculations = module.get.elementCalculations(), |
|
22212 | callback = newCallback || settings.onTopPassed, |
|
22213 | callbackName = 'topPassed' |
|
22214 | ; |
|
22215 | if(newCallback) { |
|
22216 | module.debug('Adding callback for top passed', newCallback); |
|
22217 | settings.onTopPassed = newCallback; |
|
22218 | } |
|
22219 | if(calculations.topPassed) { |
|
22220 | module.execute(callback, callbackName); |
|
22221 | } |
|
22222 | else if(!settings.once) { |
|
22223 | module.remove.occurred(callbackName); |
|
22224 | } |
|
22225 | if(newCallback === undefined) { |
|
22226 | return calculations.topPassed; |
|
22227 | } |
|
22228 | }, |
|
22229 | ||
22230 | bottomPassed: function(newCallback) { |
|
22231 | var |
|
22232 | calculations = module.get.elementCalculations(), |
|
22233 | callback = newCallback || settings.onBottomPassed, |
|
22234 | callbackName = 'bottomPassed' |
|
22235 | ; |
|
22236 | if(newCallback) { |
|
22237 | module.debug('Adding callback for bottom passed', newCallback); |
|
22238 | settings.onBottomPassed = newCallback; |
|
22239 | } |
|
22240 | if(calculations.bottomPassed) { |
|
22241 | module.execute(callback, callbackName); |
|
22242 | } |
|
22243 | else if(!settings.once) { |
|
22244 | module.remove.occurred(callbackName); |
|
22245 | } |
|
22246 | if(newCallback === undefined) { |
|
22247 | return calculations.bottomPassed; |
|
22248 | } |
|
22249 | }, |
|
22250 | ||
22251 | passingReverse: function(newCallback) { |
|
22252 | var |
|
22253 | calculations = module.get.elementCalculations(), |
|
22254 | callback = newCallback || settings.onPassingReverse, |
|
22255 | callbackName = 'passingReverse' |
|
22256 | ; |
|
22257 | if(newCallback) { |
|
22258 | module.debug('Adding callback for passing reverse', newCallback); |
|
22259 | settings.onPassingReverse = newCallback; |
|
22260 | } |
|
22261 | if(!calculations.passing) { |
|
22262 | if(module.get.occurred('passing')) { |
|
22263 | module.execute(callback, callbackName); |
|
22264 | } |
|
22265 | } |
|
22266 | else if(!settings.once) { |
|
22267 | module.remove.occurred(callbackName); |
|
22268 | } |
|
22269 | if(newCallback !== undefined) { |
|
22270 | return !calculations.passing; |
|
22271 | } |
|
22272 | }, |
|
22273 | ||
22274 | ||
22275 | topVisibleReverse: function(newCallback) { |
|
22276 | var |
|
22277 | calculations = module.get.elementCalculations(), |
|
22278 | callback = newCallback || settings.onTopVisibleReverse, |
|
22279 | callbackName = 'topVisibleReverse' |
|
22280 | ; |
|
22281 | if(newCallback) { |
|
22282 | module.debug('Adding callback for top visible reverse', newCallback); |
|
22283 | settings.onTopVisibleReverse = newCallback; |
|
22284 | } |
|
22285 | if(!calculations.topVisible) { |
|
22286 | if(module.get.occurred('topVisible')) { |
|
22287 | module.execute(callback, callbackName); |
|
22288 | } |
|
22289 | } |
|
22290 | else if(!settings.once) { |
|
22291 | module.remove.occurred(callbackName); |
|
22292 | } |
|
22293 | if(newCallback === undefined) { |
|
22294 | return !calculations.topVisible; |
|
22295 | } |
|
22296 | }, |
|
22297 | ||
22298 | bottomVisibleReverse: function(newCallback) { |
|
22299 | var |
|
22300 | calculations = module.get.elementCalculations(), |
|
22301 | callback = newCallback || settings.onBottomVisibleReverse, |
|
22302 | callbackName = 'bottomVisibleReverse' |
|
22303 | ; |
|
22304 | if(newCallback) { |
|
22305 | module.debug('Adding callback for bottom visible reverse', newCallback); |
|
22306 | settings.onBottomVisibleReverse = newCallback; |
|
22307 | } |
|
22308 | if(!calculations.bottomVisible) { |
|
22309 | if(module.get.occurred('bottomVisible')) { |
|
22310 | module.execute(callback, callbackName); |
|
22311 | } |
|
22312 | } |
|
22313 | else if(!settings.once) { |
|
22314 | module.remove.occurred(callbackName); |
|
22315 | } |
|
22316 | if(newCallback === undefined) { |
|
22317 | return !calculations.bottomVisible; |
|
22318 | } |
|
22319 | }, |
|
22320 | ||
22321 | topPassedReverse: function(newCallback) { |
|
22322 | var |
|
22323 | calculations = module.get.elementCalculations(), |
|
22324 | callback = newCallback || settings.onTopPassedReverse, |
|
22325 | callbackName = 'topPassedReverse' |
|
22326 | ; |
|
22327 | if(newCallback) { |
|
22328 | module.debug('Adding callback for top passed reverse', newCallback); |
|
22329 | settings.onTopPassedReverse = newCallback; |
|
22330 | } |
|
22331 | if(!calculations.topPassed) { |
|
22332 | if(module.get.occurred('topPassed')) { |
|
22333 | module.execute(callback, callbackName); |
|
22334 | } |
|
22335 | } |
|
22336 | else if(!settings.once) { |
|
22337 | module.remove.occurred(callbackName); |
|
22338 | } |
|
22339 | if(newCallback === undefined) { |
|
22340 | return !calculations.onTopPassed; |
|
22341 | } |
|
22342 | }, |
|
22343 | ||
22344 | bottomPassedReverse: function(newCallback) { |
|
22345 | var |
|
22346 | calculations = module.get.elementCalculations(), |
|
22347 | callback = newCallback || settings.onBottomPassedReverse, |
|
22348 | callbackName = 'bottomPassedReverse' |
|
22349 | ; |
|
22350 | if(newCallback) { |
|
22351 | module.debug('Adding callback for bottom passed reverse', newCallback); |
|
22352 | settings.onBottomPassedReverse = newCallback; |
|
22353 | } |
|
22354 | if(!calculations.bottomPassed) { |
|
22355 | if(module.get.occurred('bottomPassed')) { |
|
22356 | module.execute(callback, callbackName); |
|
22357 | } |
|
22358 | } |
|
22359 | else if(!settings.once) { |
|
22360 | module.remove.occurred(callbackName); |
|
22361 | } |
|
22362 | if(newCallback === undefined) { |
|
22363 | return !calculations.bottomPassed; |
|
22364 | } |
|
22365 | }, |
|
22366 | ||
22367 | execute: function(callback, callbackName) { |
|
22368 | var |
|
22369 | calculations = module.get.elementCalculations(), |
|
22370 | screen = module.get.screenCalculations() |
|
22371 | ; |
|
22372 | callback = callback || false; |
|
22373 | if(callback) { |
|
22374 | if(settings.continuous) { |
|
22375 | module.debug('Callback being called continuously', callbackName, calculations); |
|
22376 | callback.call(element, calculations, screen); |
|
22377 | } |
|
22378 | else if(!module.get.occurred(callbackName)) { |
|
22379 | module.debug('Conditions met', callbackName, calculations); |
|
22380 | callback.call(element, calculations, screen); |
|
22381 | } |
|
22382 | } |
|
22383 | module.save.occurred(callbackName); |
|
22384 | }, |
|
22385 | ||
22386 | remove: { |
|
22387 | fixed: function() { |
|
22388 | module.debug('Removing fixed position'); |
|
22389 | $module |
|
22390 | .removeClass(className.fixed) |
|
22391 | .css({ |
|
22392 | position : '', |
|
22393 | top : '', |
|
22394 | left : '', |
|
22395 | zIndex : '' |
|
22396 | }) |
|
22397 | ; |
|
22398 | settings.onUnfixed.call(element); |
|
22399 | }, |
|
22400 | placeholder: function() { |
|
22401 | module.debug('Removing placeholder content'); |
|
22402 | if($placeholder) { |
|
22403 | $placeholder.remove(); |
|
22404 | } |
|
22405 | }, |
|
22406 | occurred: function(callback) { |
|
22407 | if(callback) { |
|
22408 | var |
|
22409 | occurred = module.cache.occurred |
|
22410 | ; |
|
22411 | if(occurred[callback] !== undefined && occurred[callback] === true) { |
|
22412 | module.debug('Callback can now be called again', callback); |
|
22413 | module.cache.occurred[callback] = false; |
|
22414 | } |
|
22415 | } |
|
22416 | else { |
|
22417 | module.cache.occurred = {}; |
|
22418 | } |
|
22419 | } |
|
22420 | }, |
|
22421 | ||
22422 | save: { |
|
22423 | calculations: function() { |
|
22424 | module.verbose('Saving all calculations necessary to determine positioning'); |
|
22425 | module.save.direction(); |
|
22426 | module.save.screenCalculations(); |
|
22427 | module.save.elementCalculations(); |
|
22428 | }, |
|
22429 | occurred: function(callback) { |
|
22430 | if(callback) { |
|
22431 | if(module.cache.occurred[callback] === undefined || (module.cache.occurred[callback] !== true)) { |
|
22432 | module.verbose('Saving callback occurred', callback); |
|
22433 | module.cache.occurred[callback] = true; |
|
22434 | } |
|
22435 | } |
|
22436 | }, |
|
22437 | scroll: function(scrollPosition) { |
|
22438 | scrollPosition = scrollPosition + settings.offset || $context.scrollTop() + settings.offset; |
|
22439 | module.cache.scroll = scrollPosition; |
|
22440 | }, |
|
22441 | direction: function() { |
|
22442 | var |
|
22443 | scroll = module.get.scroll(), |
|
22444 | lastScroll = module.get.lastScroll(), |
|
22445 | direction |
|
22446 | ; |
|
22447 | if(scroll > lastScroll && lastScroll) { |
|
22448 | direction = 'down'; |
|
22449 | } |
|
22450 | else if(scroll < lastScroll && lastScroll) { |
|
22451 | direction = 'up'; |
|
22452 | } |
|
22453 | else { |
|
22454 | direction = 'static'; |
|
22455 | } |
|
22456 | module.cache.direction = direction; |
|
22457 | return module.cache.direction; |
|
22458 | }, |
|
22459 | elementPosition: function() { |
|
22460 | var |
|
22461 | element = module.cache.element, |
|
22462 | screen = module.get.screenSize() |
|
22463 | ; |
|
22464 | module.verbose('Saving element position'); |
|
22465 | // (quicker than $.extend) |
|
22466 | element.fits = (element.height < screen.height); |
|
22467 | element.offset = $module.offset(); |
|
22468 | element.width = $module.outerWidth(); |
|
22469 | element.height = $module.outerHeight(); |
|
22470 | // compensate for scroll in context |
|
22471 | if(module.is.verticallyScrollableContext()) { |
|
22472 | element.offset.top += $context.scrollTop() - $context.offset().top; |
|
22473 | } |
|
22474 | if(module.is.horizontallyScrollableContext()) { |
|
22475 | element.offset.left += $context.scrollLeft - $context.offset().left; |
|
22476 | } |
|
22477 | // store |
|
22478 | module.cache.element = element; |
|
22479 | return element; |
|
22480 | }, |
|
22481 | elementCalculations: function() { |
|
22482 | var |
|
22483 | screen = module.get.screenCalculations(), |
|
22484 | element = module.get.elementPosition() |
|
22485 | ; |
|
22486 | // offset |
|
22487 | if(settings.includeMargin) { |
|
22488 | element.margin = {}; |
|
22489 | element.margin.top = parseInt($module.css('margin-top'), 10); |
|
22490 | element.margin.bottom = parseInt($module.css('margin-bottom'), 10); |
|
22491 | element.top = element.offset.top - element.margin.top; |
|
22492 | element.bottom = element.offset.top + element.height + element.margin.bottom; |
|
22493 | } |
|
22494 | else { |
|
22495 | element.top = element.offset.top; |
|
22496 | element.bottom = element.offset.top + element.height; |
|
22497 | } |
|
22498 | ||
22499 | // visibility |
|
22500 | element.topPassed = (screen.top >= element.top); |
|
22501 | element.bottomPassed = (screen.top >= element.bottom); |
|
22502 | element.topVisible = (screen.bottom >= element.top) && !element.bottomPassed; |
|
22503 | element.bottomVisible = (screen.bottom >= element.bottom) && !element.topPassed; |
|
22504 | element.pixelsPassed = 0; |
|
22505 | element.percentagePassed = 0; |
|
22506 | ||
22507 | // meta calculations |
|
22508 | element.onScreen = (element.topVisible && !element.bottomPassed); |
|
22509 | element.passing = (element.topPassed && !element.bottomPassed); |
|
22510 | element.offScreen = (!element.onScreen); |
|
22511 | ||
22512 | // passing calculations |
|
22513 | if(element.passing) { |
|
22514 | element.pixelsPassed = (screen.top - element.top); |
|
22515 | element.percentagePassed = (screen.top - element.top) / element.height; |
|
22516 | } |
|
22517 | module.cache.element = element; |
|
22518 | module.verbose('Updated element calculations', element); |
|
22519 | return element; |
|
22520 | }, |
|
22521 | screenCalculations: function() { |
|
22522 | var |
|
22523 | scroll = module.get.scroll() |
|
22524 | ; |
|
22525 | module.save.direction(); |
|
22526 | module.cache.screen.top = scroll; |
|
22527 | module.cache.screen.bottom = scroll + module.cache.screen.height; |
|
22528 | return module.cache.screen; |
|
22529 | }, |
|
22530 | screenSize: function() { |
|
22531 | module.verbose('Saving window position'); |
|
22532 | module.cache.screen = { |
|
22533 | height: $context.height() |
|
22534 | }; |
|
22535 | }, |
|
22536 | position: function() { |
|
22537 | module.save.screenSize(); |
|
22538 | module.save.elementPosition(); |
|
22539 | } |
|
22540 | }, |
|
22541 | ||
22542 | get: { |
|
22543 | pixelsPassed: function(amount) { |
|
22544 | var |
|
22545 | element = module.get.elementCalculations() |
|
22546 | ; |
|
22547 | if(amount.search('%') > -1) { |
|
22548 | return ( element.height * (parseInt(amount, 10) / 100) ); |
|
22549 | } |
|
22550 | return parseInt(amount, 10); |
|
22551 | }, |
|
22552 | occurred: function(callback) { |
|
22553 | return (module.cache.occurred !== undefined) |
|
22554 | ? module.cache.occurred[callback] || false |
|
22555 | : false |
|
22556 | ; |
|
22557 | }, |
|
22558 | direction: function() { |
|
22559 | if(module.cache.direction === undefined) { |
|
22560 | module.save.direction(); |
|
22561 | } |
|
22562 | return module.cache.direction; |
|
22563 | }, |
|
22564 | elementPosition: function() { |
|
22565 | if(module.cache.element === undefined) { |
|
22566 | module.save.elementPosition(); |
|
22567 | } |
|
22568 | return module.cache.element; |
|
22569 | }, |
|
22570 | elementCalculations: function() { |
|
22571 | if(module.cache.element === undefined) { |
|
22572 | module.save.elementCalculations(); |
|
22573 | } |
|
22574 | return module.cache.element; |
|
22575 | }, |
|
22576 | screenCalculations: function() { |
|
22577 | if(module.cache.screen === undefined) { |
|
22578 | module.save.screenCalculations(); |
|
22579 | } |
|
22580 | return module.cache.screen; |
|
22581 | }, |
|
22582 | screenSize: function() { |
|
22583 | if(module.cache.screen === undefined) { |
|
22584 | module.save.screenSize(); |
|
22585 | } |
|
22586 | return module.cache.screen; |
|
22587 | }, |
|
22588 | scroll: function() { |
|
22589 | if(module.cache.scroll === undefined) { |
|
22590 | module.save.scroll(); |
|
22591 | } |
|
22592 | return module.cache.scroll; |
|
22593 | }, |
|
22594 | lastScroll: function() { |
|
22595 | if(module.cache.screen === undefined) { |
|
22596 | module.debug('First scroll event, no last scroll could be found'); |
|
22597 | return false; |
|
22598 | } |
|
22599 | return module.cache.screen.top; |
|
22600 | } |
|
22601 | }, |
|
22602 | ||
22603 | setting: function(name, value) { |
|
22604 | if( $.isPlainObject(name) ) { |
|
22605 | $.extend(true, settings, name); |
|
22606 | } |
|
22607 | else if(value !== undefined) { |
|
22608 | settings[name] = value; |
|
22609 | } |
|
22610 | else { |
|
22611 | return settings[name]; |
|
22612 | } |
|
22613 | }, |
|
22614 | internal: function(name, value) { |
|
22615 | if( $.isPlainObject(name) ) { |
|
22616 | $.extend(true, module, name); |
|
22617 | } |
|
22618 | else if(value !== undefined) { |
|
22619 | module[name] = value; |
|
22620 | } |
|
22621 | else { |
|
22622 | return module[name]; |
|
22623 | } |
|
22624 | }, |
|
22625 | debug: function() { |
|
22626 | if(!settings.silent && settings.debug) { |
|
22627 | if(settings.performance) { |
|
22628 | module.performance.log(arguments); |
|
22629 | } |
|
22630 | else { |
|
22631 | module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
|
22632 | module.debug.apply(console, arguments); |
|
22633 | } |
|
22634 | } |
|
22635 | }, |
|
22636 | verbose: function() { |
|
22637 | if(!settings.silent && settings.verbose && settings.debug) { |
|
22638 | if(settings.performance) { |
|
22639 | module.performance.log(arguments); |
|
22640 | } |
|
22641 | else { |
|
22642 | module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
|
22643 | module.verbose.apply(console, arguments); |
|
22644 | } |
|
22645 | } |
|
22646 | }, |
|
22647 | error: function() { |
|
22648 | if(!settings.silent) { |
|
22649 | module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); |
|
22650 | module.error.apply(console, arguments); |
|
22651 | } |
|
22652 | }, |
|
22653 | performance: { |
|
22654 | log: function(message) { |
|
22655 | var |
|
22656 | currentTime, |
|
22657 | executionTime, |
|
22658 | previousTime |
|
22659 | ; |
|
22660 | if(settings.performance) { |
|
22661 | currentTime = new Date().getTime(); |
|
22662 | previousTime = time || currentTime; |
|
22663 | executionTime = currentTime - previousTime; |
|
22664 | time = currentTime; |
|
22665 | performance.push({ |
|
22666 | 'Name' : message[0], |
|
22667 | 'Arguments' : [].slice.call(message, 1) || '', |
|
22668 | 'Element' : element, |
|
22669 | 'Execution Time' : executionTime |
|
22670 | }); |
|
22671 | } |
|
22672 | clearTimeout(module.performance.timer); |
|
22673 | module.performance.timer = setTimeout(module.performance.display, 500); |
|
22674 | }, |
|
22675 | display: function() { |
|
22676 | var |
|
22677 | title = settings.name + ':', |
|
22678 | totalTime = 0 |
|
22679 | ; |
|
22680 | time = false; |
|
22681 | clearTimeout(module.performance.timer); |
|
22682 | $.each(performance, function(index, data) { |
|
22683 | totalTime += data['Execution Time']; |
|
22684 | }); |
|
22685 | title += ' ' + totalTime + 'ms'; |
|
22686 | if(moduleSelector) { |
|
22687 | title += ' \'' + moduleSelector + '\''; |
|
22688 | } |
|
22689 | if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { |
|
22690 | console.groupCollapsed(title); |
|
22691 | if(console.table) { |
|
22692 | console.table(performance); |
|
22693 | } |
|
22694 | else { |
|
22695 | $.each(performance, function(index, data) { |
|
22696 | console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); |
|
22697 | }); |
|
22698 | } |
|
22699 | console.groupEnd(); |
|
22700 | } |
|
22701 | performance = []; |
|
22702 | } |
|
22703 | }, |
|
22704 | invoke: function(query, passedArguments, context) { |
|
22705 | var |
|
22706 | object = instance, |
|
22707 | maxDepth, |
|
22708 | found, |
|
22709 | response |
|
22710 | ; |
|
22711 | passedArguments = passedArguments || queryArguments; |
|
22712 | context = element || context; |
|
22713 | if(typeof query == 'string' && object !== undefined) { |
|
22714 | query = query.split(/[\. ]/); |
|
22715 | maxDepth = query.length - 1; |
|
22716 | $.each(query, function(depth, value) { |
|
22717 | var camelCaseValue = (depth != maxDepth) |
|
22718 | ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) |
|
22719 | : query |
|
22720 | ; |
|
22721 | if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { |
|
22722 | object = object[camelCaseValue]; |
|
22723 | } |
|
22724 | else if( object[camelCaseValue] !== undefined ) { |
|
22725 | found = object[camelCaseValue]; |
|
22726 | return false; |
|
22727 | } |
|
22728 | else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { |
|
22729 | object = object[value]; |
|
22730 | } |
|
22731 | else if( object[value] !== undefined ) { |
|
22732 | found = object[value]; |
|
22733 | return false; |
|
22734 | } |
|
22735 | else { |
|
22736 | module.error(error.method, query); |
|
22737 | return false; |
|
22738 | } |
|
22739 | }); |
|
22740 | } |
|
22741 | if ( $.isFunction( found ) ) { |
|
22742 | response = found.apply(context, passedArguments); |
|
22743 | } |
|
22744 | else if(found !== undefined) { |
|
22745 | response = found; |
|
22746 | } |
|
22747 | if($.isArray(returnedValue)) { |
|
22748 | returnedValue.push(response); |
|
22749 | } |
|
22750 | else if(returnedValue !== undefined) { |
|
22751 | returnedValue = [returnedValue, response]; |
|
22752 | } |
|
22753 | else if(response !== undefined) { |
|
22754 | returnedValue = response; |
|
22755 | } |
|
22756 | return found; |
|
22757 | } |
|
22758 | }; |
|
22759 | ||
22760 | if(methodInvoked) { |
|
22761 | if(instance === undefined) { |
|
22762 | module.initialize(); |
|
22763 | } |
|
22764 | instance.save.scroll(); |
|
22765 | instance.save.calculations(); |
|
22766 | module.invoke(query); |
|
22767 | } |
|
22768 | else { |
|
22769 | if(instance !== undefined) { |
|
22770 | instance.invoke('destroy'); |
|
22771 | } |
|
22772 | module.initialize(); |
|
22773 | } |
|
22774 | }) |
|
22775 | ; |
|
22776 | ||
22777 | return (returnedValue !== undefined) |
|
22778 | ? returnedValue |
|
22779 | : this |
|
22780 | ; |
|
22781 | }; |
|
22782 | ||
22783 | $.fn.visibility.settings = { |
|
22784 | ||
22785 | name : 'Visibility', |
|
22786 | namespace : 'visibility', |
|
22787 | ||
22788 | debug : false, |
|
22789 | verbose : false, |
|
22790 | performance : true, |
|
22791 | ||
22792 | // whether to use mutation observers to follow changes |
|
22793 | observeChanges : true, |
|
22794 | ||
22795 | // check position immediately on init |
|
22796 | initialCheck : true, |
|
22797 | ||
22798 | // whether to refresh calculations after all page images load |
|
22799 | refreshOnLoad : true, |
|
22800 | ||
22801 | // whether to refresh calculations after page resize event |
|
22802 | refreshOnResize : true, |
|
22803 | ||
22804 | // should call callbacks on refresh event (resize, etc) |
|
22805 | checkOnRefresh : true, |
|
22806 | ||
22807 | // callback should only occur one time |
|
22808 | once : true, |
|
22809 | ||
22810 | // callback should fire continuously whe evaluates to true |
|
22811 | continuous : false, |
|
22812 | ||
22813 | // offset to use with scroll top |
|
22814 | offset : 0, |
|
22815 | ||
22816 | // whether to include margin in elements position |
|
22817 | includeMargin : false, |
|
22818 | ||
22819 | // scroll context for visibility checks |
|
22820 | context : window, |
|
22821 | ||
22822 | // visibility check delay in ms (defaults to animationFrame) |
|
22823 | throttle : false, |
|
22824 | ||
22825 | // special visibility type (image, fixed) |
|
22826 | type : false, |
|
22827 | ||
22828 | // z-index to use with visibility 'fixed' |
|
22829 | zIndex : '10', |
|
22830 | ||
22831 | // image only animation settings |
|
22832 | transition : 'fade in', |
|
22833 | duration : 1000, |
|
22834 | ||
22835 | // array of callbacks for percentage |
|
22836 | onPassed : {}, |
|
22837 | ||
22838 | // standard callbacks |
|
22839 | onOnScreen : false, |
|
22840 | onOffScreen : false, |
|
22841 | onPassing : false, |
|
22842 | onTopVisible : false, |
|
22843 | onBottomVisible : false, |
|
22844 | onTopPassed : false, |
|
22845 | onBottomPassed : false, |
|
22846 | ||
22847 | // reverse callbacks |
|
22848 | onPassingReverse : false, |
|
22849 | onTopVisibleReverse : false, |
|
22850 | onBottomVisibleReverse : false, |
|
22851 | onTopPassedReverse : false, |
|
22852 | onBottomPassedReverse : false, |
|
22853 | ||
22854 | // special callbacks for image |
|
22855 | onLoad : function() {}, |
|
22856 | onAllLoaded : function() {}, |
|
22857 | ||
22858 | // special callbacks for fixed position |
|
22859 | onFixed : function() {}, |
|
22860 | onUnfixed : function() {}, |
|
22861 | ||
22862 | // utility callbacks |
|
22863 | onUpdate : false, // disabled by default for performance |
|
22864 | onRefresh : function(){}, |
|
22865 | ||
22866 | metadata : { |
|
22867 | src: 'src' |
|
22868 | }, |
|
22869 | ||
22870 | className: { |
|
22871 | fixed : 'fixed', |
|
22872 | placeholder : 'placeholder', |
|
22873 | visible : 'visible' |
|
22874 | }, |
|
22875 | ||
22876 | error : { |
|
22877 | method : 'The method you called is not defined.', |
|
22878 | visible : 'Element is hidden, you must call refresh after element becomes visible' |
|
22879 | } |
|
22880 | ||
22881 | }; |
|
22882 | ||
22883 | })( jQuery, window, document ); |
|
22884 |
@@ 11-1311 (lines=1301) @@ | ||
8 | * |
|
9 | */ |
|
10 | ||
11 | ;(function ($, window, document, undefined) { |
|
12 | ||
13 | "use strict"; |
|
14 | ||
15 | window = (typeof window != 'undefined' && window.Math == Math) |
|
16 | ? window |
|
17 | : (typeof self != 'undefined' && self.Math == Math) |
|
18 | ? self |
|
19 | : Function('return this')() |
|
20 | ; |
|
21 | ||
22 | $.fn.visibility = function(parameters) { |
|
23 | var |
|
24 | $allModules = $(this), |
|
25 | moduleSelector = $allModules.selector || '', |
|
26 | ||
27 | time = new Date().getTime(), |
|
28 | performance = [], |
|
29 | ||
30 | query = arguments[0], |
|
31 | methodInvoked = (typeof query == 'string'), |
|
32 | queryArguments = [].slice.call(arguments, 1), |
|
33 | returnedValue, |
|
34 | ||
35 | moduleCount = $allModules.length, |
|
36 | loadedCount = 0 |
|
37 | ; |
|
38 | ||
39 | $allModules |
|
40 | .each(function() { |
|
41 | var |
|
42 | settings = ( $.isPlainObject(parameters) ) |
|
43 | ? $.extend(true, {}, $.fn.visibility.settings, parameters) |
|
44 | : $.extend({}, $.fn.visibility.settings), |
|
45 | ||
46 | className = settings.className, |
|
47 | namespace = settings.namespace, |
|
48 | error = settings.error, |
|
49 | metadata = settings.metadata, |
|
50 | ||
51 | eventNamespace = '.' + namespace, |
|
52 | moduleNamespace = 'module-' + namespace, |
|
53 | ||
54 | $window = $(window), |
|
55 | ||
56 | $module = $(this), |
|
57 | $context = $(settings.context), |
|
58 | ||
59 | $placeholder, |
|
60 | ||
61 | selector = $module.selector || '', |
|
62 | instance = $module.data(moduleNamespace), |
|
63 | ||
64 | requestAnimationFrame = window.requestAnimationFrame |
|
65 | || window.mozRequestAnimationFrame |
|
66 | || window.webkitRequestAnimationFrame |
|
67 | || window.msRequestAnimationFrame |
|
68 | || function(callback) { setTimeout(callback, 0); }, |
|
69 | ||
70 | element = this, |
|
71 | disabled = false, |
|
72 | ||
73 | contextObserver, |
|
74 | observer, |
|
75 | module |
|
76 | ; |
|
77 | ||
78 | module = { |
|
79 | ||
80 | initialize: function() { |
|
81 | module.debug('Initializing', settings); |
|
82 | ||
83 | module.setup.cache(); |
|
84 | ||
85 | if( module.should.trackChanges() ) { |
|
86 | ||
87 | if(settings.type == 'image') { |
|
88 | module.setup.image(); |
|
89 | } |
|
90 | if(settings.type == 'fixed') { |
|
91 | module.setup.fixed(); |
|
92 | } |
|
93 | ||
94 | if(settings.observeChanges) { |
|
95 | module.observeChanges(); |
|
96 | } |
|
97 | module.bind.events(); |
|
98 | } |
|
99 | ||
100 | module.save.position(); |
|
101 | if( !module.is.visible() ) { |
|
102 | module.error(error.visible, $module); |
|
103 | } |
|
104 | ||
105 | if(settings.initialCheck) { |
|
106 | module.checkVisibility(); |
|
107 | } |
|
108 | module.instantiate(); |
|
109 | }, |
|
110 | ||
111 | instantiate: function() { |
|
112 | module.debug('Storing instance', module); |
|
113 | $module |
|
114 | .data(moduleNamespace, module) |
|
115 | ; |
|
116 | instance = module; |
|
117 | }, |
|
118 | ||
119 | destroy: function() { |
|
120 | module.verbose('Destroying previous module'); |
|
121 | if(observer) { |
|
122 | observer.disconnect(); |
|
123 | } |
|
124 | if(contextObserver) { |
|
125 | contextObserver.disconnect(); |
|
126 | } |
|
127 | $window |
|
128 | .off('load' + eventNamespace, module.event.load) |
|
129 | .off('resize' + eventNamespace, module.event.resize) |
|
130 | ; |
|
131 | $context |
|
132 | .off('scroll' + eventNamespace, module.event.scroll) |
|
133 | .off('scrollchange' + eventNamespace, module.event.scrollchange) |
|
134 | ; |
|
135 | if(settings.type == 'fixed') { |
|
136 | module.resetFixed(); |
|
137 | module.remove.placeholder(); |
|
138 | } |
|
139 | $module |
|
140 | .off(eventNamespace) |
|
141 | .removeData(moduleNamespace) |
|
142 | ; |
|
143 | }, |
|
144 | ||
145 | observeChanges: function() { |
|
146 | if('MutationObserver' in window) { |
|
147 | contextObserver = new MutationObserver(module.event.contextChanged); |
|
148 | observer = new MutationObserver(module.event.changed); |
|
149 | contextObserver.observe(document, { |
|
150 | childList : true, |
|
151 | subtree : true |
|
152 | }); |
|
153 | observer.observe(element, { |
|
154 | childList : true, |
|
155 | subtree : true |
|
156 | }); |
|
157 | module.debug('Setting up mutation observer', observer); |
|
158 | } |
|
159 | }, |
|
160 | ||
161 | bind: { |
|
162 | events: function() { |
|
163 | module.verbose('Binding visibility events to scroll and resize'); |
|
164 | if(settings.refreshOnLoad) { |
|
165 | $window |
|
166 | .on('load' + eventNamespace, module.event.load) |
|
167 | ; |
|
168 | } |
|
169 | $window |
|
170 | .on('resize' + eventNamespace, module.event.resize) |
|
171 | ; |
|
172 | // pub/sub pattern |
|
173 | $context |
|
174 | .off('scroll' + eventNamespace) |
|
175 | .on('scroll' + eventNamespace, module.event.scroll) |
|
176 | .on('scrollchange' + eventNamespace, module.event.scrollchange) |
|
177 | ; |
|
178 | } |
|
179 | }, |
|
180 | ||
181 | event: { |
|
182 | changed: function(mutations) { |
|
183 | module.verbose('DOM tree modified, updating visibility calculations'); |
|
184 | module.timer = setTimeout(function() { |
|
185 | module.verbose('DOM tree modified, updating sticky menu'); |
|
186 | module.refresh(); |
|
187 | }, 100); |
|
188 | }, |
|
189 | contextChanged: function(mutations) { |
|
190 | [].forEach.call(mutations, function(mutation) { |
|
191 | if(mutation.removedNodes) { |
|
192 | [].forEach.call(mutation.removedNodes, function(node) { |
|
193 | if(node == element || $(node).find(element).length > 0) { |
|
194 | module.debug('Element removed from DOM, tearing down events'); |
|
195 | module.destroy(); |
|
196 | } |
|
197 | }); |
|
198 | } |
|
199 | }); |
|
200 | }, |
|
201 | resize: function() { |
|
202 | module.debug('Window resized'); |
|
203 | if(settings.refreshOnResize) { |
|
204 | requestAnimationFrame(module.refresh); |
|
205 | } |
|
206 | }, |
|
207 | load: function() { |
|
208 | module.debug('Page finished loading'); |
|
209 | requestAnimationFrame(module.refresh); |
|
210 | }, |
|
211 | // publishes scrollchange event on one scroll |
|
212 | scroll: function() { |
|
213 | if(settings.throttle) { |
|
214 | clearTimeout(module.timer); |
|
215 | module.timer = setTimeout(function() { |
|
216 | $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]); |
|
217 | }, settings.throttle); |
|
218 | } |
|
219 | else { |
|
220 | requestAnimationFrame(function() { |
|
221 | $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]); |
|
222 | }); |
|
223 | } |
|
224 | }, |
|
225 | // subscribes to scrollchange |
|
226 | scrollchange: function(event, scrollPosition) { |
|
227 | module.checkVisibility(scrollPosition); |
|
228 | }, |
|
229 | }, |
|
230 | ||
231 | precache: function(images, callback) { |
|
232 | if (!(images instanceof Array)) { |
|
233 | images = [images]; |
|
234 | } |
|
235 | var |
|
236 | imagesLength = images.length, |
|
237 | loadedCounter = 0, |
|
238 | cache = [], |
|
239 | cacheImage = document.createElement('img'), |
|
240 | handleLoad = function() { |
|
241 | loadedCounter++; |
|
242 | if (loadedCounter >= images.length) { |
|
243 | if ($.isFunction(callback)) { |
|
244 | callback(); |
|
245 | } |
|
246 | } |
|
247 | } |
|
248 | ; |
|
249 | while (imagesLength--) { |
|
250 | cacheImage = document.createElement('img'); |
|
251 | cacheImage.onload = handleLoad; |
|
252 | cacheImage.onerror = handleLoad; |
|
253 | cacheImage.src = images[imagesLength]; |
|
254 | cache.push(cacheImage); |
|
255 | } |
|
256 | }, |
|
257 | ||
258 | enableCallbacks: function() { |
|
259 | module.debug('Allowing callbacks to occur'); |
|
260 | disabled = false; |
|
261 | }, |
|
262 | ||
263 | disableCallbacks: function() { |
|
264 | module.debug('Disabling all callbacks temporarily'); |
|
265 | disabled = true; |
|
266 | }, |
|
267 | ||
268 | should: { |
|
269 | trackChanges: function() { |
|
270 | if(methodInvoked) { |
|
271 | module.debug('One time query, no need to bind events'); |
|
272 | return false; |
|
273 | } |
|
274 | module.debug('Callbacks being attached'); |
|
275 | return true; |
|
276 | } |
|
277 | }, |
|
278 | ||
279 | setup: { |
|
280 | cache: function() { |
|
281 | module.cache = { |
|
282 | occurred : {}, |
|
283 | screen : {}, |
|
284 | element : {}, |
|
285 | }; |
|
286 | }, |
|
287 | image: function() { |
|
288 | var |
|
289 | src = $module.data(metadata.src) |
|
290 | ; |
|
291 | if(src) { |
|
292 | module.verbose('Lazy loading image', src); |
|
293 | settings.once = true; |
|
294 | settings.observeChanges = false; |
|
295 | ||
296 | // show when top visible |
|
297 | settings.onOnScreen = function() { |
|
298 | module.debug('Image on screen', element); |
|
299 | module.precache(src, function() { |
|
300 | module.set.image(src, function() { |
|
301 | loadedCount++; |
|
302 | if(loadedCount == moduleCount) { |
|
303 | settings.onAllLoaded.call(this); |
|
304 | } |
|
305 | settings.onLoad.call(this); |
|
306 | }); |
|
307 | }); |
|
308 | }; |
|
309 | } |
|
310 | }, |
|
311 | fixed: function() { |
|
312 | module.debug('Setting up fixed'); |
|
313 | settings.once = false; |
|
314 | settings.observeChanges = false; |
|
315 | settings.initialCheck = true; |
|
316 | settings.refreshOnLoad = true; |
|
317 | if(!parameters.transition) { |
|
318 | settings.transition = false; |
|
319 | } |
|
320 | module.create.placeholder(); |
|
321 | module.debug('Added placeholder', $placeholder); |
|
322 | settings.onTopPassed = function() { |
|
323 | module.debug('Element passed, adding fixed position', $module); |
|
324 | module.show.placeholder(); |
|
325 | module.set.fixed(); |
|
326 | if(settings.transition) { |
|
327 | if($.fn.transition !== undefined) { |
|
328 | $module.transition(settings.transition, settings.duration); |
|
329 | } |
|
330 | } |
|
331 | }; |
|
332 | settings.onTopPassedReverse = function() { |
|
333 | module.debug('Element returned to position, removing fixed', $module); |
|
334 | module.hide.placeholder(); |
|
335 | module.remove.fixed(); |
|
336 | }; |
|
337 | } |
|
338 | }, |
|
339 | ||
340 | create: { |
|
341 | placeholder: function() { |
|
342 | module.verbose('Creating fixed position placeholder'); |
|
343 | $placeholder = $module |
|
344 | .clone(false) |
|
345 | .css('display', 'none') |
|
346 | .addClass(className.placeholder) |
|
347 | .insertAfter($module) |
|
348 | ; |
|
349 | } |
|
350 | }, |
|
351 | ||
352 | show: { |
|
353 | placeholder: function() { |
|
354 | module.verbose('Showing placeholder'); |
|
355 | $placeholder |
|
356 | .css('display', 'block') |
|
357 | .css('visibility', 'hidden') |
|
358 | ; |
|
359 | } |
|
360 | }, |
|
361 | hide: { |
|
362 | placeholder: function() { |
|
363 | module.verbose('Hiding placeholder'); |
|
364 | $placeholder |
|
365 | .css('display', 'none') |
|
366 | .css('visibility', '') |
|
367 | ; |
|
368 | } |
|
369 | }, |
|
370 | ||
371 | set: { |
|
372 | fixed: function() { |
|
373 | module.verbose('Setting element to fixed position'); |
|
374 | $module |
|
375 | .addClass(className.fixed) |
|
376 | .css({ |
|
377 | position : 'fixed', |
|
378 | top : settings.offset + 'px', |
|
379 | left : 'auto', |
|
380 | zIndex : settings.zIndex |
|
381 | }) |
|
382 | ; |
|
383 | settings.onFixed.call(element); |
|
384 | }, |
|
385 | image: function(src, callback) { |
|
386 | $module |
|
387 | .attr('src', src) |
|
388 | ; |
|
389 | if(settings.transition) { |
|
390 | if( $.fn.transition !== undefined) { |
|
391 | if($module.hasClass(className.visible)) { |
|
392 | module.debug('Transition already occurred on this image, skipping animation'); |
|
393 | return; |
|
394 | } |
|
395 | $module.transition(settings.transition, settings.duration, callback); |
|
396 | } |
|
397 | else { |
|
398 | $module.fadeIn(settings.duration, callback); |
|
399 | } |
|
400 | } |
|
401 | else { |
|
402 | $module.show(); |
|
403 | } |
|
404 | } |
|
405 | }, |
|
406 | ||
407 | is: { |
|
408 | onScreen: function() { |
|
409 | var |
|
410 | calculations = module.get.elementCalculations() |
|
411 | ; |
|
412 | return calculations.onScreen; |
|
413 | }, |
|
414 | offScreen: function() { |
|
415 | var |
|
416 | calculations = module.get.elementCalculations() |
|
417 | ; |
|
418 | return calculations.offScreen; |
|
419 | }, |
|
420 | visible: function() { |
|
421 | if(module.cache && module.cache.element) { |
|
422 | return !(module.cache.element.width === 0 && module.cache.element.offset.top === 0); |
|
423 | } |
|
424 | return false; |
|
425 | }, |
|
426 | verticallyScrollableContext: function() { |
|
427 | var |
|
428 | overflowY = ($context.get(0) !== window) |
|
429 | ? $context.css('overflow-y') |
|
430 | : false |
|
431 | ; |
|
432 | return (overflowY == 'auto' || overflowY == 'scroll'); |
|
433 | }, |
|
434 | horizontallyScrollableContext: function() { |
|
435 | var |
|
436 | overflowX = ($context.get(0) !== window) |
|
437 | ? $context.css('overflow-x') |
|
438 | : false |
|
439 | ; |
|
440 | return (overflowX == 'auto' || overflowX == 'scroll'); |
|
441 | } |
|
442 | }, |
|
443 | ||
444 | refresh: function() { |
|
445 | module.debug('Refreshing constants (width/height)'); |
|
446 | if(settings.type == 'fixed') { |
|
447 | module.resetFixed(); |
|
448 | } |
|
449 | module.reset(); |
|
450 | module.save.position(); |
|
451 | if(settings.checkOnRefresh) { |
|
452 | module.checkVisibility(); |
|
453 | } |
|
454 | settings.onRefresh.call(element); |
|
455 | }, |
|
456 | ||
457 | resetFixed: function () { |
|
458 | module.remove.fixed(); |
|
459 | module.remove.occurred(); |
|
460 | }, |
|
461 | ||
462 | reset: function() { |
|
463 | module.verbose('Resetting all cached values'); |
|
464 | if( $.isPlainObject(module.cache) ) { |
|
465 | module.cache.screen = {}; |
|
466 | module.cache.element = {}; |
|
467 | } |
|
468 | }, |
|
469 | ||
470 | checkVisibility: function(scroll) { |
|
471 | module.verbose('Checking visibility of element', module.cache.element); |
|
472 | ||
473 | if( !disabled && module.is.visible() ) { |
|
474 | ||
475 | // save scroll position |
|
476 | module.save.scroll(scroll); |
|
477 | ||
478 | // update calculations derived from scroll |
|
479 | module.save.calculations(); |
|
480 | ||
481 | // percentage |
|
482 | module.passed(); |
|
483 | ||
484 | // reverse (must be first) |
|
485 | module.passingReverse(); |
|
486 | module.topVisibleReverse(); |
|
487 | module.bottomVisibleReverse(); |
|
488 | module.topPassedReverse(); |
|
489 | module.bottomPassedReverse(); |
|
490 | ||
491 | // one time |
|
492 | module.onScreen(); |
|
493 | module.offScreen(); |
|
494 | module.passing(); |
|
495 | module.topVisible(); |
|
496 | module.bottomVisible(); |
|
497 | module.topPassed(); |
|
498 | module.bottomPassed(); |
|
499 | ||
500 | // on update callback |
|
501 | if(settings.onUpdate) { |
|
502 | settings.onUpdate.call(element, module.get.elementCalculations()); |
|
503 | } |
|
504 | } |
|
505 | }, |
|
506 | ||
507 | passed: function(amount, newCallback) { |
|
508 | var |
|
509 | calculations = module.get.elementCalculations(), |
|
510 | amountInPixels |
|
511 | ; |
|
512 | // assign callback |
|
513 | if(amount && newCallback) { |
|
514 | settings.onPassed[amount] = newCallback; |
|
515 | } |
|
516 | else if(amount !== undefined) { |
|
517 | return (module.get.pixelsPassed(amount) > calculations.pixelsPassed); |
|
518 | } |
|
519 | else if(calculations.passing) { |
|
520 | $.each(settings.onPassed, function(amount, callback) { |
|
521 | if(calculations.bottomVisible || calculations.pixelsPassed > module.get.pixelsPassed(amount)) { |
|
522 | module.execute(callback, amount); |
|
523 | } |
|
524 | else if(!settings.once) { |
|
525 | module.remove.occurred(callback); |
|
526 | } |
|
527 | }); |
|
528 | } |
|
529 | }, |
|
530 | ||
531 | onScreen: function(newCallback) { |
|
532 | var |
|
533 | calculations = module.get.elementCalculations(), |
|
534 | callback = newCallback || settings.onOnScreen, |
|
535 | callbackName = 'onScreen' |
|
536 | ; |
|
537 | if(newCallback) { |
|
538 | module.debug('Adding callback for onScreen', newCallback); |
|
539 | settings.onOnScreen = newCallback; |
|
540 | } |
|
541 | if(calculations.onScreen) { |
|
542 | module.execute(callback, callbackName); |
|
543 | } |
|
544 | else if(!settings.once) { |
|
545 | module.remove.occurred(callbackName); |
|
546 | } |
|
547 | if(newCallback !== undefined) { |
|
548 | return calculations.onOnScreen; |
|
549 | } |
|
550 | }, |
|
551 | ||
552 | offScreen: function(newCallback) { |
|
553 | var |
|
554 | calculations = module.get.elementCalculations(), |
|
555 | callback = newCallback || settings.onOffScreen, |
|
556 | callbackName = 'offScreen' |
|
557 | ; |
|
558 | if(newCallback) { |
|
559 | module.debug('Adding callback for offScreen', newCallback); |
|
560 | settings.onOffScreen = newCallback; |
|
561 | } |
|
562 | if(calculations.offScreen) { |
|
563 | module.execute(callback, callbackName); |
|
564 | } |
|
565 | else if(!settings.once) { |
|
566 | module.remove.occurred(callbackName); |
|
567 | } |
|
568 | if(newCallback !== undefined) { |
|
569 | return calculations.onOffScreen; |
|
570 | } |
|
571 | }, |
|
572 | ||
573 | passing: function(newCallback) { |
|
574 | var |
|
575 | calculations = module.get.elementCalculations(), |
|
576 | callback = newCallback || settings.onPassing, |
|
577 | callbackName = 'passing' |
|
578 | ; |
|
579 | if(newCallback) { |
|
580 | module.debug('Adding callback for passing', newCallback); |
|
581 | settings.onPassing = newCallback; |
|
582 | } |
|
583 | if(calculations.passing) { |
|
584 | module.execute(callback, callbackName); |
|
585 | } |
|
586 | else if(!settings.once) { |
|
587 | module.remove.occurred(callbackName); |
|
588 | } |
|
589 | if(newCallback !== undefined) { |
|
590 | return calculations.passing; |
|
591 | } |
|
592 | }, |
|
593 | ||
594 | ||
595 | topVisible: function(newCallback) { |
|
596 | var |
|
597 | calculations = module.get.elementCalculations(), |
|
598 | callback = newCallback || settings.onTopVisible, |
|
599 | callbackName = 'topVisible' |
|
600 | ; |
|
601 | if(newCallback) { |
|
602 | module.debug('Adding callback for top visible', newCallback); |
|
603 | settings.onTopVisible = newCallback; |
|
604 | } |
|
605 | if(calculations.topVisible) { |
|
606 | module.execute(callback, callbackName); |
|
607 | } |
|
608 | else if(!settings.once) { |
|
609 | module.remove.occurred(callbackName); |
|
610 | } |
|
611 | if(newCallback === undefined) { |
|
612 | return calculations.topVisible; |
|
613 | } |
|
614 | }, |
|
615 | ||
616 | bottomVisible: function(newCallback) { |
|
617 | var |
|
618 | calculations = module.get.elementCalculations(), |
|
619 | callback = newCallback || settings.onBottomVisible, |
|
620 | callbackName = 'bottomVisible' |
|
621 | ; |
|
622 | if(newCallback) { |
|
623 | module.debug('Adding callback for bottom visible', newCallback); |
|
624 | settings.onBottomVisible = newCallback; |
|
625 | } |
|
626 | if(calculations.bottomVisible) { |
|
627 | module.execute(callback, callbackName); |
|
628 | } |
|
629 | else if(!settings.once) { |
|
630 | module.remove.occurred(callbackName); |
|
631 | } |
|
632 | if(newCallback === undefined) { |
|
633 | return calculations.bottomVisible; |
|
634 | } |
|
635 | }, |
|
636 | ||
637 | topPassed: function(newCallback) { |
|
638 | var |
|
639 | calculations = module.get.elementCalculations(), |
|
640 | callback = newCallback || settings.onTopPassed, |
|
641 | callbackName = 'topPassed' |
|
642 | ; |
|
643 | if(newCallback) { |
|
644 | module.debug('Adding callback for top passed', newCallback); |
|
645 | settings.onTopPassed = newCallback; |
|
646 | } |
|
647 | if(calculations.topPassed) { |
|
648 | module.execute(callback, callbackName); |
|
649 | } |
|
650 | else if(!settings.once) { |
|
651 | module.remove.occurred(callbackName); |
|
652 | } |
|
653 | if(newCallback === undefined) { |
|
654 | return calculations.topPassed; |
|
655 | } |
|
656 | }, |
|
657 | ||
658 | bottomPassed: function(newCallback) { |
|
659 | var |
|
660 | calculations = module.get.elementCalculations(), |
|
661 | callback = newCallback || settings.onBottomPassed, |
|
662 | callbackName = 'bottomPassed' |
|
663 | ; |
|
664 | if(newCallback) { |
|
665 | module.debug('Adding callback for bottom passed', newCallback); |
|
666 | settings.onBottomPassed = newCallback; |
|
667 | } |
|
668 | if(calculations.bottomPassed) { |
|
669 | module.execute(callback, callbackName); |
|
670 | } |
|
671 | else if(!settings.once) { |
|
672 | module.remove.occurred(callbackName); |
|
673 | } |
|
674 | if(newCallback === undefined) { |
|
675 | return calculations.bottomPassed; |
|
676 | } |
|
677 | }, |
|
678 | ||
679 | passingReverse: function(newCallback) { |
|
680 | var |
|
681 | calculations = module.get.elementCalculations(), |
|
682 | callback = newCallback || settings.onPassingReverse, |
|
683 | callbackName = 'passingReverse' |
|
684 | ; |
|
685 | if(newCallback) { |
|
686 | module.debug('Adding callback for passing reverse', newCallback); |
|
687 | settings.onPassingReverse = newCallback; |
|
688 | } |
|
689 | if(!calculations.passing) { |
|
690 | if(module.get.occurred('passing')) { |
|
691 | module.execute(callback, callbackName); |
|
692 | } |
|
693 | } |
|
694 | else if(!settings.once) { |
|
695 | module.remove.occurred(callbackName); |
|
696 | } |
|
697 | if(newCallback !== undefined) { |
|
698 | return !calculations.passing; |
|
699 | } |
|
700 | }, |
|
701 | ||
702 | ||
703 | topVisibleReverse: function(newCallback) { |
|
704 | var |
|
705 | calculations = module.get.elementCalculations(), |
|
706 | callback = newCallback || settings.onTopVisibleReverse, |
|
707 | callbackName = 'topVisibleReverse' |
|
708 | ; |
|
709 | if(newCallback) { |
|
710 | module.debug('Adding callback for top visible reverse', newCallback); |
|
711 | settings.onTopVisibleReverse = newCallback; |
|
712 | } |
|
713 | if(!calculations.topVisible) { |
|
714 | if(module.get.occurred('topVisible')) { |
|
715 | module.execute(callback, callbackName); |
|
716 | } |
|
717 | } |
|
718 | else if(!settings.once) { |
|
719 | module.remove.occurred(callbackName); |
|
720 | } |
|
721 | if(newCallback === undefined) { |
|
722 | return !calculations.topVisible; |
|
723 | } |
|
724 | }, |
|
725 | ||
726 | bottomVisibleReverse: function(newCallback) { |
|
727 | var |
|
728 | calculations = module.get.elementCalculations(), |
|
729 | callback = newCallback || settings.onBottomVisibleReverse, |
|
730 | callbackName = 'bottomVisibleReverse' |
|
731 | ; |
|
732 | if(newCallback) { |
|
733 | module.debug('Adding callback for bottom visible reverse', newCallback); |
|
734 | settings.onBottomVisibleReverse = newCallback; |
|
735 | } |
|
736 | if(!calculations.bottomVisible) { |
|
737 | if(module.get.occurred('bottomVisible')) { |
|
738 | module.execute(callback, callbackName); |
|
739 | } |
|
740 | } |
|
741 | else if(!settings.once) { |
|
742 | module.remove.occurred(callbackName); |
|
743 | } |
|
744 | if(newCallback === undefined) { |
|
745 | return !calculations.bottomVisible; |
|
746 | } |
|
747 | }, |
|
748 | ||
749 | topPassedReverse: function(newCallback) { |
|
750 | var |
|
751 | calculations = module.get.elementCalculations(), |
|
752 | callback = newCallback || settings.onTopPassedReverse, |
|
753 | callbackName = 'topPassedReverse' |
|
754 | ; |
|
755 | if(newCallback) { |
|
756 | module.debug('Adding callback for top passed reverse', newCallback); |
|
757 | settings.onTopPassedReverse = newCallback; |
|
758 | } |
|
759 | if(!calculations.topPassed) { |
|
760 | if(module.get.occurred('topPassed')) { |
|
761 | module.execute(callback, callbackName); |
|
762 | } |
|
763 | } |
|
764 | else if(!settings.once) { |
|
765 | module.remove.occurred(callbackName); |
|
766 | } |
|
767 | if(newCallback === undefined) { |
|
768 | return !calculations.onTopPassed; |
|
769 | } |
|
770 | }, |
|
771 | ||
772 | bottomPassedReverse: function(newCallback) { |
|
773 | var |
|
774 | calculations = module.get.elementCalculations(), |
|
775 | callback = newCallback || settings.onBottomPassedReverse, |
|
776 | callbackName = 'bottomPassedReverse' |
|
777 | ; |
|
778 | if(newCallback) { |
|
779 | module.debug('Adding callback for bottom passed reverse', newCallback); |
|
780 | settings.onBottomPassedReverse = newCallback; |
|
781 | } |
|
782 | if(!calculations.bottomPassed) { |
|
783 | if(module.get.occurred('bottomPassed')) { |
|
784 | module.execute(callback, callbackName); |
|
785 | } |
|
786 | } |
|
787 | else if(!settings.once) { |
|
788 | module.remove.occurred(callbackName); |
|
789 | } |
|
790 | if(newCallback === undefined) { |
|
791 | return !calculations.bottomPassed; |
|
792 | } |
|
793 | }, |
|
794 | ||
795 | execute: function(callback, callbackName) { |
|
796 | var |
|
797 | calculations = module.get.elementCalculations(), |
|
798 | screen = module.get.screenCalculations() |
|
799 | ; |
|
800 | callback = callback || false; |
|
801 | if(callback) { |
|
802 | if(settings.continuous) { |
|
803 | module.debug('Callback being called continuously', callbackName, calculations); |
|
804 | callback.call(element, calculations, screen); |
|
805 | } |
|
806 | else if(!module.get.occurred(callbackName)) { |
|
807 | module.debug('Conditions met', callbackName, calculations); |
|
808 | callback.call(element, calculations, screen); |
|
809 | } |
|
810 | } |
|
811 | module.save.occurred(callbackName); |
|
812 | }, |
|
813 | ||
814 | remove: { |
|
815 | fixed: function() { |
|
816 | module.debug('Removing fixed position'); |
|
817 | $module |
|
818 | .removeClass(className.fixed) |
|
819 | .css({ |
|
820 | position : '', |
|
821 | top : '', |
|
822 | left : '', |
|
823 | zIndex : '' |
|
824 | }) |
|
825 | ; |
|
826 | settings.onUnfixed.call(element); |
|
827 | }, |
|
828 | placeholder: function() { |
|
829 | module.debug('Removing placeholder content'); |
|
830 | if($placeholder) { |
|
831 | $placeholder.remove(); |
|
832 | } |
|
833 | }, |
|
834 | occurred: function(callback) { |
|
835 | if(callback) { |
|
836 | var |
|
837 | occurred = module.cache.occurred |
|
838 | ; |
|
839 | if(occurred[callback] !== undefined && occurred[callback] === true) { |
|
840 | module.debug('Callback can now be called again', callback); |
|
841 | module.cache.occurred[callback] = false; |
|
842 | } |
|
843 | } |
|
844 | else { |
|
845 | module.cache.occurred = {}; |
|
846 | } |
|
847 | } |
|
848 | }, |
|
849 | ||
850 | save: { |
|
851 | calculations: function() { |
|
852 | module.verbose('Saving all calculations necessary to determine positioning'); |
|
853 | module.save.direction(); |
|
854 | module.save.screenCalculations(); |
|
855 | module.save.elementCalculations(); |
|
856 | }, |
|
857 | occurred: function(callback) { |
|
858 | if(callback) { |
|
859 | if(module.cache.occurred[callback] === undefined || (module.cache.occurred[callback] !== true)) { |
|
860 | module.verbose('Saving callback occurred', callback); |
|
861 | module.cache.occurred[callback] = true; |
|
862 | } |
|
863 | } |
|
864 | }, |
|
865 | scroll: function(scrollPosition) { |
|
866 | scrollPosition = scrollPosition + settings.offset || $context.scrollTop() + settings.offset; |
|
867 | module.cache.scroll = scrollPosition; |
|
868 | }, |
|
869 | direction: function() { |
|
870 | var |
|
871 | scroll = module.get.scroll(), |
|
872 | lastScroll = module.get.lastScroll(), |
|
873 | direction |
|
874 | ; |
|
875 | if(scroll > lastScroll && lastScroll) { |
|
876 | direction = 'down'; |
|
877 | } |
|
878 | else if(scroll < lastScroll && lastScroll) { |
|
879 | direction = 'up'; |
|
880 | } |
|
881 | else { |
|
882 | direction = 'static'; |
|
883 | } |
|
884 | module.cache.direction = direction; |
|
885 | return module.cache.direction; |
|
886 | }, |
|
887 | elementPosition: function() { |
|
888 | var |
|
889 | element = module.cache.element, |
|
890 | screen = module.get.screenSize() |
|
891 | ; |
|
892 | module.verbose('Saving element position'); |
|
893 | // (quicker than $.extend) |
|
894 | element.fits = (element.height < screen.height); |
|
895 | element.offset = $module.offset(); |
|
896 | element.width = $module.outerWidth(); |
|
897 | element.height = $module.outerHeight(); |
|
898 | // compensate for scroll in context |
|
899 | if(module.is.verticallyScrollableContext()) { |
|
900 | element.offset.top += $context.scrollTop() - $context.offset().top; |
|
901 | } |
|
902 | if(module.is.horizontallyScrollableContext()) { |
|
903 | element.offset.left += $context.scrollLeft - $context.offset().left; |
|
904 | } |
|
905 | // store |
|
906 | module.cache.element = element; |
|
907 | return element; |
|
908 | }, |
|
909 | elementCalculations: function() { |
|
910 | var |
|
911 | screen = module.get.screenCalculations(), |
|
912 | element = module.get.elementPosition() |
|
913 | ; |
|
914 | // offset |
|
915 | if(settings.includeMargin) { |
|
916 | element.margin = {}; |
|
917 | element.margin.top = parseInt($module.css('margin-top'), 10); |
|
918 | element.margin.bottom = parseInt($module.css('margin-bottom'), 10); |
|
919 | element.top = element.offset.top - element.margin.top; |
|
920 | element.bottom = element.offset.top + element.height + element.margin.bottom; |
|
921 | } |
|
922 | else { |
|
923 | element.top = element.offset.top; |
|
924 | element.bottom = element.offset.top + element.height; |
|
925 | } |
|
926 | ||
927 | // visibility |
|
928 | element.topPassed = (screen.top >= element.top); |
|
929 | element.bottomPassed = (screen.top >= element.bottom); |
|
930 | element.topVisible = (screen.bottom >= element.top) && !element.bottomPassed; |
|
931 | element.bottomVisible = (screen.bottom >= element.bottom) && !element.topPassed; |
|
932 | element.pixelsPassed = 0; |
|
933 | element.percentagePassed = 0; |
|
934 | ||
935 | // meta calculations |
|
936 | element.onScreen = (element.topVisible && !element.bottomPassed); |
|
937 | element.passing = (element.topPassed && !element.bottomPassed); |
|
938 | element.offScreen = (!element.onScreen); |
|
939 | ||
940 | // passing calculations |
|
941 | if(element.passing) { |
|
942 | element.pixelsPassed = (screen.top - element.top); |
|
943 | element.percentagePassed = (screen.top - element.top) / element.height; |
|
944 | } |
|
945 | module.cache.element = element; |
|
946 | module.verbose('Updated element calculations', element); |
|
947 | return element; |
|
948 | }, |
|
949 | screenCalculations: function() { |
|
950 | var |
|
951 | scroll = module.get.scroll() |
|
952 | ; |
|
953 | module.save.direction(); |
|
954 | module.cache.screen.top = scroll; |
|
955 | module.cache.screen.bottom = scroll + module.cache.screen.height; |
|
956 | return module.cache.screen; |
|
957 | }, |
|
958 | screenSize: function() { |
|
959 | module.verbose('Saving window position'); |
|
960 | module.cache.screen = { |
|
961 | height: $context.height() |
|
962 | }; |
|
963 | }, |
|
964 | position: function() { |
|
965 | module.save.screenSize(); |
|
966 | module.save.elementPosition(); |
|
967 | } |
|
968 | }, |
|
969 | ||
970 | get: { |
|
971 | pixelsPassed: function(amount) { |
|
972 | var |
|
973 | element = module.get.elementCalculations() |
|
974 | ; |
|
975 | if(amount.search('%') > -1) { |
|
976 | return ( element.height * (parseInt(amount, 10) / 100) ); |
|
977 | } |
|
978 | return parseInt(amount, 10); |
|
979 | }, |
|
980 | occurred: function(callback) { |
|
981 | return (module.cache.occurred !== undefined) |
|
982 | ? module.cache.occurred[callback] || false |
|
983 | : false |
|
984 | ; |
|
985 | }, |
|
986 | direction: function() { |
|
987 | if(module.cache.direction === undefined) { |
|
988 | module.save.direction(); |
|
989 | } |
|
990 | return module.cache.direction; |
|
991 | }, |
|
992 | elementPosition: function() { |
|
993 | if(module.cache.element === undefined) { |
|
994 | module.save.elementPosition(); |
|
995 | } |
|
996 | return module.cache.element; |
|
997 | }, |
|
998 | elementCalculations: function() { |
|
999 | if(module.cache.element === undefined) { |
|
1000 | module.save.elementCalculations(); |
|
1001 | } |
|
1002 | return module.cache.element; |
|
1003 | }, |
|
1004 | screenCalculations: function() { |
|
1005 | if(module.cache.screen === undefined) { |
|
1006 | module.save.screenCalculations(); |
|
1007 | } |
|
1008 | return module.cache.screen; |
|
1009 | }, |
|
1010 | screenSize: function() { |
|
1011 | if(module.cache.screen === undefined) { |
|
1012 | module.save.screenSize(); |
|
1013 | } |
|
1014 | return module.cache.screen; |
|
1015 | }, |
|
1016 | scroll: function() { |
|
1017 | if(module.cache.scroll === undefined) { |
|
1018 | module.save.scroll(); |
|
1019 | } |
|
1020 | return module.cache.scroll; |
|
1021 | }, |
|
1022 | lastScroll: function() { |
|
1023 | if(module.cache.screen === undefined) { |
|
1024 | module.debug('First scroll event, no last scroll could be found'); |
|
1025 | return false; |
|
1026 | } |
|
1027 | return module.cache.screen.top; |
|
1028 | } |
|
1029 | }, |
|
1030 | ||
1031 | setting: function(name, value) { |
|
1032 | if( $.isPlainObject(name) ) { |
|
1033 | $.extend(true, settings, name); |
|
1034 | } |
|
1035 | else if(value !== undefined) { |
|
1036 | settings[name] = value; |
|
1037 | } |
|
1038 | else { |
|
1039 | return settings[name]; |
|
1040 | } |
|
1041 | }, |
|
1042 | internal: function(name, value) { |
|
1043 | if( $.isPlainObject(name) ) { |
|
1044 | $.extend(true, module, name); |
|
1045 | } |
|
1046 | else if(value !== undefined) { |
|
1047 | module[name] = value; |
|
1048 | } |
|
1049 | else { |
|
1050 | return module[name]; |
|
1051 | } |
|
1052 | }, |
|
1053 | debug: function() { |
|
1054 | if(!settings.silent && settings.debug) { |
|
1055 | if(settings.performance) { |
|
1056 | module.performance.log(arguments); |
|
1057 | } |
|
1058 | else { |
|
1059 | module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
|
1060 | module.debug.apply(console, arguments); |
|
1061 | } |
|
1062 | } |
|
1063 | }, |
|
1064 | verbose: function() { |
|
1065 | if(!settings.silent && settings.verbose && settings.debug) { |
|
1066 | if(settings.performance) { |
|
1067 | module.performance.log(arguments); |
|
1068 | } |
|
1069 | else { |
|
1070 | module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
|
1071 | module.verbose.apply(console, arguments); |
|
1072 | } |
|
1073 | } |
|
1074 | }, |
|
1075 | error: function() { |
|
1076 | if(!settings.silent) { |
|
1077 | module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); |
|
1078 | module.error.apply(console, arguments); |
|
1079 | } |
|
1080 | }, |
|
1081 | performance: { |
|
1082 | log: function(message) { |
|
1083 | var |
|
1084 | currentTime, |
|
1085 | executionTime, |
|
1086 | previousTime |
|
1087 | ; |
|
1088 | if(settings.performance) { |
|
1089 | currentTime = new Date().getTime(); |
|
1090 | previousTime = time || currentTime; |
|
1091 | executionTime = currentTime - previousTime; |
|
1092 | time = currentTime; |
|
1093 | performance.push({ |
|
1094 | 'Name' : message[0], |
|
1095 | 'Arguments' : [].slice.call(message, 1) || '', |
|
1096 | 'Element' : element, |
|
1097 | 'Execution Time' : executionTime |
|
1098 | }); |
|
1099 | } |
|
1100 | clearTimeout(module.performance.timer); |
|
1101 | module.performance.timer = setTimeout(module.performance.display, 500); |
|
1102 | }, |
|
1103 | display: function() { |
|
1104 | var |
|
1105 | title = settings.name + ':', |
|
1106 | totalTime = 0 |
|
1107 | ; |
|
1108 | time = false; |
|
1109 | clearTimeout(module.performance.timer); |
|
1110 | $.each(performance, function(index, data) { |
|
1111 | totalTime += data['Execution Time']; |
|
1112 | }); |
|
1113 | title += ' ' + totalTime + 'ms'; |
|
1114 | if(moduleSelector) { |
|
1115 | title += ' \'' + moduleSelector + '\''; |
|
1116 | } |
|
1117 | if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { |
|
1118 | console.groupCollapsed(title); |
|
1119 | if(console.table) { |
|
1120 | console.table(performance); |
|
1121 | } |
|
1122 | else { |
|
1123 | $.each(performance, function(index, data) { |
|
1124 | console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); |
|
1125 | }); |
|
1126 | } |
|
1127 | console.groupEnd(); |
|
1128 | } |
|
1129 | performance = []; |
|
1130 | } |
|
1131 | }, |
|
1132 | invoke: function(query, passedArguments, context) { |
|
1133 | var |
|
1134 | object = instance, |
|
1135 | maxDepth, |
|
1136 | found, |
|
1137 | response |
|
1138 | ; |
|
1139 | passedArguments = passedArguments || queryArguments; |
|
1140 | context = element || context; |
|
1141 | if(typeof query == 'string' && object !== undefined) { |
|
1142 | query = query.split(/[\. ]/); |
|
1143 | maxDepth = query.length - 1; |
|
1144 | $.each(query, function(depth, value) { |
|
1145 | var camelCaseValue = (depth != maxDepth) |
|
1146 | ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) |
|
1147 | : query |
|
1148 | ; |
|
1149 | if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { |
|
1150 | object = object[camelCaseValue]; |
|
1151 | } |
|
1152 | else if( object[camelCaseValue] !== undefined ) { |
|
1153 | found = object[camelCaseValue]; |
|
1154 | return false; |
|
1155 | } |
|
1156 | else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { |
|
1157 | object = object[value]; |
|
1158 | } |
|
1159 | else if( object[value] !== undefined ) { |
|
1160 | found = object[value]; |
|
1161 | return false; |
|
1162 | } |
|
1163 | else { |
|
1164 | module.error(error.method, query); |
|
1165 | return false; |
|
1166 | } |
|
1167 | }); |
|
1168 | } |
|
1169 | if ( $.isFunction( found ) ) { |
|
1170 | response = found.apply(context, passedArguments); |
|
1171 | } |
|
1172 | else if(found !== undefined) { |
|
1173 | response = found; |
|
1174 | } |
|
1175 | if($.isArray(returnedValue)) { |
|
1176 | returnedValue.push(response); |
|
1177 | } |
|
1178 | else if(returnedValue !== undefined) { |
|
1179 | returnedValue = [returnedValue, response]; |
|
1180 | } |
|
1181 | else if(response !== undefined) { |
|
1182 | returnedValue = response; |
|
1183 | } |
|
1184 | return found; |
|
1185 | } |
|
1186 | }; |
|
1187 | ||
1188 | if(methodInvoked) { |
|
1189 | if(instance === undefined) { |
|
1190 | module.initialize(); |
|
1191 | } |
|
1192 | instance.save.scroll(); |
|
1193 | instance.save.calculations(); |
|
1194 | module.invoke(query); |
|
1195 | } |
|
1196 | else { |
|
1197 | if(instance !== undefined) { |
|
1198 | instance.invoke('destroy'); |
|
1199 | } |
|
1200 | module.initialize(); |
|
1201 | } |
|
1202 | }) |
|
1203 | ; |
|
1204 | ||
1205 | return (returnedValue !== undefined) |
|
1206 | ? returnedValue |
|
1207 | : this |
|
1208 | ; |
|
1209 | }; |
|
1210 | ||
1211 | $.fn.visibility.settings = { |
|
1212 | ||
1213 | name : 'Visibility', |
|
1214 | namespace : 'visibility', |
|
1215 | ||
1216 | debug : false, |
|
1217 | verbose : false, |
|
1218 | performance : true, |
|
1219 | ||
1220 | // whether to use mutation observers to follow changes |
|
1221 | observeChanges : true, |
|
1222 | ||
1223 | // check position immediately on init |
|
1224 | initialCheck : true, |
|
1225 | ||
1226 | // whether to refresh calculations after all page images load |
|
1227 | refreshOnLoad : true, |
|
1228 | ||
1229 | // whether to refresh calculations after page resize event |
|
1230 | refreshOnResize : true, |
|
1231 | ||
1232 | // should call callbacks on refresh event (resize, etc) |
|
1233 | checkOnRefresh : true, |
|
1234 | ||
1235 | // callback should only occur one time |
|
1236 | once : true, |
|
1237 | ||
1238 | // callback should fire continuously whe evaluates to true |
|
1239 | continuous : false, |
|
1240 | ||
1241 | // offset to use with scroll top |
|
1242 | offset : 0, |
|
1243 | ||
1244 | // whether to include margin in elements position |
|
1245 | includeMargin : false, |
|
1246 | ||
1247 | // scroll context for visibility checks |
|
1248 | context : window, |
|
1249 | ||
1250 | // visibility check delay in ms (defaults to animationFrame) |
|
1251 | throttle : false, |
|
1252 | ||
1253 | // special visibility type (image, fixed) |
|
1254 | type : false, |
|
1255 | ||
1256 | // z-index to use with visibility 'fixed' |
|
1257 | zIndex : '10', |
|
1258 | ||
1259 | // image only animation settings |
|
1260 | transition : 'fade in', |
|
1261 | duration : 1000, |
|
1262 | ||
1263 | // array of callbacks for percentage |
|
1264 | onPassed : {}, |
|
1265 | ||
1266 | // standard callbacks |
|
1267 | onOnScreen : false, |
|
1268 | onOffScreen : false, |
|
1269 | onPassing : false, |
|
1270 | onTopVisible : false, |
|
1271 | onBottomVisible : false, |
|
1272 | onTopPassed : false, |
|
1273 | onBottomPassed : false, |
|
1274 | ||
1275 | // reverse callbacks |
|
1276 | onPassingReverse : false, |
|
1277 | onTopVisibleReverse : false, |
|
1278 | onBottomVisibleReverse : false, |
|
1279 | onTopPassedReverse : false, |
|
1280 | onBottomPassedReverse : false, |
|
1281 | ||
1282 | // special callbacks for image |
|
1283 | onLoad : function() {}, |
|
1284 | onAllLoaded : function() {}, |
|
1285 | ||
1286 | // special callbacks for fixed position |
|
1287 | onFixed : function() {}, |
|
1288 | onUnfixed : function() {}, |
|
1289 | ||
1290 | // utility callbacks |
|
1291 | onUpdate : false, // disabled by default for performance |
|
1292 | onRefresh : function(){}, |
|
1293 | ||
1294 | metadata : { |
|
1295 | src: 'src' |
|
1296 | }, |
|
1297 | ||
1298 | className: { |
|
1299 | fixed : 'fixed', |
|
1300 | placeholder : 'placeholder', |
|
1301 | visible : 'visible' |
|
1302 | }, |
|
1303 | ||
1304 | error : { |
|
1305 | method : 'The method you called is not defined.', |
|
1306 | visible : 'Element is hidden, you must call refresh after element becomes visible' |
|
1307 | } |
|
1308 | ||
1309 | }; |
|
1310 | ||
1311 | })( jQuery, window, document ); |
|
1312 |