From 1758250f399de14afcc60c3fc7081ec16cac3b23 Mon Sep 17 00:00:00 2001 From: jlukic Date: Tue, 16 Sep 2014 23:49:02 -0400 Subject: [PATCH] Rewrite of sticky's crucial 'stick' function to be more coherent, deal with scrolling better. Fixes to grid/menu/list. Demo page footer --- server/documents/elements/list.html.eco | 2 +- server/files/javascript/semantic.js | 5 +- server/files/stylesheets/semantic.css | 39 +-- server/layouts/default.html.eco | 24 ++ src/definitions/collections/grid.less | 7 +- src/definitions/elements/list.less | 12 +- src/definitions/elements/segment.less | 5 + src/definitions/modules/sticky.js | 267 ++++++++++-------- .../default/collections/grid.variables | 9 +- .../default/collections/menu.variables | 2 +- .../packages/default/elements/list.variables | 17 +- .../packages/default/globals/site.variables | 1 + 12 files changed, 233 insertions(+), 157 deletions(-) diff --git a/server/documents/elements/list.html.eco b/server/documents/elements/list.html.eco index c2e303ae6..e0c08197c 100755 --- a/server/documents/elements/list.html.eco +++ b/server/documents/elements/list.html.eco @@ -837,7 +837,7 @@ themes : ['Default'] - + \ No newline at end of file diff --git a/server/files/javascript/semantic.js b/server/files/javascript/semantic.js index 26789b3c5..9a43a3325 100755 --- a/server/files/javascript/semantic.js +++ b/server/files/javascript/semantic.js @@ -118,7 +118,7 @@ semantic.ready = function() { $examples = $exampleSet.slice(firstIndex, lastIndex + 1), activeClass = (index === 0) ? 'active ' - : 'active ' + : '' ; html += '
'; html += ' ' + $(this).text() + ''; @@ -163,7 +163,8 @@ semantic.ready = function() { $sticky .transition('fade', function() { $sticky.sticky({ - context: $container + context: $container, + offset: 50 }); }) ; diff --git a/server/files/stylesheets/semantic.css b/server/files/stylesheets/semantic.css index 269e72c33..10555e296 100755 --- a/server/files/stylesheets/semantic.css +++ b/server/files/stylesheets/semantic.css @@ -161,7 +161,6 @@ a:hover { border-radius: 0px; } #example #menu .inverted.header { - margin-bottom: 0em; color: rgba(255, 255, 255, 0.8); } #example #menu a.inverted.header.active, @@ -174,9 +173,6 @@ a:hover { #example #menu .menu .active.item { color: #6DFFFF !important; } -#example #menu .item .item { - font-size: 0.875rem; -} /* segment headers */ @@ -754,6 +750,13 @@ body#example.hide { width: auto; } +/*---------------- + Footer +-----------------*/ + +#example .page > .footer { + padding: 4em 0em; +} /*---------------- Settings Table @@ -1438,44 +1441,46 @@ body.progress .ui.progress .bar { } #example .container { position: relative; - right: 100px; width: 915px; margin: 0px auto; } #example .main.container .right.rail .sticky { - padding-top: 50px !important; + padding-bottom: 30px; } @media only screen and (max-width : 600px) { #example .container { width: auto; - margin: 0% 1em 0px; + margin: 0em 1rem; } } -@media only screen and (max-width : 1050px) { +@media only screen and (min-width : 600px) and (max-width : 1000px) { #example .container { width: auto; - margin: 0px 30px 0px; + margin: 0em 3rem; } } - -@media only screen and (max-width : 1325px) { - #example .following.menu { - display: none; - } +@media only screen and (min-width : 1000px) and (max-width: 1325px) { #example .container { width: auto; margin-right: auto; margin-left: auto; max-width: 700px; } - #example.index .container { - margin-left: 8em; - margin-right: 8em; +} +@media only screen and (max-width : 1325px) { + #example .following.menu { + display: none; } } @media only screen and (min-width : 1325px) { + #example .container { + right: 100px; + } + #example .following.menu { + display: block; + } #example .container { width: 850px; } diff --git a/server/layouts/default.html.eco b/server/layouts/default.html.eco index 86d69f90f..180c274f0 100755 --- a/server/layouts/default.html.eco +++ b/server/layouts/default.html.eco @@ -254,6 +254,30 @@
<%- @content %> +
diff --git a/src/definitions/collections/grid.less b/src/definitions/collections/grid.less index 48d5634f4..53d925bee 100755 --- a/src/definitions/collections/grid.less +++ b/src/definitions/collections/grid.less @@ -545,9 +545,14 @@ } /* Inverted Divided */ -.ui.inverted.divided.grid > .row { +.ui.inverted.divided.grid:not(.vertical) > .column, +.ui.inverted.divided.grid:not(.vertical) > .row > .column { box-shadow: @dividedInvertedBorder; } +.ui.inverted.divided.grid:not(.vertical) > .column:first-child, +.ui.inverted.divided.grid:not(.vertical) > .row > .column:first-child { + box-shadow: none; +} .ui.inverted[class*="vertically divided"].grid > .row { box-shadow: @verticallyDividedInvertedBorder; } diff --git a/src/definitions/elements/list.less b/src/definitions/elements/list.less index 67da6bd9d..d24b971d2 100755 --- a/src/definitions/elements/list.less +++ b/src/definitions/elements/list.less @@ -282,14 +282,15 @@ ol.ui.list ol, .ui.link.list a.item, .ui.link.list .item a { color: @linkListItemColor; + transition: @linkListTransition; } .ui.link.list a.item:hover, .ui.link.list .item a:hover { - color:@linkListItemHoverColor; + color: @linkListItemHoverColor; } .ui.link.list a.item:active, .ui.link.list .item a:active { - color:@linkListItemDownColor; + color: @linkListItemDownColor; } .ui.link.list .active.item, .ui.link.list .active.item a { @@ -323,9 +324,14 @@ ol.ui.list ol, cursor: pointer; background: @selectionListBackground; padding: @selectionListItemVerticalPadding @selectionListItemHorizontalPadding; + margin: @selectionListItemMargin; color: @selectionListColor; + border-radius: @selectionListItemBorderRadius; transition: @selectionListTransition; } +.ui.selection.list .item:last-child { + margin-bottom: 0em; +} .ui.selection.list .item:hover { background: @selectionListHoverBackground; color: @selectionListHoverColor; @@ -343,7 +349,7 @@ ol.ui.list ol, .ui.inverted.selection.list .item { background: @invertedSelectionListBackground; - color: @selectionListColor; + color: @invertedSelectionListColor; } .ui.inverted.selection.list .item:hover { background: @invertedSelectionListHoverBackground; diff --git a/src/definitions/elements/segment.less b/src/definitions/elements/segment.less index 6c2125cbb..46e3ccac1 100755 --- a/src/definitions/elements/segment.less +++ b/src/definitions/elements/segment.less @@ -92,6 +92,11 @@ top: 1px; } +/* Header */ +.ui.inverted.segment > .ui.header { + color: @white; +} + /* Label */ .ui[class*="bottom attached"].segment > [class*="top attached"].label { border-top-left-radius: 0em; diff --git a/src/definitions/modules/sticky.js b/src/definitions/modules/sticky.js index f50c5bc24..dad3e8cc3 100755 --- a/src/definitions/modules/sticky.js +++ b/src/definitions/modules/sticky.js @@ -62,9 +62,6 @@ $.fn.sticky = function(parameters) { module = { initialize: function() { - if( !$module.is(':visible') ) { - module.error(error.visible, $module); - } if(settings.context) { $context = $(settings.context); } @@ -75,17 +72,26 @@ $.fn.sticky = function(parameters) { module.error(error.invalidContext, settings.context, $module); return; } - if(module.supports.sticky()) { - // needs to enable native ios support + module.verbose('Initializing sticky', settings, $container); + module.save.positions(); + + // error conditions + if( module.is.hidden() ) { + module.error(error.visible, $module); + } + if(module.cache.element.height > module.cache.context.height) { + module.reset(); + module.error(error.elementSize, $module); + return; } + $window .on('resize' + eventNamespace, module.event.resize) ; $scroll .on('scroll' + eventNamespace, module.event.scroll) ; - module.verbose('Initializing sticky', settings, $container); - module.save.positions(); + module.observeChanges(); module.instantiate(); }, @@ -102,8 +108,10 @@ $.fn.sticky = function(parameters) { module.verbose('Destroying previous module'); module.reset(); $window - .off('resize', module.event.resize) - .off('scroll', module.event.scroll) + .off('resize' + eventNamespace, module.event.resize) + ; + $scroll + .off('scroll' + eventNamespace, module.event.scroll) ; $module .removeData(moduleNamespace) @@ -192,7 +200,7 @@ $.fn.sticky = function(parameters) { } ; module.cache = { - fits : ( element.height < $window.height() ), + fits : ( element.height < window.height ), window: { height: window.height }, @@ -233,30 +241,53 @@ $.fn.sticky = function(parameters) { } return direction; }, - currentOffset: function() { - return ( module.is.top() ) - ? parseInt($module.css('top'), 10) || 0 - : parseInt($module.css('bottom'), 10) || 0 - ; - }, - offsetChange: function(scroll) { + scrollChange: function(scroll) { scroll = scroll || $scroll.scrollTop(); return (module.lastScroll) - ? Math.abs(scroll - module.lastScroll) + ? (scroll - module.lastScroll) : 0 ; }, - newOffset: function(scroll) { + currentElementScroll: function() { + return ( module.is.top() ) + ? Math.abs(parseInt($module.css('top'), 10)) || 0 + : Math.abs(parseInt($module.css('bottom'), 10)) || 0 + ; + }, + elementScroll: function(scroll) { scroll = scroll || $scroll.scrollTop(); var - currentOffset = module.get.currentOffset(), - delta = module.get.offsetChange(scroll) + element = module.cache.element, + window = module.cache.window, + delta = module.get.scrollChange(scroll), + maxScroll = (element.height - window.height + settings.offset), + currentScroll = module.get.currentElementScroll(), + possibleScroll = (currentScroll + delta), + elementScroll ; - return Math.abs(currentOffset - delta); + if(possibleScroll < 0) { + elementScroll = 0; + } + else if (possibleScroll > maxScroll ) { + elementScroll = maxScroll; + } + else { + elementScroll = possibleScroll; + } + return elementScroll; + } + }, + + remove: { + offset: function() { + $module.css('margin-top', ''); } }, set: { + offset: function() { + $module.css('margin-top', settings.offset); + }, containerSize: function() { var tagName = $container.get(0).tagName @@ -270,6 +301,18 @@ $.fn.sticky = function(parameters) { $container.height(module.cache.context.height); } }, + scroll: function(scroll) { + if( module.is.top() ) { + $module + .css('top', -scroll) + ; + } + if( module.is.bottom() ) { + $module + .css('bottom', scroll) + ; + } + }, size: function() { if(module.cache.element.height !== 0 && module.cache.element.width !== 0) { $module @@ -289,6 +332,12 @@ $.fn.sticky = function(parameters) { bottom: function() { return $module.hasClass(className.bottom); }, + initialPosition: function() { + return (!module.is.fixed() && !module.is.bound()); + }, + hidden: function() { + return (!$module.is(':visible')); + }, bound: function() { return $module.hasClass(className.bound); }, @@ -304,114 +353,77 @@ $.fn.sticky = function(parameters) { element = cache.element, window = cache.window, context = cache.context, - scrollTop = $scroll.scrollTop(), - screen = { - top : scrollTop + settings.offset, - bottom : scrollTop + window.height + settings.offset + scrollTop = $scroll.scrollTop() + settings.offset, + scroll = { + top : scrollTop, + bottom : scrollTop + window.height }, direction = module.get.direction(scrollTop), - currentOffset = module.get.currentOffset(), - newOffset = module.get.newOffset(scrollTop), - elementPassed = (screen.bottom > element.top + element.height), - fixedBottom = (cache.element.height + screen.top) + elementScroll = module.get.elementScroll(scrollTop), + + // shorthand + doesntFit = !fits, + elementVisible = (element.height !== 0) ; + // save current scroll for next run module.save.scroll(scrollTop); - if(element.height !== 0) { - - if( module.is.fixed() ) { - if(fits) { - // if module is fixed top - if(module.is.top()) { - if( screen.top < element.top ) { - module.unfix(); - } - else if( fixedBottom > context.bottom ) { - module.debug('Top attached rail has reached bottom of container'); - module.bindBottom(); - } - } - // if module is fixed bottom - if(module.is.bottom() ) { - // top edge - if( (screen.bottom - element.height) < element.top) { - module.unfix(); - } - // bottom edge - else if(screen.bottom > context.bottom) { - module.debug('Bottom attached rail has reached bottom of container'); - module.bindBottom(); - } + + if(elementVisible) { + + if( module.is.initialPosition() ) { + if(scroll.top >= element.top) { + module.debug('Element passed, fixing element to page'); + module.fixTop(); + } + } + else if( module.is.fixed() ) { + + // currently fixed top + if( module.is.top() ) { + + if( scroll.top < element.top ) { + module.debug('Fixed element reached top of container'); + module.setInitialPosition(); } - if( fixedBottom > context.bottom ) { + else if( (element.height + scroll.top) > context.bottom ) { + module.debug('Fixed element reached bottom of container'); module.bindBottom(); } } - else { - if(screen.bottom > context.bottom) { - module.bindBottom(); - } - else if(elementPassed) { - if(module.is.top() && direction == 'down') { - module.debug('Stuck content at bottom edge'); - if(newOffset >= (element.height - window.height)) { - $module - .css('top', '') - ; - module.stickBottom(); - } - else { - $module - .css('top', -newOffset) - ; - } - } - if(module.is.bottom() && direction == 'up') { - module.debug('Stuck content at top edge'); - if(newOffset >= (element.height - window.height)) { - $module - .css('bottom', '') - ; - module.stickTop(); - } - else { - $module - .css('bottom', -newOffset) - ; - } - } + + // currently fixed bottom + if(module.is.bottom() ) { + + // top edge + if( (scroll.bottom - element.height) < element.top) { + module.setInitialPosition(); } - else { - module.unfix(); + // bottom edge + else if(scroll.bottom > context.bottom) { + module.debug('Bottom attached rail has reached bottom of container'); + module.bindBottom(); } + } - } - else { - // determine if needs to be bound - if(screen.top + element.height > context.bottom) { - module.bindBottom(); + + // scroll element if larger than screen + if(doesntFit) { + module.set.scroll(elementScroll); } - if(fits) { - // fix to bottom of screen on way back up - if(module.is.bottom() ) { - if(settings.pushing) { - if(module.is.bound() && screen.bottom < context.bottom ) { - module.stickBottom(); - } - } - else { - if(module.is.bound() && screen.top < context.bottom - element.height) { - module.stickTop(); - } + } + else if( module.is.bottom() ) { + // fix to bottom of screen on way back up + if( module.is.bottom() ) { + if(settings.pushing) { + if(module.is.bound() && scroll.bottom < context.bottom ) { + module.fixBottom(); } } - else if(screen.top >= element.top && screen.top < context.bottom - element.height) { - module.stickTop(); - } - } - else { - if(elementPassed && screen.bottom < context.bottom ) { - module.stickBottom(); + else { + if(module.is.bound() && (scroll.top < context.bottom - element.height) ) { + module.fixTop(); + } } } } @@ -420,6 +432,7 @@ $.fn.sticky = function(parameters) { bindTop: function() { module.debug('Binding element to top of parent container'); + module.remove.offset(); $module .css('left' , '') .removeClass(className.fixed) @@ -432,6 +445,7 @@ $.fn.sticky = function(parameters) { }, bindBottom: function() { module.debug('Binding element to bottom of parent container'); + module.remove.offset(); $module .css('left' , '') .removeClass(className.fixed) @@ -443,8 +457,15 @@ $.fn.sticky = function(parameters) { $.proxy(settings.onUnstick, element)(); }, - stickTop: function() { + setInitialPosition: function() { + module.unfix(); + module.unbind(); + }, + + + fixTop: function() { module.debug('Fixing element to top of page'); + module.set.offset(); $module .css('left', module.cache.element.left) .removeClass(className.bound) @@ -455,8 +476,9 @@ $.fn.sticky = function(parameters) { $.proxy(settings.onStick, element)(); }, - stickBottom: function() { + fixBottom: function() { module.debug('Sticking element to bottom of page'); + module.set.offset(); $module .css('left', module.cache.element.left) .removeClass(className.bound) @@ -469,6 +491,7 @@ $.fn.sticky = function(parameters) { unbind: function() { module.debug('Removing absolute position on element'); + module.remove.offset(); $module .removeClass(className.bound) .removeClass(className.top) @@ -478,6 +501,7 @@ $.fn.sticky = function(parameters) { unfix: function() { module.debug('Removing fixed position on element'); + module.remove.offset(); $module .removeClass(className.fixed) .removeClass(className.top) @@ -689,9 +713,9 @@ $.fn.sticky.settings = { name : 'Sticky', namespace : 'sticky', - verbose : false, - debug : false, - performance : false, + verbose : true, + debug : true, + performance : true, pushing : false, @@ -710,7 +734,8 @@ $.fn.sticky.settings = { container : 'Sticky element must be inside a relative container', visible : 'Element is hidden, you must call refresh after element becomes visible', method : 'The method you called is not defined.', - invalidContext : 'Context specified does not exist' + invalidContext : 'Context specified does not exist', + elementSize : 'Sticky element is larger than its container, cannot create sticky.' }, className : { diff --git a/src/themes/packages/default/collections/grid.variables b/src/themes/packages/default/collections/grid.variables index d0a479050..e295be092 100755 --- a/src/themes/packages/default/collections/grid.variables +++ b/src/themes/packages/default/collections/grid.variables @@ -59,8 +59,8 @@ ---------------*/ @dividedBorder: - -1px 0px 0px 0px rgba(0, 0, 0, 0.1), - -2px 0px 0px 0px rgba(255, 255, 255, 0.3) + -1px 0px 0px 0px rgba(255, 255, 255, 0.1), + -2px 0px 0px 0px rgba(0, 0, 0, 0.3) ; @verticallyDividedBorder: 0px -1px 0px 0px rgba(0, 0, 0, 0.1), @@ -68,15 +68,14 @@ ; @dividedInvertedBorder: - -1px 0px 0px 0px rgba(0, 0, 0, 0.15), + -1px 0px 0px 0px rgba(255, 255, 255, 0.15), -2px 0px 0px 0px rgba(0, 0, 0, 0.15) ; @verticallyDividedInvertedBorder: 0px -1px 0px 0px rgba(0, 0, 0, 0.15), - 0px -2px 0px 0px rgba(0, 0, 0, 0.15) + 0px -2px 0px 0px rgba(255, 255, 255, 0.15) ; - /*-------------- Celled ---------------*/ diff --git a/src/themes/packages/default/collections/menu.variables b/src/themes/packages/default/collections/menu.variables index 648beda3c..19f7b2479 100755 --- a/src/themes/packages/default/collections/menu.variables +++ b/src/themes/packages/default/collections/menu.variables @@ -60,7 +60,7 @@ /* Sub Menu */ @subMenuMargin: 0.5em; @subMenuFontSize: 0.875rem; -@subMenuTextColor: @textColor; +@subMenuTextColor: @unselectedTextColor; @subMenuHorizontalPadding: 0.5rem; @subMenuVerticalPadding: 1.5rem; diff --git a/src/themes/packages/default/elements/list.variables b/src/themes/packages/default/elements/list.variables index 0a97094c2..e7cbfecd1 100755 --- a/src/themes/packages/default/elements/list.variables +++ b/src/themes/packages/default/elements/list.variables @@ -83,20 +83,25 @@ @linkListItemHoverColor: @hoveredTextColor; @linkListItemDownColor: @pressedTextColor; @linkListItemActiveColor: @selectedTextColor; +@linkListTransition: + 0.2s color @defaultEasing +; /* Inverted Link List */ @invertedLinkListItemColor: @invertedUnselectedTextColor; -@invertedLinkListItemHoverColor: @invertedUnselectedTextColor; -@invertedLinkListItemDownColor: @invertedTextColor; +@invertedLinkListItemHoverColor: @invertedHoveredTextColor; +@invertedLinkListItemDownColor: @invertedPressedTextColor; @invertedLinkListItemActiveColor: @invertedSelectedTextColor; /* Selection List */ +@selectionListItemMargin: 0em 0em 0.3em 0em; +@selectionListItemBorderRadius: 0.5em; @selectionListItemVerticalPadding: 0.5em; @selectionListItemHorizontalPadding: 0.5em; @selectionListTransition: - 0.2s color ease, - 0.2s padding-left ease, - 0.2s background-color ease + 0.2s color @defaultEasing, + 0.2s padding-left @defaultEasing, + 0.2s background-color @defaultEasing ; /* Selection List States */ @selectionListBackground: transparent; @@ -114,7 +119,7 @@ @invertedSelectionListHoverBackground: @subtleTransparentWhite; @invertedSelectionListHoverColor: @invertedHoveredTextColor; @invertedSelectionListDownBackground: @transparentWhite; -@invertedSelectionListDownColor: @invertedHoveredTextColor; +@invertedSelectionListDownColor: @invertedPressedTextColor; @invertedSelectionListActiveBackground: @transparentWhite; @invertedSelectionListActiveColor: @invertedSelectedTextColor; diff --git a/src/themes/packages/default/globals/site.variables b/src/themes/packages/default/globals/site.variables index 4b19a404d..ba5df14cd 100755 --- a/src/themes/packages/default/globals/site.variables +++ b/src/themes/packages/default/globals/site.variables @@ -151,6 +151,7 @@ @tealBackground : #D2F5F5; @yellowBackground : #FCF5D8; + /*--- Colored Text ---*/ @blueTextColor : @blue; @orangeTextColor : @orange;