<commit_before>module MobileDragAndDropPolyfill {

    var _options:ScrollOptions = {
        threshold: 75,
        velocityFn: function( velocity:number ) {
            var multiplier = .7;
            // default to cubic-in-easing
            var easeInCubic = multiplier * multiplier * multiplier;
            return easeInCubic * velocity;
        }
    };

    var _scrollIntentions:ScrollIntentions = {
        horizontal: ScrollIntention.NONE,
        vertical: ScrollIntention.NONE
    };

    var _dynamicVelocity:Point = {
        x: 0,
        y: 0
    };

    var _scrollAnimationFrameId:any;
    var _currentCoordinates:Point;
    var _hoveredElement:HTMLElement;
    var _scrollableParent:HTMLElement;
    var _translateDragImageFn:( offsetX:number, offsetY:number ) => void;

    //<editor-fold desc="public api">

    export interface ScrollOptions {
        // threshold in px. when distance between scrollable element edge and touch position is smaller start programmatic scroll.
        // defaults to 75px
        threshold?:number;
        // function to customize the scroll velocity
        // the function receives the current distance
        // of the touch to the scrollable element edge in px.
        // defaults to cubic-ease-in.
        velocityFn:( velocity:number ) => number;
    }

    export function SetOptions( options:ScrollOptions ):void {

        // overwrite defaults with input options
        Object.keys( options ).forEach( function( key ) {
            _options[ key ] = options[ key ];
        } );
    }

    export function HandleDragImageTranslateOverride( event:TouchEvent,
                                                      currentCoordinates:Point,
                                                      hoveredElement:HTMLElement,
                                                      translateDragImageFn:( scrollDiffX:number, scrollDiffY:number ) => void ):boolean {

        _currentCoordinates = currentCoordinates;
        _translateDragImageFn = translateDragImageFn;

        // update parent if hovered element changed
        if( _hoveredElement !== hoveredElement ) {

            _hoveredElement = hoveredElement;
            _scrollableParent = findScrollableParent( _hoveredElement );
        }

        // update scroll intention and check if we should scroll at all
        var performScrollAnimation = updateScrollIntentions( _currentCoordinates, _scrollableParent, _options.threshold, _scrollIntentions, _dynamicVelocity );

        // no animation in progress but scroll is intended
        if( performScrollAnimation ) {

            // setup scroll animation frame
            scheduleScrollAnimation();
        }
        else if( !!_scrollAnimationFrameId ) {

            window.cancelAnimationFrame( _scrollAnimationFrameId );
            _scrollAnimationFrameId = undefined;
        }

        return performScrollAnimation;
    }

    //</editor-fold>

    //<editor-fold desc="programmatic scroll animation frame handler">

    function scheduleScrollAnimation() {

        // prevent scheduling when already scheduled
        if( !!_scrollAnimationFrameId ) {

            return;
        }

        _scrollAnimationFrameId = window.requestAnimationFrame( scrollAnimation );
    }

    function scrollAnimation() {

        var scrollDiffX = 0,
            scrollDiffY = 0,
            isTopLevel  = isTopLevelEl( _scrollableParent );

        if( _scrollIntentions.horizontal !== ScrollIntention.NONE ) {

            scrollDiffX = Math.round( _options.velocityFn( _dynamicVelocity.x ) * _scrollIntentions.horizontal );
            getSetElementScroll( _scrollableParent, ScrollAxis.HORIZONTAL, scrollDiffX );
        }

        if( _scrollIntentions.vertical !== ScrollIntention.NONE ) {

            scrollDiffY = Math.round( _options.velocityFn( _dynamicVelocity.y ) * _scrollIntentions.vertical );
            getSetElementScroll( _scrollableParent, ScrollAxis.VERTICAL, scrollDiffY );
        }

        if( isTopLevel ) {
            // on top level element scrolling we need to translate the drag image as much as we scroll
            _translateDragImageFn( scrollDiffX, scrollDiffY );
        }
        else {
            // just scroll the container and update the drag image position without offset
            _translateDragImageFn( 0, 0 );
        }

        // reset to make sure we can re-schedule scroll animation
        _scrollAnimationFrameId = undefined;

        // check if we should continue scrolling
        if( updateScrollIntentions( _currentCoordinates, _scrollableParent, _options.threshold, _scrollIntentions, _dynamicVelocity ) ) {<commit_msg>+ added threshold parameter to velocityFn + improved default cubic-ease-in scroll velocity fn<commit_after>module MobileDragAndDropPolyfill {

    var _options:ScrollOptions = {
        threshold: 75,
        // simplified cubic-ease-in function
        velocityFn: function( velocity:number, threshold:number ) {
            var multiplier = velocity / threshold;
            var easeInCubic = multiplier * multiplier * multiplier;
            return easeInCubic * threshold;
        }
    };

    var _scrollIntentions:ScrollIntentions = {
        horizontal: ScrollIntention.NONE,
        vertical: ScrollIntention.NONE
    };

    var _dynamicVelocity:Point = {
        x: 0,
        y: 0
    };

    var _scrollAnimationFrameId:any;
    var _currentCoordinates:Point;
    var _hoveredElement:HTMLElement;
    var _scrollableParent:HTMLElement;
    var _translateDragImageFn:( offsetX:number, offsetY:number ) => void;

    //<editor-fold desc="public api">

    export interface ScrollOptions {
        // threshold in px. when distance between scrollable element edge and touch position is smaller start programmatic scroll.
        // defaults to 75px
        threshold?:number;
        // function to customize the scroll velocity
        // velocity param: distance to scrollable element edge
        // threshold: the threshold used to determine when scrolling should start
        // defaults to cubic-ease-in.
        velocityFn:( velocity:number, threshold:number ) => number;
    }

    export function SetOptions( options:ScrollOptions ):void {

        // overwrite defaults with input options
        Object.keys( options ).forEach( function( key ) {
            _options[ key ] = options[ key ];
        } );
    }

    export function HandleDragImageTranslateOverride( event:TouchEvent,
                                                      currentCoordinates:Point,
                                                      hoveredElement:HTMLElement,
                                                      translateDragImageFn:( scrollDiffX:number, scrollDiffY:number ) => void ):boolean {

        _currentCoordinates = currentCoordinates;
        _translateDragImageFn = translateDragImageFn;

        // update parent if hovered element changed
        if( _hoveredElement !== hoveredElement ) {

            _hoveredElement = hoveredElement;
            _scrollableParent = findScrollableParent( _hoveredElement );
        }

        // update scroll intention and check if we should scroll at all
        var performScrollAnimation = updateScrollIntentions( _currentCoordinates, _scrollableParent, _options.threshold, _scrollIntentions, _dynamicVelocity );

        // no animation in progress but scroll is intended
        if( performScrollAnimation ) {

            // setup scroll animation frame
            scheduleScrollAnimation();
        }
        else if( !!_scrollAnimationFrameId ) {

            window.cancelAnimationFrame( _scrollAnimationFrameId );
            _scrollAnimationFrameId = undefined;
        }

        return performScrollAnimation;
    }

    //</editor-fold>

    //<editor-fold desc="programmatic scroll animation frame handler">

    function scheduleScrollAnimation() {

        // prevent scheduling when already scheduled
        if( !!_scrollAnimationFrameId ) {

            return;
        }

        _scrollAnimationFrameId = window.requestAnimationFrame( scrollAnimation );
    }

    function scrollAnimation() {

        var scrollDiffX = 0,
            scrollDiffY = 0,
            isTopLevel  = isTopLevelEl( _scrollableParent );

        if( _scrollIntentions.horizontal !== ScrollIntention.NONE ) {

            scrollDiffX = Math.round( _options.velocityFn( _dynamicVelocity.x, _options.threshold ) * _scrollIntentions.horizontal );
            getSetElementScroll( _scrollableParent, ScrollAxis.HORIZONTAL, scrollDiffX );
        }

        if( _scrollIntentions.vertical !== ScrollIntention.NONE ) {

            scrollDiffY = Math.round( _options.velocityFn( _dynamicVelocity.y, _options.threshold ) * _scrollIntentions.vertical );
            getSetElementScroll( _scrollableParent, ScrollAxis.VERTICAL, scrollDiffY );
        }

        if( isTopLevel ) {
            // on top level element scrolling we need to translate the drag image as much as we scroll
            _translateDragImageFn( scrollDiffX, scrollDiffY );
        }
        else {
            // just scroll the container and update the drag image position without offset
            _translateDragImageFn( 0, 0 );
        }

        // reset to make sure we can re-schedule scroll animation
        _scrollAnimationFrameId = undefined;

        // check if we should continue scrolling
        if( updateScrollIntentions( _currentCoordinates, _scrollableParent, _options.threshold, _scrollIntentions, _dynamicVelocity ) ) {
{'fraction_non_alphanumeric': 0.07085126482628319, 'fraction_numerical': 0.002204261572373255, 'mean_word_length': 2.300311742293038, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7482969', 'n_tokens_mistral': 2347, 'n_tokens_neox': 2222, 'n_words': 637}