• 
      

    [WIP] Added a floating banner to the diff view

    Review Request #8746 — Created Feb. 14, 2017 and discarded

    Information

    Review Board
    master

    Reviewers

    We currently have to scroll all the way to the top if we want to be navigated to a
    specific diff file.

    I added a floating banner to the diff view that sticks to the top of the page when
    the user has scrolled down on the page. On this banner, I will further add a
    collapsed list of the diff files, showing only the the file that the user is currently
    looking at. The user will be able to expand this list to navigate to the other files.

    Screenshots and demo video: Notion

    I have tested the floating banner on the dev server on review requests with multiple
    diff files.

    I have started writing jasmine tests for the floating banner. This is still a WIP.
    The banner has been manually tested (including responsiveness) on Chrome, Safari, and
    Firefox. Click here to see GIFs of the manual tests (running on diff revision 13).

    Further testing on other browsers are required.

    Description From Last Updated

    I think this would be more readable if this else was on a new line.

    DA DanielPBak

    Same here.

    DA DanielPBak

    remove blank line

    RK rkdhatt

    Alphabetize

    brenniebrennie

    Doc comments begin with /**.

    brenniebrennie

    Doc comments begin with /** in JS

    brenniebrennie

    How about viewType

    brenniebrennie

    This can always run, since it is just a call to bind. It doesn't hurt. Alternatively we can add this …

    brenniebrennie

    Instead of using each, we should do a for loop. That way we can break out after finding the element …

    brenniebrennie

    This isnt a jQuery. To get a jQuery (and use the .show() method i suggested) use this._$items.eq(index).

    brenniebrennie

    you can do $bannerTableRow.show() here.

    brenniebrennie

    This should be a class, not an ID.

    brenniebrennie

    border has a shorthand property as following: border: border-width border-style border-color or you can define border-width as following: border-width: top …

    AN anni_cao

    Why do you need break at the end of if statement? It will jump out of the loop anyway, right?

    AN anni_cao
    reviewbot
    1. Tool: PEP8 Style Checker
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/diffviewer/collections/diffReviewableCollection.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
      
      Tool: Pyflakes
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/diffviewer/collections/diffReviewableCollection.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
    2. 
        
    MO
    MO
    DA
    1. 
        
    2. Show all issues

      I think this would be more readable if this else was on a new line.

      1. I totally agree with you. However, I am following the same coding style / conventions
        that are used elsewhere in RB's codebase. The rest of RB's Javascript codebase uses
        else statements on the same line as the curly bracket.

    3. Show all issues

      Same here.

      1. See reply above.

    4. 
        
    MO
    reviewbot
    1. Tool: PEP8 Style Checker
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
      
      Tool: Pyflakes
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
    2. 
        
    MO
    reviewbot
    1. Tool: Pyflakes
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/diffviewer/views/floatingBannerIndexView.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
      
      Tool: PEP8 Style Checker
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/diffviewer/views/floatingBannerIndexView.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
    2. 
        
    MO
    reviewbot
    1. Tool: PEP8 Style Checker
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/diffviewer/views/floatingBannerIndexView.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
      
      Tool: Pyflakes
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/diffviewer/views/floatingBannerIndexView.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
    2. 
        
    MO
    reviewbot
    1. Tool: Pyflakes
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/diffviewer/views/floatingBannerIndexView.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
      
      Tool: PEP8 Style Checker
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/diffviewer/views/floatingBannerIndexView.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
    2. 
        
    RK
    1. 
        
    2. Show all issues

      remove blank line

    3. 
        
    MO
    reviewbot
    1. Tool: PEP8 Style Checker
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/diffviewer/views/floatingBannerIndexView.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
      
      Tool: Pyflakes
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/diffviewer/views/floatingBannerIndexView.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
    2. 
        
    MO
    reviewbot
    1. Tool: Pyflakes
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/diffviewer/views/floatingBannerIndexView.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
      
      Tool: PEP8 Style Checker
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/diffviewer/views/floatingBannerIndexView.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
    2. 
        
    MO
    reviewbot
    1. Tool: Pyflakes
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/diffviewer/views/floatingBannerIndexView.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
      
      Tool: PEP8 Style Checker
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/diffviewer/views/floatingBannerIndexView.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
    2. 
        
    MO
    reviewbot
    1. Tool: PEP8 Style Checker
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/diffviewer/views/floatingBannerIndexView.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
      
      Tool: Pyflakes
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/diffviewer/views/floatingBannerIndexView.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
    2. 
        
    brennie
    1. 
        
    2. Show all issues

      Alphabetize

    3. Show all issues

      Doc comments begin with /**.

    4. Show all issues

      Doc comments begin with /** in JS

    5. Show all issues

      How about viewType

    6. Show all issues

      This can always run, since it is just a call to bind. It doesn't hurt.

      Alternatively we can add this specific behaviour in a subclass. (That is what I would prefer here, but you may want to ask another mentor's opinion.)

      1. I suggested using a subclass to Christian earlier, and he mentioned that we didn't need a subclass in this case since the class only has two modes (page-view and banner-view). He said we should use a subclass if it had more than two modes (if I recall correctly).

    7. reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js (Diff revision 9)
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
      Show all issues

      Instead of using each, we should do a for loop. That way we can break out after finding the element to display (because if its the first one of twenty, there is no need to consider the next 19). It also lets us use a more correct way of determing if something is in view:

      windowBottom = windowTop + $(window).height();
      
      for (i = 0; i < this.collection.size(); i++) {
          /* variable assignments */
      
          if (filePositionTop <= windowTop && filePositionBottom >= windowTop ||
              filePositionTop >= windowTop && filePositionTop <= windowTop + $(window).height()) {
              /* in view, show it */
              break;
           }
      }
      

      The first condition checks if the file is above or starting at the top of the window and the second checks that the top of the file is within the window viewport.

      However, you will also have to hide all other elements which you can do with this._$items.hide() before the loop.

      1. I am noticing a couple of issues with this implementation. The break statement creates issues when scrolling up in the view; the diff files are never removed, so it ends up appending each diff file as it enters the screen. It never gets to the hide() function for the diff file below it because it breaks out of the loop.

        Therefore, I tried removing the break statement. In this case, each file inside the view is shown. For example, if four small diff files are currently inside the window, then all four appears in the banner as default.

        I came up with a working solution for only displaying one row as default:

        for (var i = 0; i < this.collection.size(); i++) {
            diffFileId = '#file' + this.collection.models[i].attributes.id;
            diffFileContainer = $(diffFileId).parent().parent();   //get the "diff-container"
            containerTop = diffFileContainer.offset().top;
            containerBottom = containerTop + diffFileContainer.outerHeight(true);
            $bannerTableRow = this._$items.eq(i);
            /**
             * Show the table row only if it intersects with the top of the window.
             */
             if (windowTop >= containerTop && windowTop < containerBottom) {
                 $bannerTableRow.show();
                 $bannerTableRow.attr('id', 'banner-active-file');
             } else {
                 $bannerTableRow.hide();
                 if ($bannerTableRow.is('#banner-active-file')) {
                     $bannerTableRow.removeAttr('id');
                 }
            }
        }
        

        It is very similar to the one I previously had, and the major difference is that I'm getting the diff-container rather than the table inside the diff-container. This solution also takes the margin size into account between each diff-container (I tested it by changing the margin-bottom value in the inspector).

        Let me know what you think.

    8. Show all issues

      This isnt a jQuery. To get a jQuery (and use the .show() method i suggested) use this._$items.eq(index).

    9. Show all issues

      you can do $bannerTableRow.show() here.

    10. 
        
    MO
    reviewbot
    1. Tool: PEP8 Style Checker
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/diffviewer/views/floatingBannerIndexView.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
      
      Tool: Pyflakes
      Processed Files:
          reviewboard/staticbundles.py
      
      Ignored Files:
          reviewboard/static/rb/js/diffviewer/views/diffFileIndexView.js
          reviewboard/static/rb/css/pages/diffviewer.less
          reviewboard/static/rb/js/views/floatingBannerView.js
          reviewboard/templates/diffviewer/view_diff.html
          reviewboard/static/rb/js/pages/models/diffViewerPageModel.js
          reviewboard/static/rb/js/diffviewer/models/diffFileIndexModel.js
          reviewboard/static/rb/js/diffviewer/views/floatingBannerIndexView.js
          reviewboard/static/rb/js/pages/views/diffViewerPageView.js
      
      
    2. 
        
    brennie
    1. 
        
    2. Show all issues

      This should be a class, not an ID.

    3. 
        
    MO
    MO
    MO
    MO
    AN
    1. 
        
    2. Show all issues

      Why do you need break at the end of if statement? It will jump out of the loop anyway, right?

      1. The break statement optimizes the number of computations we have to do in the loop.
        For example, if the size of the list we are looping through is 20, and we find the
        file that we want after 3 iterations, the break statement skips the next 17 iterations.

    3. 
        
    AN
    1. 
        
    2. Show all issues

      border has a shorthand property as following:
      border: border-width border-style border-color

      or you can define border-width as following:
      border-width: top right bottom left

      In your case, looks like they are all 0, you can do
      border-width: 0

      1. Thanks for pointing this out, Anni! I fixed it by doing this:

        border: 0 @review-request-border-color;
        

        I also realized I had hard-coded the colors instead of using RB's .less color definitions.

    3. 
        
    MO
    MO
    MO
    MO
    david
    Review request changed
    Status:
    Discarded