diff --git a/definitions/behaviors/visibility.js b/definitions/behaviors/visibility.js index 08ade20..880dc17 100755 --- a/definitions/behaviors/visibility.js +++ b/definitions/behaviors/visibility.js @@ -42,11 +42,11 @@ $.fn.visibility = function(parameters) { moduleNamespace = 'module-' + namespace, $window = $(window), + $module = $(this), $context = $(settings.context), - $images = $module.find('img'), - selector = $module.selector || '', + instance = $module.data(moduleNamespace), requestAnimationFrame = window.requestAnimationFrame @@ -76,13 +76,16 @@ $.fn.visibility = function(parameters) { if(settings.type == 'fixed') { module.setup.fixed(); } + if(settings.observeChanges) { + module.observeChanges(); + } + if( !module.is.visible() ) { + module.error(error.visible, $module); + } } if(settings.initialCheck) { module.checkVisibility(); } - if(settings.observeChanges) { - module.observeChanges(); - } module.instantiate(); }, @@ -96,12 +99,18 @@ $.fn.visibility = function(parameters) { destroy: function() { module.verbose('Destroying previous module'); + if(observer) { + observer.disconnect(); + } + $window + .off('load' + eventNamespace, module.event.load) + .off('resize' + eventNamespace, module.event.resize) + ; + $context.off('scrollchange' + eventNamespace, module.event.scrollchange); $module .off(eventNamespace) .removeData(moduleNamespace) ; - $window.off('resize' + eventNamespace, module.event.refresh); - $context.off('scroll' + eventNamespace, module.event.scroll); }, observeChanges: function() { @@ -111,7 +120,10 @@ $.fn.visibility = function(parameters) { if('MutationObserver' in window) { observer = new MutationObserver(function(mutations) { module.verbose('DOM tree modified, updating visibility calculations'); - module.refresh(); + module.timer = setTimeout(function() { + module.verbose('DOM tree modified, updating sticky menu'); + module.refresh(); + }, 100); }); observer.observe(element, { childList : true, @@ -125,17 +137,19 @@ $.fn.visibility = function(parameters) { events: function() { module.verbose('Binding visibility events to scroll and resize'); $window - .on('resize' + eventNamespace, module.event.refresh) + .on('load' + eventNamespace, module.event.load) + .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) ; - if($images.length > 0) { - module.bind.imageLoad(); - } }, imageLoad: function() { var + $images = $module.find('img'), imageCount = $images.length, index = imageCount, loadedCount = 0, @@ -150,44 +164,82 @@ $.fn.visibility = function(parameters) { } } ; - $images - .each(function() { - images.push( $(this).attr('src') ); - }) - ; - while(index--) { - cacheImage = document.createElement('img'); - cacheImage.onload = handleLoad; - cacheImage.onerror = handleLoad; - cacheImage.src = images[index]; - cache.push(cacheImage); + if(imageCount > 0) { + $images + .each(function() { + images.push( $(this).attr('src') ); + }) + ; + while(index--) { + cacheImage = document.createElement('img'); + cacheImage.onload = handleLoad; + cacheImage.onerror = handleLoad; + cacheImage.src = images[index]; + cache.push(cacheImage); + } } } }, event: { - refresh: function() { + resize: function() { + module.debug('Window resized'); requestAnimationFrame(module.refresh); }, + load: function() { + module.debug('Page finished loading'); + requestAnimationFrame(module.refresh); + }, + // publishes scrollchange event on one scroll scroll: function() { - module.verbose('Scroll position changed'); if(settings.throttle) { clearTimeout(module.timer); module.timer = setTimeout(function() { - module.checkVisibility(); + $context.trigger('scrollchange' + eventNamespace, [ $context.scrollTop() ]); }, settings.throttle); } else { requestAnimationFrame(function() { - module.checkVisibility(); + $context.trigger('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); } }, should: { trackChanges: function() { - if(methodInvoked && queryArguments.length > 0) { + if(methodInvoked) { module.debug('One time query, no need to bind events'); return false; } @@ -287,7 +339,7 @@ $.fn.visibility = function(parameters) { }, refresh: function() { - module.debug('Refreshing constants (element width/height)'); + module.debug('Refreshing constants (width/height)'); module.reset(); module.save.position(); module.checkVisibility(); @@ -302,11 +354,14 @@ $.fn.visibility = function(parameters) { } }, - checkVisibility: function() { + checkVisibility: function(scroll) { module.verbose('Checking visibility of element', module.cache.element); if( module.is.visible() ) { + // save scroll position + module.save.scroll(scroll); + // update calculations derived from scroll module.save.calculations(); @@ -616,7 +671,6 @@ $.fn.visibility = function(parameters) { save: { calculations: function() { module.verbose('Saving all calculations necessary to determine positioning'); - module.save.scroll(); module.save.direction(); module.save.screenCalculations(); module.save.elementCalculations(); @@ -629,8 +683,9 @@ $.fn.visibility = function(parameters) { } } }, - scroll: function() { - module.cache.scroll = $context.scrollTop() + settings.offset; + scroll: function(scrollPosition) { + scrollPosition = scrollPosition + settings.offset || $context.scrollTop() + settings.offset; + module.cache.scroll = scrollPosition; }, direction: function() { var @@ -855,7 +910,7 @@ $.fn.visibility = function(parameters) { }); } clearTimeout(module.performance.timer); - module.performance.timer = setTimeout(module.performance.display, 100); + module.performance.timer = setTimeout(module.performance.display, 500); }, display: function() { var @@ -975,6 +1030,9 @@ $.fn.visibility.settings = { // whether to use mutation observers to follow changes observeChanges : true, + // whether to refresh calculations after all page images load + refreshOnLoad : true, + // callback should only occur one time once : true, @@ -1029,9 +1087,10 @@ $.fn.visibility.settings = { }, error : { - method : 'The method you called is not defined.' + method : 'The method you called is not defined.', + visible : 'Element is hidden, you must call refresh after element becomes visible' } }; -})( jQuery, window , document ); +})( jQuery, window , document ); \ No newline at end of file diff --git a/definitions/elements/input.less b/definitions/elements/input.less index 3255f1c..cc74c05 100755 --- a/definitions/elements/input.less +++ b/definitions/elements/input.less @@ -397,7 +397,7 @@ ---------------------*/ .ui.fluid.input { - display: block; + display: flex; } /*-------------------- diff --git a/definitions/modules/popup.js b/definitions/modules/popup.js index 903dc49..59751c5 100755 --- a/definitions/modules/popup.js +++ b/definitions/modules/popup.js @@ -760,7 +760,7 @@ $.fn.popup = function(parameters) { } else if(!settings.lastResort) { module.debug('Popup could not find a position in view', $popup); - module.error(error.cannotPlace, element); + // module.error(error.cannotPlace, element); module.remove.attempts(); module.remove.loading(); module.reset(); diff --git a/definitions/modules/sticky.js b/definitions/modules/sticky.js index a8a4b22..40d2e77 100755 --- a/definitions/modules/sticky.js +++ b/definitions/modules/sticky.js @@ -87,13 +87,18 @@ $.fn.sticky = function(parameters) { }, destroy: function() { - module.verbose('Destroying previous module'); + module.verbose('Destroying previous instance'); module.reset(); if(observer) { observer.disconnect(); } - $window.off('resize' + eventNamespace, module.event.resize); - $scroll.off('scroll' + eventNamespace, module.event.scroll); + $window + .off('load' + eventNamespace, module.event.load) + .off('resize' + eventNamespace, module.event.resize) + ; + $scroll + .off('scrollchange' + eventNamespace, module.event.scrollchange) + ; $module.removeData(moduleNamespace); }, @@ -107,7 +112,7 @@ $.fn.sticky = function(parameters) { module.timer = setTimeout(function() { module.verbose('DOM tree modified, updating sticky menu'); module.refresh(); - }, 20); + }, 100); }); observer.observe(element, { childList : true, @@ -147,23 +152,36 @@ $.fn.sticky = function(parameters) { bind: { events: function() { - $window.on('resize' + eventNamespace, module.event.resize); - $scroll.on('scroll' + eventNamespace, module.event.scroll); + $window + .on('load' + eventNamespace, module.event.load) + .on('resize' + eventNamespace, module.event.resize) + ; + // pub/sub pattern + $scroll + .off('scroll' + eventNamespace) + .on('scroll' + eventNamespace, module.event.scroll) + .on('scrollchange' + eventNamespace, module.event.scrollchange) + ; } }, event: { + load: function() { + module.verbose('Page contents finished loading'); + requestAnimationFrame(module.refresh); + }, resize: function() { - requestAnimationFrame(function() { - module.refresh(); - module.stick(); - }); + module.verbose('Window resized'); + requestAnimationFrame(module.refresh); }, scroll: function() { requestAnimationFrame(function() { - module.stick(); - settings.onScroll.call(element); + $scroll.trigger('scrollchange' + eventNamespace, $scroll.scrollTop() ); }); + }, + scrollchange: function(event, scrollPosition) { + module.stick(scrollPosition); + settings.onScroll.call(element); } }, @@ -189,7 +207,7 @@ $.fn.sticky = function(parameters) { }, save: { - scroll: function(scroll) { + lastScroll: function(scroll) { module.lastScroll = scroll; }, positions: function() { @@ -268,6 +286,7 @@ $.fn.sticky = function(parameters) { : Math.abs(parseInt($module.css('bottom'), 10)) || 0 ; }, + elementScroll: function(scroll) { scroll = scroll || $scroll.scrollTop(); var @@ -275,14 +294,14 @@ $.fn.sticky = function(parameters) { window = module.cache.window, delta = module.get.scrollChange(scroll), maxScroll = (element.height - window.height + settings.offset), - currentScroll = module.get.currentElementScroll(), - possibleScroll = (currentScroll + delta), + elementScroll = module.get.currentElementScroll(), + possibleScroll = (elementScroll + delta), elementScroll ; if(module.cache.fits || possibleScroll < 0) { elementScroll = 0; } - else if (possibleScroll > maxScroll ) { + else if(possibleScroll > maxScroll ) { elementScroll = maxScroll; } else { @@ -313,8 +332,8 @@ $.fn.sticky = function(parameters) { $container = $module.offsetParent(); } else { - module.debug('Settings container size', module.cache.context.height); if( Math.abs($container.height() - module.cache.context.height) > 5) { + module.debug('Context has padding, specifying exact height for container', module.cache.context.height); $container.css({ height: module.cache.context.height }); @@ -369,8 +388,9 @@ $.fn.sticky = function(parameters) { } }, - stick: function() { + stick: function(scroll) { var + cachedPosition = scroll || $scroll.scrollTop(), cache = module.cache, fits = cache.fits, element = cache.element, @@ -380,11 +400,13 @@ $.fn.sticky = function(parameters) { ? settings.bottomOffset : settings.offset, scroll = { - top : $scroll.scrollTop() + offset, - bottom : $scroll.scrollTop() + offset + window.height + top : cachedPosition + offset, + bottom : cachedPosition + offset + window.height }, direction = module.get.direction(scroll.top), - elementScroll = module.get.elementScroll(scroll.top), + elementScroll = (fits) + ? 0 + : module.get.elementScroll(scroll.top), // shorthand doesntFit = !fits, @@ -392,7 +414,7 @@ $.fn.sticky = function(parameters) { ; // save current scroll for next run - module.save.scroll(scroll.top); + module.save.lastScroll(scroll.top); if(elementVisible) { @@ -552,13 +574,12 @@ $.fn.sticky = function(parameters) { module.unbind(); module.unfix(); module.resetCSS(); + module.remove.offset(); }, resetCSS: function() { $module .css({ - top : '', - bottom : '', width : '', height : '' }) @@ -788,4 +809,4 @@ $.fn.sticky.settings = { }; -})( jQuery, window , document ); +})( jQuery, window , document ); \ No newline at end of file diff --git a/package.js b/package.js index c1f766f..f4e1109 100644 --- a/package.js +++ b/package.js @@ -5,7 +5,7 @@ var Package.describe({ name : 'semantic:ui', summary : 'Semantic UI - LESS Release of Semantic UI', - version : '1.11.7', + version : '1.12.0', git : 'git://github.com/Semantic-Org/Semantic-UI-LESS.git', }); diff --git a/package.json b/package.json index 3bd3597..4e400cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "semantic-ui-less", - "version": "1.11.7", + "version": "1.12.0", "title": "Semantic UI", "description": "LESS Only distribution of Semantic UI", "homepage": "http://www.semantic-ui.com",