<commit_before>(function (mt) {
    'use strict';

    /**
     * @ngdoc directive
     * @name mt.directive:mtScrollable
     * @restrict A
     *
     * Declares a scrollable container that can be manipulated thanks to its controller. The attribute value is an unique
     * name that can be used to get the directive controller from the {@link mtScrollablesRegistry}.
     *
     * An anchor string declared on children elements thanks to the "mt-scrollable-anchor" attribute can be then used
     * when calling {@link mtScrollable.mtScrollableController#putInViewPort(string)} to scroll until the child element
     * is visible.
     */
    mt.MixTubeApp.directive('mtScrollable', function ($window, $rootScope, mtScrollablesRegistry, BASE_TRANSITION_DURATION, EASE_IN_OUT_FN) {

        return {
            restrict: 'A',
            controller: function ($scope, $element, $attrs) {

                var scrollableName = $attrs.mtScrollable;

                if (!scrollableName || scrollableName.trim().length === 0) {
                    throw new Error('mtScrollable expected a non empty string as attribute value');
                }

                mtScrollablesRegistry.register(scrollableName, this);
                $scope.$on('$destroy', function () {
                    mtScrollablesRegistry.unregister(scrollableName);
                });

                function transitionScrollTop(scrollableElement, duration, scrollOffset) {
                    // store the scroll position at the beginning of the transition
                    var scrollStart = scrollableElement[0].scrollTop;

                    var startTs = null;
                    (function requestNextFrame() {
                        $window.requestAnimationFrame(function (frameTs) {
                            if (startTs === null) {
                                startTs = frameTs;
                            }

                            var progress = (frameTs - startTs) / duration;

                            if (progress > 0) {
                                var frameScrollOffset = scrollOffset * EASE_IN_OUT_FN(progress);
                                scrollableElement[0].scrollTop = scrollStart + frameScrollOffset;
                            }

                            if (progress < 1) {
                                requestNextFrame();
                            }
                        });
                    })();
                }

                function putElementInViewPort(target) {
                    var scrollViewRect = scrollableElement[0].getBoundingClientRect();
                    var targetRect = target[0].getBoundingClientRect();

                    var offset = 0;
                    if (targetRect.top < scrollViewRect.top) {
                        offset = targetRect.top - scrollViewRect.top;
                    } else if (scrollViewRect.bottom < targetRect.bottom) {
                        offset = targetRect.bottom - scrollViewRect.bottom;
                    }

                    if (offset !== 0) {
                        transitionScrollTop(scrollableElement, BASE_TRANSITION_DURATION, offset);
                    }
                }

                function putAnchorInViewPort(anchor) {
                    var target = mt.tools.querySelector(scrollableElement, '[mt-anchor=' + anchor + ']');
                    if (target.length > 0) {
                        putElementInViewPort(target);
                    }
                }

                /**
                 * Ensures the given target is visible in the view port by scrolling the scrollable.
                 *
                 * @param {(string|jqLite)} target could be an anchor define by "mt-anchor" attribute or a jqLite element
                 */
                this.putInViewPort = function (target) {
                    if (angular.isElement(target)) {
                        putElementInViewPort(target);
                    } else if (angular.isString(target)) {
                        putAnchorInViewPort(target);
                    } else {
                        throw new Error('The "putInViewPort" method from mtScrollable only accepts strings or jQLite elements');
                    }
                };
            }
        };
    });
})(mt);<commit_msg>fixed a bug introduced in scrollable directive<commit_after>(function (mt) {
    'use strict';

    /**
     * @ngdoc directive
     * @name mt.directive:mtScrollable
     * @restrict A
     *
     * Declares a scrollable container that can be manipulated thanks to its controller. The attribute value is an unique
     * name that can be used to get the directive controller from the {@link mtScrollablesRegistry}.
     *
     * An anchor string declared on children elements thanks to the "mt-scrollable-anchor" attribute can be then used
     * when calling {@link mtScrollable.mtScrollableController#putInViewPort(string)} to scroll until the child element
     * is visible.
     */
    mt.MixTubeApp.directive('mtScrollable', function ($window, $rootScope, mtScrollablesRegistry, BASE_TRANSITION_DURATION, EASE_IN_OUT_FN) {

        return {
            restrict: 'A',
            controller: function ($scope, $element, $attrs) {

                var scrollableName = $attrs.mtScrollable;
                var scrollableElement = $element;

                if (!scrollableName || scrollableName.trim().length === 0) {
                    throw new Error('mtScrollable expected a non empty string as attribute value');
                }

                mtScrollablesRegistry.register(scrollableName, this);
                $scope.$on('$destroy', function () {
                    mtScrollablesRegistry.unregister(scrollableName);
                });

                function transitionScrollTop(duration, scrollOffset) {
                    // store the scroll position at the beginning of the transition
                    var scrollStart = scrollableElement[0].scrollTop;

                    var startTs = null;
                    (function requestNextFrame() {
                        $window.requestAnimationFrame(function (frameTs) {
                            if (startTs === null) {
                                startTs = frameTs;
                            }

                            var progress = (frameTs - startTs) / duration;

                            if (progress > 0) {
                                var frameScrollOffset = scrollOffset * EASE_IN_OUT_FN(progress);
                                scrollableElement[0].scrollTop = scrollStart + frameScrollOffset;
                            }

                            if (progress < 1) {
                                requestNextFrame();
                            }
                        });
                    })();
                }

                function putElementInViewPort(target) {
                    var scrollViewRect = scrollableElement[0].getBoundingClientRect();
                    var targetRect = target[0].getBoundingClientRect();

                    var offset = 0;
                    if (targetRect.top < scrollViewRect.top) {
                        offset = targetRect.top - scrollViewRect.top;
                    } else if (scrollViewRect.bottom < targetRect.bottom) {
                        offset = targetRect.bottom - scrollViewRect.bottom;
                    }

                    if (offset !== 0) {
                        transitionScrollTop(BASE_TRANSITION_DURATION, offset);
                    }
                }

                function putAnchorInViewPort(anchor) {
                    var target = mt.tools.querySelector(scrollableElement, '[mt-anchor=' + anchor + ']');
                    if (target.length > 0) {
                        putElementInViewPort(target);
                    }
                }

                /**
                 * Ensures the given target is visible in the view port by scrolling the scrollable.
                 *
                 * @param {(string|jqLite)} target could be an anchor define by "mt-anchor" attribute or a jqLite element
                 */
                this.putInViewPort = function (target) {
                    if (angular.isElement(target)) {
                        putElementInViewPort(target);
                    } else if (angular.isString(target)) {
                        putAnchorInViewPort(target);
                    } else {
                        throw new Error('The "putInViewPort" method from mtScrollable only accepts strings or jQLite elements');
                    }
                };
            }
        };
    });
})(mt);
{'fraction_non_alphanumeric': 0.07976451575666628, 'fraction_numerical': 0.002308669052291354, 'mean_word_length': 1.367860071057666, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4668095', 'n_tokens_mistral': 2049, 'n_tokens_neox': 1888, 'n_words': 508}