From 7ab43524055ec694a8da76aea661358a01c7758e Mon Sep 17 00:00:00 2001 From: Thibaut Date: Tue, 19 Nov 2013 22:11:48 +0100 Subject: [PATCH] Expand truncated sidebar items on hover/focus --- .../javascripts/templates/sidebar_tmpl.coffee | 6 +- .../javascripts/views/sidebar/sidebar.coffee | 2 + .../views/sidebar/sidebar_hover.coffee | 100 ++++++++++++++++++ assets/stylesheets/components/_sidebar.scss | 47 +++++++- assets/stylesheets/global/_base.scss | 1 - assets/stylesheets/global/_variables.scss | 1 + 6 files changed, 151 insertions(+), 6 deletions(-) create mode 100644 assets/javascripts/views/sidebar/sidebar_hover.coffee diff --git a/assets/javascripts/templates/sidebar_tmpl.coffee b/assets/javascripts/templates/sidebar_tmpl.coffee index 543c9f90..2e3f583c 100644 --- a/assets/javascripts/templates/sidebar_tmpl.coffee +++ b/assets/javascripts/templates/sidebar_tmpl.coffee @@ -12,12 +12,10 @@ templates.sidebarType = (type) -> """#{type.count}#{type.name}""" templates.sidebarEntry = (entry) -> - name = $.escape(entry.name) - """#{name}""" + """#{$.escape entry.name}""" templates.sidebarResult = (entry) -> - name = $.escape(entry.name) - """#{name}""" + """#{$.escape entry.name}""" templates.sidebarPageLink = (count) -> """Show moreā€¦ (#{count})""" diff --git a/assets/javascripts/views/sidebar/sidebar.coffee b/assets/javascripts/views/sidebar/sidebar.coffee index 2133f8c6..04d533f3 100644 --- a/assets/javascripts/views/sidebar/sidebar.coffee +++ b/assets/javascripts/views/sidebar/sidebar.coffee @@ -8,6 +8,7 @@ class app.views.Sidebar extends app.View escape: 'onEscape' init: -> + @addSubview @hover = new app.views.SidebarHover @el unless $.isTouchScreen() @addSubview @search = new app.views.Search @search @@ -24,6 +25,7 @@ class app.views.Sidebar extends app.View show: (view) -> unless @view is view + @hover?.hide() @saveScrollPosition() @view?.deactivate() @html @view = view diff --git a/assets/javascripts/views/sidebar/sidebar_hover.coffee b/assets/javascripts/views/sidebar/sidebar_hover.coffee new file mode 100644 index 00000000..3bbdacaa --- /dev/null +++ b/assets/javascripts/views/sidebar/sidebar_hover.coffee @@ -0,0 +1,100 @@ +class app.views.SidebarHover extends app.View + @itemClass: '_list-hover' + + @events: + focus: 'onFocus' + blur: 'onBlur' + mouseover: 'onMouseover' + mouseout: 'onMouseout' + scroll: 'onScroll' + click: 'onClick' + + @routes: + after: 'onRoute' + + constructor: (@el) -> + unless isPointerEventsSupported() + delete @constructor.events.mouseover + super + + init: -> + @offsetTop = @el.offsetTop + return + + show: (el) -> + unless el is @cursor + @hide() + if @isTarget(el) and @isTruncated(el) + @cursor = el + @clone = @makeClone @cursor + $.append document.body, @clone + @position() + return + + hide: -> + if @cursor + $.remove @clone + @cursor = @clone = null + return + + position: => + if @cursor + top = $.rect(@cursor).top + if top > @offsetTop + @clone.style.top = top + 'px' + else + @hide() + return + + makeClone: (el) -> + clone = el.cloneNode() + clone.textContent = el.textContent + clone.classList.add 'clone' + clone + + isTarget: (el) -> + el.classList.contains @constructor.itemClass + + isTruncated: (el) -> + el.scrollWidth >= el.offsetWidth + + onFocus: (event) => + @focusTime = Date.now() + @show event.target + return + + onBlur: => + @hide() + return + + onMouseover: (event) => + if @isTarget(event.target) and @mouseActivated() + @show event.target + return + + onMouseout: (event) => + if @isTarget(event.target) and @mouseActivated() + @hide() + return + + mouseActivated: -> + # Skip mouse events caused by focus events scrolling the sidebar. + not @focusTime or Date.now() - @focusTime > 500 + + onScroll: => + @position() + return + + onClick: (event) => + if event.target is @clone + $.click @cursor + return + + onRoute: => + @hide() + return + +isPointerEventsSupported = -> + el = document.createElement 'div' + el.style.cssText = 'pointer-events: auto' + el.style.pointerEvents is 'auto' diff --git a/assets/stylesheets/components/_sidebar.scss b/assets/stylesheets/components/_sidebar.scss index 4bf3f743..b84813ee 100644 --- a/assets/stylesheets/components/_sidebar.scss +++ b/assets/stylesheets/components/_sidebar.scss @@ -64,7 +64,9 @@ line-height: 1.75rem; font-size: .875rem; white-space: nowrap; + word-wrap: normal; text-overflow: ellipsis; + text-shadow: 0 1px rgba(white, .3); border: solid transparent; border-width: 1px 1px 1px 0; cursor: default; @@ -83,7 +85,7 @@ background: -webkit-linear-gradient(top, #bfc6dd, #949eb8); background: linear-gradient(to bottom, #bfc6dd, #949eb8); border-color: #96a1c6 #8e99b7 #7f87a4; - box-shadow: inset 0 1px rgba(white, .15), // top inner glow + box-shadow: inset 0 1px rgba(white, .15), // top inner glow inset 0 0 0 1px rgba(white, .08), // inner glow 0 1px rgba(black, .05); // drop shadow } @@ -178,6 +180,49 @@ } } +// +// List hover clone +// + +._list-hover.clone { + position: fixed; + z-index: $hoverZ; + left: 0; + overflow: visible; + background-color: #e5eaf4; + pointer-events: none; + -webkit-font-smoothing: subpixel-antialiased; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + + &:not(._list-result) { + padding-left: 2.75rem; + + &:before { content: none; } + } + + &:not(.focus):not(.active):after { + content: ''; + position: absolute; + top: -1px; + bottom: -1px; + left: $sidebarWidth; + right: -2px; + margin-left: -1px; + border: 1px solid #bbc1cc; + border-left-width: 0; + border-radius: 0 2px 2px 0; + box-shadow: inset -1px 0 rgba(white, .15), // right inner glow + inset 0 1px rgba(white, .15), // top inner glow + inset 0 -1px rgba(white, .15), // bottom inner glow + 1px 0 rgba(black, .04), // right shadow + 0 1px rgba(black, .04), // bottom shadow + 0 -1px rgba(black, .02); // top shadow + + @media #{$mediumScreen} { left: $sidebarMediumWidth; } + } +} + // // List picker // diff --git a/assets/stylesheets/global/_base.scss b/assets/stylesheets/global/_base.scss index cc1519fa..23a55f2e 100644 --- a/assets/stylesheets/global/_base.scss +++ b/assets/stylesheets/global/_base.scss @@ -11,7 +11,6 @@ body { height: 100%; font: normal 1em/1.7 $baseFont; color: $textColor; - overflow-wrap: break-word; word-wrap: break-word; -webkit-tap-highlight-color: rgba(black, 0); -webkit-touch-callout: none; diff --git a/assets/stylesheets/global/_variables.scss b/assets/stylesheets/global/_variables.scss index 57b74412..6bc88956 100644 --- a/assets/stylesheets/global/_variables.scss +++ b/assets/stylesheets/global/_variables.scss @@ -19,3 +19,4 @@ $headerZ: 1; $sidebarZ: 2; $contentZ: 3; $noticeZ: 4; +$hoverZ: 5;