                         else if (viewport.horizontalScrollPosition + width < eltBounds.right + focusThickness)
                             viewport.horizontalScrollPosition = eltBounds.right + focusThickness - width;
                     }
+                    snapContentScrollPosition();
                 }
                 
                 if (doValidateNow && viewport is UIComponent)

                
                // 5 pixels at 252dpi worked fairly well for this heuristic.
                const THRESHOLD_INCHES:Number = 0.01984; // 5/252 
                var captureThreshold:Number = Math.round(THRESHOLD_INCHES * effectiveScreenDPI);
                
                // Need to convert the pixel delta to the local coordinate system in 
                // order to compare it to a scroll position delta. 

        removeEventListener(MouseEvent.MOUSE_DOWN, touchScrolling_captureMouseHandler, true);
    }
    
    /**
     *  @private
     *  This function determines whether a switch to an adjacent page is warranted, given 
     *  the distance dragged and/or the velocity thrown. 
     */
    private function determineNewPageScrollPosition(velocityX:Number, velocityY:Number):void
    {
        // needdoc
        var minVelocityPixels:Number = pageThrowVelocityThreshold * Capabilities.screenDPI / 1000;
        
        if (canScrollHorizontally)
        {
            // needdoc
            if (velocityX < -minVelocityPixels || viewport.horizontalScrollPosition >= currentPageScrollPosition + viewport.width * pageDragDistanceThreshold)
            {
                // needdoc
                // Go to the next horizontal page
                currentPageScrollPosition = Math.min(currentPageScrollPosition + viewport.width, viewport.contentWidth - viewport.width);
            }
            else if (velocityX > minVelocityPixels || viewport.horizontalScrollPosition <= currentPageScrollPosition - viewport.width * pageDragDistanceThreshold)
            {
                // Go to the previous horizontal page
                currentPageScrollPosition = Math.max(currentPageScrollPosition - viewport.width, 0);     
            }
            
            // Ensure the new page position is snapped appropriately 
            currentPageScrollPosition = getSnappedPosition(currentPageScrollPosition, HORIZONTAL_SCROLL_POSITION);
        }
        else if (canScrollVertically)
        {
            if (velocityY < -minVelocityPixels || viewport.verticalScrollPosition >= currentPageScrollPosition + viewport.height * pageDragDistanceThreshold)
            {
                // Go to the next vertical page
                currentPageScrollPosition = Math.min(currentPageScrollPosition + viewport.height, viewport.contentHeight - viewport.height);     
            }
            else if (velocityY > minVelocityPixels || viewport.verticalScrollPosition <= currentPageScrollPosition - viewport.height * pageDragDistanceThreshold)
            {
                // Go to the previous vertical page
                currentPageScrollPosition = Math.max(currentPageScrollPosition - viewport.height, 0);     
            }

            // Ensure the new page position is snapped appropriately 
            currentPageScrollPosition = getSnappedPosition(currentPageScrollPosition, VERTICAL_SCROLL_POSITION);
        }
    }
    
    /**
     *  @private
     *  Set up the effect to be used for the throw animation
     */
    private function setUpThrowEffect(velocityX:Number, velocityY:Number):Boolean
    {
        if (!throwEffect)
        {
            throwEffect = new ThrowEffect();
            throwEffect.target = viewport;
            throwEffect.addEventListener(EffectEvent.EFFECT_END, throwEffect_effectEndHandler);
        }

        var minHSP:Number = minHorizontalScrollPosition;
        var minVSP:Number = minVerticalScrollPosition;
        var maxHSP:Number = maxHorizontalScrollPosition;
        var maxVSP:Number = maxVerticalScrollPosition;

        if (pageScrollingEnabled)
        {
            // The throw velocity is greatly attenuated in paging mode
            const PAGING_VELOCITY_FACTOR:Number = 0.25; 
            velocityX *= PAGING_VELOCITY_FACTOR;
            velocityY *= PAGING_VELOCITY_FACTOR;
            
            // See whether a page switch is warranted for this touch gesture.
            determineNewPageScrollPosition(velocityX, velocityY);
            
            // Make the scroller "lock" to the current page
            if (canScrollHorizontally)
                minHSP = maxHSP = currentPageScrollPosition;
            else if (canScrollVertically)
                minVSP = maxVSP = currentPageScrollPosition;
        }

        throwEffect.propertyNameX = canScrollHorizontally ? HORIZONTAL_SCROLL_POSITION : null;
        throwEffect.propertyNameY = canScrollVertically ? VERTICAL_SCROLL_POSITION : null;
        throwEffect.startingVelocityX = velocityX;
        throwEffect.startingVelocityY = velocityY;
        throwEffect.startingPositionX = viewport.horizontalScrollPosition;
        throwEffect.startingPositionY = viewport.verticalScrollPosition;
        throwEffect.minPositionX = minHSP;
        throwEffect.minPositionY = minVSP;
        throwEffect.maxPositionX = maxHSP;
        throwEffect.maxPositionY = maxVSP;
        throwEffect.decelerationFactor = throwEffectDecelFactor;
        
        // In snapping mode, we need to ensure that the final throw position is snapped appropriately.
        throwEffect.finalPositionFilterFunction = scrollSnappingMode == ScrollSnappingMode.NONE ? null : getSnappedPosition; 
        
        throwReachedMaximumScrollPosition = false;
        if (throwEffect.setup())
        {
            throwFinalHSP = throwEffect.finalPosition.x;
            if (canScrollHorizontally && bounceEnabled && throwFinalHSP == maxHorizontalScrollPosition)
                throwReachedMaximumScrollPosition = true;
            throwFinalVSP = throwEffect.finalPosition.y;
            if (canScrollVertically && bounceEnabled && throwFinalVSP == maxVerticalScrollPosition)
                throwReachedMaximumScrollPosition = true;
        }
        else
        {
            touchScrollHelper.endTouchScroll();
            return false;
        }
        return true;
    }
        
    
    /**
     *  @private
     *  This function takes a scroll position and the associated property name, and finds
     *  the nearest snapped position (i.e. one that satifises the current scrollSnappingMode).
     */
    private function getSnappedPosition(position:Number, propertyName:String):Number
    {
        var layout:LayoutBase = viewportLayout;
        var nearestElementIndex:int;
        var nearestElementBounds:Rectangle;

        if (layout && layout.target.numElements > 0)
        {
            switch (_scrollSnappingMode)
            {
                case ScrollSnappingMode.LEADING_EDGE:
                    if (canScrollHorizontally && propertyName == HORIZONTAL_SCROLL_POSITION)
                    {
                        nearestElementIndex = layout.getElementNearestScrollPosition(new Point(position, 0), "topLeft");
                        nearestElementBounds = layout.getElementBounds(nearestElementIndex);
                        position = nearestElementBounds.left;
                    }
                    else if (canScrollVertically && propertyName == VERTICAL_SCROLL_POSITION)
                    {
                        nearestElementIndex = layout.getElementNearestScrollPosition(new Point(0, position), "topLeft");
                        nearestElementBounds = layout.getElementBounds(nearestElementIndex);
                        position = nearestElementBounds.top;
                    }
                    break;
                case ScrollSnappingMode.CENTER:
                    if (canScrollHorizontally && propertyName == HORIZONTAL_SCROLL_POSITION)
                    {
                        nearestElementIndex = layout.getElementNearestScrollPosition(new Point(position + viewport.width/2, 0), "center");
                        nearestElementBounds = layout.getElementBounds(nearestElementIndex);
                        position = nearestElementBounds.left + (nearestElementBounds.width / 2) - (viewport.width / 2);
                    }
                    else if (canScrollVertically && propertyName == VERTICAL_SCROLL_POSITION)
                    {
                        nearestElementIndex = layout.getElementNearestScrollPosition(new Point(0, position + viewport.height/2), "center");
                        nearestElementBounds = layout.getElementBounds(nearestElementIndex);
                        position = nearestElementBounds.top + (nearestElementBounds.height / 2) - (viewport.height / 2);
                    }
                    break;
                case ScrollSnappingMode.TRAILING_EDGE:                
                    if (canScrollHorizontally && propertyName == HORIZONTAL_SCROLL_POSITION)
                    {
                        nearestElementIndex = layout.getElementNearestScrollPosition(new Point(position + viewport.width, 0), "bottomRight");
                        nearestElementBounds = layout.getElementBounds(nearestElementIndex);
                        position = nearestElementBounds.right - viewport.width;
                    }
                    else if (canScrollVertically && propertyName == VERTICAL_SCROLL_POSITION)
                    {
                        nearestElementIndex = layout.getElementNearestScrollPosition(new Point(0, position + viewport.height), "bottomRight");
                        nearestElementBounds = layout.getElementBounds(nearestElementIndex);
                        position = nearestElementBounds.bottom - viewport.height;
                    }
                    break;
            }
        }
        return Math.round(position);
    }

    /**
     *  @private
     *  When the throw or drag scroll is over, we should play a nice 
