Hackpads are smart collaborative documents. .

Peter Smith

611 days ago
Unfiled. Edited by Peter Smith 611 days ago
I think I have the logic in the two subviews of the banner working more or less correctly.
I also think the banner itself is in pretty close to a good state.
However, I think I was confused about how things outside the banner interact with it, and as such, left it in a bit of a mess.
After tonight's deadline, I think the best thing to do might be to raze my changes on those components to the ground and start anew.
674 days ago
677 days ago
Unfiled. Edited by Mike Conley , Peter Smith 677 days ago
Mike C Exploring floatingBannerView
Generally, the idea behind floating banner view is this:
  • /*
  •  * Floats a banner on screen within a container.
  •  *
  •  * The banner will appear at the top of the container, or the screen,
  •  * whichever is visible, until the container is no longer on-screen.
  •  *
  •  * The banner will keep a spacer in its original location at the top
  •  * of the container in order to reserve space for it to anchor to.
  •  * This ensures that the page doesn't jump too horribly.
  •  */
That's a pretty good explanation of what's going on here. So, to be clear, the container is some bounding box that you want to be contained within at all times.
One of the challenges, perhaps, is that the floatContainer for your project isn't too clear; we want it anchored to the top of the screen if the file index isn't listed. That means that we might either need to modify floatingBannerView's behaviour, or create something different.
Let's consider opting for the former for now (perhaps chipx86 or david have some preference on the matter), but suppose we have a configuration option for the floatingBannerView that only pays attention to whether or not the floatContainer has gone past the top of the screen, and ignores the bottom part of the floatContainer.
I believe that's taken care of later in the file. Anyhow, let's keep looking...
  • RB.FloatingBannerView = Backbone.View.extend({
Okay, easy peasy, we're extending a Backbone.View .
  •     initialize: function() {
  •         this._$floatSpacer = null;
  •         _.bindAll(this, '_updateFloatPosition', '_updateSize');
  •     },
The initialize function is called when the View is instantiated. In this case, the instance sets `_$floatSpacer` to be null, and then uses underscore.js's _bindAll  to make it so that when `_updateFloatPosition` or `_updateSize` are called on this instance, that "this" within those functions is bound to this floatingBannerView instance.
  •     /*
  •      * Renders the banner and listens for scroll and resize updates.
  •      */
  •     render: function() {
  •         $(window)
  •             .scroll(this._updateFloatPosition)
  •             .resize(this._updateSize);
  •         _.defer(this._updateFloatPosition);
  •         return this;
  •     },
`render()` is called by somebody who instantiates our floatingBannerView, like here .
`render()` will set up event listeners for scrolling the page, and resizing the window, and then makes it so that _updateFloatPosition will be called "in the next tick of the event loop", which basically means when all of the page JavaScript has finished executing. It then returns `this`, which is convention for Backbone Views.
Note that we're not returning a DOM node or anything. Backbone convention makes it so that a View by default will create an empty `<div>` and assign that to `$el`. It's that `$el` that `_updateSize` and `_updateFloatPosition` manipulates, and is what the caller of `render()` will insert into the DOM.
  •     /*
  •      * Updates the size of the banner to match the spacer.
  •      */
  •     _updateSize: function() {
  •         var rect;
  •         if (this._$floatSpacer !== null) {
  •             if (this.$el.hasClass('floating')) {
  •                 rect = this._$floatSpacer.parent()[0].getBoundingClientRect();
  •                 this.$el.width(
  •                     Math.ceil(rect.width) -
  •                     this.$el.getExtents('bpm', 'lr'));
  •             } else {
  •                 this.$el.width('auto');
  •             }
  •         }
  •     },
So if we've entered here, it means that the window has resized. We check to see if we have a `$floatSpacer` (which is set up in `_updateFloatPosition`), and if we find it and we find out we're floating (indicated by the 'floating' class), then we make sure that the $el width matches that of the `$floatSpacer` parent. Otherwise, if we're not floating, it sets the width of the element to 'auto'. The end result in both cases is that the width will look correct.
  •     /*
  •      * Updates the position of the banner.
  •      *
  •      * This will factor in how much of the container is visible, based on
  •      * its size, position, and the scroll offset. It will then attempt
  •      * to position the banner to the top of the visible portion of the
  •      * container.
  •      */
`_updateFloatPosition` is definitely the most complicated function of this View class, and where you'd be doing any modifications if we go that route.
Note again that this is run both on scroll, and soon after the View is initially rendered and inserted into the DOM.
  •     _updateFloatPosition: function() {
  •         var $container,
  •             containerTop,
  •             containerBottom,
  •             containerHeight,
  •             wasFloating,
  •             windowTop,
  •             topOffset,
  •             outerHeight;
  •         if (this.$el.parent().length === 0) {

Contact Support

Please check out our How-to Guide and FAQ first to see if your question is already answered! :)

If you have a feature request, please add it to this pad. Thanks!

Log in