• Robert Knight's avatar
    Re-implement excerpt overflow state recalculation · 6f49c8f6
    Robert Knight authored
    Previously the overflowing state of the excerpt was computed implicitly
    by the overflowing() method, which was called from several other
    controller functions.
    
    There were several problems with this approach:
    
     1. Since this method calls Element.scrollHeight, it triggered an
        expensive synchronous layout flush.
     2. In certain situations, this could trigger a loop where the
        overflowing flag was continually flipped (see #2960)
     3  It was unpredictable when the overflowing state would be recomputed.
    
    This commit instead opts for a different approach which is more explicit
    about when the state is recomputed, based on the assumption that the
    <excerpt>'s content size is a function of:
    
     1. The inputs to the <excerpt>'s content (eg. the text of a quote, the body
        of an annotation)
     2. The sidebar window's size
     3. The dimensions of any embedded media
    
    The content size is then computed and updated as follows:
    
     1. When the <excerpt> is initially created, an async computation of
        the scrollHeight is scheduled. The calculation unfortunately needs
        to be async because the content may contain Angular directives which
        take several $digest cycles to fully process.
    
     2. The <excerpt> listens for changes to the content's data (via a
        'contentData' property), media 'load' events and window 'resize'
        events and recomputes the overflow state in response to any of
        these.
    
    There are a couple of other fixes here:
    
     - Use an optional boolean property for the 'enabled' input,
       rather than a function. The app passed a function to this property
       but the tests passed a boolean.
    
    Fixes #2960
    6f49c8f6
annotation.html 9.31 KB