<commit_before>class jfMultiDropdownController {
    constructor($scope, $filter) {

        this.$scope = $scope;

        this.filter = $filter('filter');
        this.opened = false;

        this.handleOutsideClick();

        this.$scope.$watch('jfMultiDropdown.items', (newVal, oldVal) => {
            if (newVal) {
                this.sortItems();
            }
        });
        this.$scope.$watch('jfMultiDropdown.dropdownOpened', (val) => {
            if (val === true) {
                if (!this.items) return;
                this.opened = true;
                this.filterText = '';
            }
            else if (val === false) {
                this.opened = false;
                this.filterText = '';
            }
            else {

            }
        });

    }

    handleOutsideClick() {
        let handler = (e) => {
            let outside = !$(e.target).parents('.jf-multi-dropdown').length
            if (outside) {
                this.opened = false;
                this.sortItems();
            }
            this.$scope.$apply();
        };
        $(document).on('click',handler);
        this.$scope.$on('$destroy',() => {
            $(document).off('click', handler)
        })
    }

    onClick() {
        if (this.disabled !== true) {
            if (!this.items) return;
            this.opened = !this.opened;
            if (!this.opened) this.sortItems();
            this.filterText = '';

        }

    }
    onSelection() {
        if (this.onChange) this.onChange();
    }
    getSelectedCount() {
        let selected = _.filter(this.items, (item) => item.isSelected);
        return selected.length;
    }

    sortItems() {
        if (!this.items) return;
        let selected = _.sortBy(_.filter(this.items, (item) => item.isSelected), 'text');
        let unSelected = _.sortBy(_.filter(this.items, (item) => !item.isSelected), 'text');
        this.lastSelectedIndex = selected.length-1;
        let combined = selected.concat(unSelected);
        this.items.splice.apply(this.items, [0,this.items.length].concat(combined));
    }
    selectAll() {
        this.filter(this.items, this.filterText).forEach((item)=>{item.isSelected = true;})
    }
    unSelectAll() {
        this.filter(this.items, this.filterText).forEach((item)=>{item.isSelected = false;})
    }

}

export function jfMultiDropdown() {
    return {
        controller: jfMultiDropdownController,
        controllerAs: 'jfMultiDropdown',
        bindToController: true,
        scope: {
            title: '@',
            filterPlaceholder: '@',
            noItemsMessage: '@',
            items: '=',
            disabled: '=?',
            onChange: '&?',
            dropdownOpened: '='
        },
        templateUrl: 'directives/jf_multi_dropdown/jf_multi_dropdown.html'
    }
}<commit_msg>backport bugfix in jf-multi-dropdown (not firing event in select/deselect all) from v1.x<commit_after>class jfMultiDropdownController {
    constructor($scope, $filter) {

        this.$scope = $scope;

        this.filter = $filter('filter');
        this.opened = false;

        this.handleOutsideClick();

        this.$scope.$watch('jfMultiDropdown.items', (newVal, oldVal) => {
            if (newVal) {
                this.sortItems();
            }
        });
        this.$scope.$watch('jfMultiDropdown.dropdownOpened', (val) => {
            if (val === true) {
                if (!this.items) return;
                this.opened = true;
                this.filterText = '';
            }
            else if (val === false) {
                this.opened = false;
                this.filterText = '';
            }
            else {

            }
        });

    }

    handleOutsideClick() {
        let handler = (e) => {
            let outside = !$(e.target).parents('.jf-multi-dropdown').length
            if (outside) {
                this.opened = false;
                this.sortItems();
            }
            this.$scope.$apply();
        };
        $(document).on('click',handler);
        this.$scope.$on('$destroy',() => {
            $(document).off('click', handler)
        })
    }

    onClick() {
        if (this.disabled !== true) {
            if (!this.items) return;
            this.opened = !this.opened;
            if (!this.opened) this.sortItems();
            this.filterText = '';

        }

    }
    onSelection() {
        if (this.onChange) this.onChange();
    }
    getSelectedCount() {
        let selected = _.filter(this.items, (item) => item.isSelected);
        return selected.length;
    }

    sortItems() {
        if (!this.items) return;
        let selected = _.sortBy(_.filter(this.items, (item) => item.isSelected), 'text');
        let unSelected = _.sortBy(_.filter(this.items, (item) => !item.isSelected), 'text');
        this.lastSelectedIndex = selected.length-1;
        let combined = selected.concat(unSelected);
        this.items.splice.apply(this.items, [0,this.items.length].concat(combined));
    }
    selectAll() {
        this.filter(this.items, this.filterText).forEach((item)=>{item.isSelected = true;})
        this.onSelection();
    }
    unSelectAll() {
        this.filter(this.items, this.filterText).forEach((item)=>{item.isSelected = false;})
        this.onSelection();
    }

}

export function jfMultiDropdown() {
    return {
        controller: jfMultiDropdownController,
        controllerAs: 'jfMultiDropdown',
        bindToController: true,
        scope: {
            title: '@',
            filterPlaceholder: '@',
            noItemsMessage: '@',
            items: '=',
            disabled: '=?',
            onChange: '&?',
            dropdownOpened: '='
        },
        templateUrl: 'directives/jf_multi_dropdown/jf_multi_dropdown.html'
    }
}
{'fraction_non_alphanumeric': 0.1512489233419466, 'fraction_numerical': 0.0008613264427217916, 'mean_word_length': 1.7335216572504708, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6198064', 'n_tokens_mistral': 1703, 'n_tokens_neox': 1641, 'n_words': 271}