diff --git a/src/behaviors/visibility.js b/src/behaviors/visibility.js new file mode 100644 index 000000000..f94a7e4ae --- /dev/null +++ b/src/behaviors/visibility.js @@ -0,0 +1,471 @@ +/* + * # Semantic - Visibility + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.visibility = function(parameters) { + var + $allModules = $(this), + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + returnedValue + ; + + $allModules + .each(function() { + var + settings = $.extend(true, {}, $.fn.visibility.settings, parameters), + + className = settings.className, + namespace = settings.namespace, + error = settings.error, + + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + + $module = $(this), + $window = $(window), + $container = $module.offsetParent(), + $context, + + selector = $module.selector || '', + instance = $module.data(moduleNamespace), + + requestAnimationFrame = window.requestAnimationFrame + || window.mozRequestAnimationFrame + || window.webkitRequestAnimationFrame + || window.msRequestAnimationFrame + || function(callback) { setTimeout(callback, 0); }, + + element = this, + module + ; + + module = { + + initialize: function() { + module.verbose('Initializing visibility', settings); + + module.reset(); + module.save.position(); + module.bindEvents(); + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, module) + ; + }, + + destroy: function() { + module.verbose('Destroying previous module'); + $window + .off(eventNamespace) + ; + $module + .off(eventNamespace) + .removeData(moduleNamespace) + ; + }, + + bindEvents: function() { + $window + .on('resize', module.event.resize) + .on('scroll', module.event.scroll) + ; + }, + + event: { + resize: function() { + requestAnimationFrame(module.refresh); + }, + scroll: function() { + requestAnimationFrame(function() { + module.checkVisibility(); + $.proxy(settings.onScroll, element)(); + }); + } + }, + + refresh: function() { + module.save.position(); + module.checkVisibility(); + $.proxy(settings.onRefresh, element)(); + }, + + reset: function() { + module.cache = { + screen : {}, + element : {} + }; + }, + + checkVisibility: function() { + module.save.scroll(); + module.save.direction(); + module.save.screenCalculations(); + module.save.elementCalculations(); + module.debug('Updating visibility of element', module.cache.element); + }, + + save: { + scroll: function() { + module.cache.scroll = $window.scrollTop() + settings.offset; + }, + direction: function() { + var + scroll = module.get.scroll(), + lastScroll = module.get.lastScroll(), + direction + ; + if(scroll > lastScroll && lastScroll) { + direction = 'down'; + } + else if(scroll < lastScroll && lastScroll) { + direction = 'up'; + } + else { + direction = 'static'; + } + module.cache.direction = direction; + return module.cache.direction; + }, + elementPosition: function() { + var + screen = module.get.screenSize() + ; + module.verbose('Saving element position'); + $.extend(module.cache.element, { + margin : { + top : parseInt($module.css('margin-top'), 10), + bottom : parseInt($module.css('margin-bottom'), 10) + }, + fits : (element.height < screen.height), + offset : $module.offset(), + width : $module.outerWidth(), + height : $module.outerHeight() + }); + return module.cache.element; + }, + elementCalculations: function() { + var + screen = module.get.screenCalculations(), + element = module.get.elementPosition() + ; + // offset + if(settings.includeMargin) { + $.extend(module.cache.element, { + top : element.offset.top - element.margin.top, + bottom : element.offset.top + element.height + element.margin.bottom + }); + } + else { + $.extend(module.cache.element, { + top : element.offset.top, + bottom : element.offset.top + element.height + }); + } + // visibility + $.extend(module.cache.element, { + topVisible : (screen.bottom > element.top), + topPassed : (screen.top > element.top), + bottomVisible : (screen.bottom > element.bottom), + bottomPassed : (screen.top > element.bottom) + }); + // meta calculations + $.extend(module.cache.element, { + visible : (module.cache.element.topVisible || module.cache.element.bottomVisible), + hidden : (!module.cache.element.topVisible && !module.cache.element.bottomVisible) + }); + }, + screenCalculations: function() { + var + scroll = $window.scrollTop() + ; + if(module.cache.scroll === undefined) { + module.cache.scroll = $window.scrollTop(); + } + module.save.direction(); + $.extend(module.cache.screen, { + top : scroll + settings.offset, + bottom : scroll + settings.offset + module.cache.screen.height + }); + return module.cache.screen; + }, + screenSize: function() { + module.verbose('Saving window position'); + module.cache.screen = { + height: $window.height() + }; + }, + position: function() { + module.save.screenSize(); + module.save.elementPosition(); + } + }, + + get: { + direction: function() { + if(module.cache.direction === undefined) { + module.save.direction(); + } + return module.cache.direction; + }, + elementPosition: function() { + if(module.cache.element === undefined) { + module.save.elementPosition(); + } + return module.cache.element; + }, + elementCalculations: function() { + if(module.cache.element === undefined) { + module.save.elementCalculations(); + } + return module.cache.element; + }, + screenCalculations: function() { + if(module.cache.screen === undefined) { + module.save.screenCalculations(); + } + return module.cache.screen; + }, + screenSize: function() { + if(module.cache.screen === undefined) { + module.save.screenSize(); + } + return module.cache.screen; + }, + scroll: function() { + if(module.cache.scroll === undefined) { + module.save.scroll(); + } + return module.cache.scroll; + }, + lastScroll: function() { + if(module.cache.screen === undefined) { + module.debug('First scroll event, no last scroll could be found'); + return false; + } + return module.cache.screen.top; + } + }, + + setting: function(name, value) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else if(value !== undefined) { + settings[name] = value; + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else if(value !== undefined) { + module[name] = value; + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + object = instance, + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && object !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { + object = object[camelCaseValue]; + } + else if( object[camelCaseValue] !== undefined ) { + found = object[camelCaseValue]; + return false; + } + else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { + object = object[value]; + } + else if( object[value] !== undefined ) { + found = object[value]; + return false; + } + else { + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(returnedValue)) { + returnedValue.push(response); + } + else if(returnedValue !== undefined) { + returnedValue = [returnedValue, response]; + } + else if(response !== undefined) { + returnedValue = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) + ; + + return (returnedValue !== undefined) + ? returnedValue + : this + ; +}; + +$.fn.visibility.settings = { + + name : 'Visibility', + namespace : 'visibility', + + verbose : false, + debug : false, + performance : true, + + offset : 0, + includeMargin : false, + + onTopVisible : function(){}, + onBottomVisible : function(){}, + onTopPassed : function(){}, + onBottomPassed : function(){}, + + onRefresh : function(){}, + onScroll : function(){}, + + error : { + method : 'The method you called is not defined.' + } + +}; + +})( jQuery, window , document ); diff --git a/src/collections/grid.less b/src/collections/grid.less index 893b3fa8c..0b683ddb3 100755 --- a/src/collections/grid.less +++ b/src/collections/grid.less @@ -369,6 +369,11 @@ body > .ui.grid { padding-right: @veryRelaxedGutterWidth; } +.ui.vertically.divided.grid > .row:before { + margin-left: @relaxedGutterWidth; + margin-right: @relaxedGutterWidth; +} + /*---------------------- Fitted -----------------------*/ @@ -383,6 +388,12 @@ body > .ui.grid { margin-right: -@relaxedGutterWidth; } +.ui.vertically.divided.fitted.grid > .row:before { + margin-left: 0%; + margin-right: 0%; +} + + /*---------------------- "Floated" -----------------------*/ @@ -826,6 +837,8 @@ body > .ui.grid { padding: 0em; margin: 0em; } + .ui.stackable.grid > .row > .wide.column, + .ui.stackable.grid > .wide.column, .ui.stackable.grid > .row > .column, .ui.stackable.grid > .column { display: block !important; diff --git a/src/modules/popup.js b/src/modules/popup.js index 7e3d25f7d..0dee4e43c 100755 --- a/src/modules/popup.js +++ b/src/modules/popup.js @@ -1,6 +1,6 @@ /* * # Semantic - Popup - * http://github.com/semantic-org/semantic-ui/ + * http://github.com/jlukic/semantic-ui/ * * * Copyright 2013 Contributors @@ -167,14 +167,12 @@ $.fn.popup = function(parameters) { if(settings.inline) { module.verbose('Inserting popup element inline', $popup); $popup - .data(moduleNamespace, instance) .insertAfter($module) ; } else { module.verbose('Appending popup element to body', $popup); $popup - .data(moduleNamespace, instance) .appendTo( $context ) ; } @@ -209,9 +207,10 @@ $.fn.popup = function(parameters) { if( !module.exists() ) { module.create(); } - module.save.conditions(); - module.set.position(); - module.animate.show(callback); + if( module.set.position() ) { + module.save.conditions(); + module.animate.show(callback); + } }, @@ -220,9 +219,9 @@ $.fn.popup = function(parameters) { $module .removeClass(className.visible) ; - module.restore.conditions(); module.unbind.close(); if( module.is.visible() ) { + module.restore.conditions(); module.animate.hide(callback); } }, @@ -276,8 +275,8 @@ $.fn.popup = function(parameters) { conditions: function() { if(module.cache && module.cache.title) { $module.attr('title', module.cache.title); - module.verbose('Restoring original attributes', module.cache.title); } + module.verbose('Restoring original attributes', module.cache.title); return true; } }, @@ -463,7 +462,7 @@ $.fn.popup = function(parameters) { break; case 'top center': positioning = { - bottom : parentHeight - offset.top + distanceAway, + bottom : parentHeight - offset.top + distanceAway, left : offset.left + (width / 2) - (popupWidth / 2) + arrowOffset, top : 'auto', right : 'auto' @@ -472,14 +471,14 @@ $.fn.popup = function(parameters) { case 'top right': positioning = { top : 'auto', - bottom : parentHeight - offset.top + distanceAway, + bottom : parentHeight - offset.top + distanceAway, left : offset.left + width + arrowOffset, right : 'auto' }; break; case 'left center': positioning = { - top : offset.top + (height / 2) - (popupHeight / 2) + arrowOffset, + top : offset.top + (height / 2) - (popupHeight / 2) + arrowOffset, right : parentWidth - offset.left + distanceAway, left : 'auto', bottom : 'auto' @@ -487,7 +486,7 @@ $.fn.popup = function(parameters) { break; case 'right center': positioning = { - top : offset.top + (height / 2) - (popupHeight / 2) + arrowOffset, + top : offset.top + (height / 2) - (popupHeight / 2) + arrowOffset, left : offset.left + width + distanceAway, bottom : 'auto', right : 'auto' @@ -495,7 +494,7 @@ $.fn.popup = function(parameters) { break; case 'bottom left': positioning = { - top : offset.top + height + distanceAway, + top : offset.top + height + distanceAway, right : parentWidth - offset.left - arrowOffset, left : 'auto', bottom : 'auto' @@ -503,7 +502,7 @@ $.fn.popup = function(parameters) { break; case 'bottom center': positioning = { - top : offset.top + height + distanceAway, + top : offset.top + height + distanceAway, left : offset.left + (width / 2) - (popupWidth / 2) + arrowOffset, bottom : 'auto', right : 'auto' @@ -511,7 +510,7 @@ $.fn.popup = function(parameters) { break; case 'bottom right': positioning = { - top : offset.top + height + distanceAway, + top : offset.top + height + distanceAway, left : offset.left + width + arrowOffset, bottom : 'auto', right : 'auto' @@ -594,10 +593,16 @@ $.fn.popup = function(parameters) { reset: function() { $popup - .attr('style', '') - .removeAttr('style') + .removeClass(className.visible) ; - if(!settings.preserve) { + if(settings.preserve) { + if($.fn.transition !== undefined) { + $popup + .transition('remove transition') + ; + } + } + else { module.remove(); } }, diff --git a/src/modules/transition.js b/src/modules/transition.js index 295f66a7c..a2cadf8c4 100755 --- a/src/modules/transition.js +++ b/src/modules/transition.js @@ -1,6 +1,6 @@ /* * # Semantic - Transition - * http://github.com/semantic-org/semantic-ui/ + * http://github.com/jlukic/semantic-ui/ * * * Copyright 2013 Contributors @@ -374,6 +374,13 @@ $.fn.transition = function() { .removeClass(className.looping) ; module.forceRepaint(); + }, + + transition: function() { + $module + .removeClass(className.visible) + .removeClass(className.hidden) + ; } },