From 30777178e3311c8aa7f4ecae82bd970fda63d85c Mon Sep 17 00:00:00 2001
From: Phil Hughes <me@iamphill.com>
Date: Fri, 28 Jul 2017 11:54:51 +0100
Subject: [PATCH] fixed jumping when bar gets stuck added specs to sticky util
 file added `No files found.` text when results are empty

---
 app/assets/javascripts/gl_dropdown.js      |  6 ++-
 app/assets/javascripts/lib/utils/sticky.js |  6 +--
 app/assets/stylesheets/pages/diff.scss     | 21 ++++++---
 app/views/projects/diffs/_stats.html.haml  |  7 ++-
 spec/javascripts/lib/utils/sticky_spec.js  | 52 ++++++++++++++++++++++
 5 files changed, 78 insertions(+), 14 deletions(-)
 create mode 100644 spec/javascripts/lib/utils/sticky_spec.js

diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js
index 85d720c3a69..73874363c1f 100644
--- a/app/assets/javascripts/gl_dropdown.js
+++ b/app/assets/javascripts/gl_dropdown.js
@@ -114,7 +114,7 @@ GitLabDropdownFilter = (function() {
     } else {
       elements = this.options.elements();
       if (search_text) {
-        return elements.each(function() {
+        elements.each(function() {
           var $el, matches;
           $el = $(this);
           matches = fuzzaldrinPlus.match($el.text().trim(), search_text);
@@ -127,8 +127,10 @@ GitLabDropdownFilter = (function() {
           }
         });
       } else {
-        return elements.show().removeClass('option-hidden');
+        elements.show().removeClass('option-hidden');
       }
+
+      elements.parent().find('.dropdown-menu-empty-link').toggleClass('hidden', elements.is(':visible'));
     }
   };
 
diff --git a/app/assets/javascripts/lib/utils/sticky.js b/app/assets/javascripts/lib/utils/sticky.js
index f53acaa17b1..b5fde040a17 100644
--- a/app/assets/javascripts/lib/utils/sticky.js
+++ b/app/assets/javascripts/lib/utils/sticky.js
@@ -1,5 +1,5 @@
-export const isSticky = (el, stickyTop) => {
-  const top = el.getBoundingClientRect().top;
+export const isSticky = (el, scrollY, stickyTop) => {
+  const top = el.offsetTop - scrollY;
 
   if (top === stickyTop) {
     el.classList.add('is-stuck');
@@ -15,7 +15,7 @@ export default (el) => {
 
   const stickyTop = parseInt(computedStyle.top, 10);
 
-  document.addEventListener('scroll', () => isSticky(el, stickyTop), {
+  document.addEventListener('scroll', () => isSticky(el, window.scrollY, stickyTop), {
     passive: true,
   });
 };
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index 7d765f45812..f98129bc09d 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -562,12 +562,18 @@
 .diff-files-changed {
   .commit-stat-summary {
     z-index: -1;
+
+    @media (min-width: $screen-sm-min) {
+      margin-left: -$gl-padding;
+      padding-left: $gl-padding;
+      background-color: $white-light;
+    }
   }
 
   @media (min-width: $screen-sm-min) {
     position: -webkit-sticky;
     position: sticky;
-    top: 100px;
+    top: 84px;
     background-color: $white-light;
     z-index: 190;
 
@@ -575,7 +581,7 @@
       margin-top: 1px;
     }
 
-    .diff-stats-additions-deletions-collapsed {
+    &:not(.is-stuck) .diff-stats-additions-deletions-collapsed {
       display: none;
     }
 
@@ -583,18 +589,15 @@
       padding-top: 0;
       padding-bottom: 0;
       border-bottom: 1px solid $white-dark;
+      transform: translateY(16px);
 
       .diff-stats-additions-deletions-expanded,
       .inline-parallel-buttons {
         display: none;
       }
 
-      .diff-stats-additions-deletions-collapsed {
-        display: block;
-      }
-
       + .files {
-        margin-top: 16px;
+        margin-top: 30px;
       }
     }
   }
@@ -604,6 +607,10 @@
   width: 450px;
   z-index: 150;
 
+  @media (min-width: $screen-sm-min) {
+    left: $gl-padding;
+  }
+
   a {
     padding-top: 8px;
     padding-bottom: 8px;
diff --git a/app/views/projects/diffs/_stats.html.haml b/app/views/projects/diffs/_stats.html.haml
index 4f784f87f2b..7c2941e6be3 100644
--- a/app/views/projects/diffs/_stats.html.haml
+++ b/app/views/projects/diffs/_stats.html.haml
@@ -5,12 +5,12 @@
   %button.diff-stats-summary-toggler.js-diff-stats-dropdown{ type: "button", data: { toggle: "dropdown" } }<
     = pluralize(diff_files.size, "changed file")
     = icon("caret-down fw")
-  %span.diff-stats-additions-deletions-expanded
+  %span.diff-stats-additions-deletions-expanded#diff-stats
     with
     %strong.cgreen #{sum_added_lines} additions
     and
     %strong.cred #{sum_removed_lines} deletions
-  .diff-stats-additions-deletions-collapsed.pull-right{ "aria-hidden": "true" }
+  .diff-stats-additions-deletions-collapsed.pull-right{ "aria-hidden": "true", "aria-describedby": "diff-stats" }
     %strong.cgreen<
       +#{sum_added_lines}
     %strong.cred<
@@ -32,3 +32,6 @@
                   +#{added_lines}
                 %span.cred<
                   \-#{removed_lines}
+        %li.dropdown-menu-empty-link.hidden
+          %a{ href: "#" }
+            No files found.
diff --git a/spec/javascripts/lib/utils/sticky_spec.js b/spec/javascripts/lib/utils/sticky_spec.js
new file mode 100644
index 00000000000..c3ee3ef9825
--- /dev/null
+++ b/spec/javascripts/lib/utils/sticky_spec.js
@@ -0,0 +1,52 @@
+import { isSticky } from '~/lib/utils/sticky';
+
+describe('sticky', () => {
+  const el = {
+    offsetTop: 0,
+    classList: {},
+  };
+
+  beforeEach(() => {
+    el.offsetTop = 0;
+    el.classList.add = jasmine.createSpy('spy');
+    el.classList.remove = jasmine.createSpy('spy');
+  });
+
+  describe('classList.remove', () => {
+    it('does not call classList.remove when stuck', () => {
+      isSticky(el, 0, 0);
+
+      expect(
+        el.classList.remove,
+      ).not.toHaveBeenCalled();
+    });
+
+    it('calls classList.remove when not stuck', () => {
+      el.offsetTop = 10;
+      isSticky(el, 0, 0);
+
+      expect(
+        el.classList.remove,
+      ).toHaveBeenCalledWith('is-stuck');
+    });
+  });
+
+  describe('classList.add', () => {
+    it('calls classList.add when stuck', () => {
+      isSticky(el, 0, 0);
+
+      expect(
+        el.classList.add,
+      ).toHaveBeenCalledWith('is-stuck');
+    });
+
+    it('does not call classList.add when not stuck', () => {
+      el.offsetTop = 10;
+      isSticky(el, 0, 0);
+
+      expect(
+        el.classList.add,
+      ).not.toHaveBeenCalled();
+    });
+  });
+});
-- 
GitLab