<commit_before>/*

    Easy widget to serve as a tabbed container.

    var $tabs =  new kbaseTabs($('#tabs'), {
            tabPosition : 'bottom', //or left or right or top. Defaults to 'top'
            canDelete : true,       //whether or not the tab can be removed. Defaults to false.
            tabs : [
                {
                    tab : 'T1',                                     //name of the tab
                    content : $('<div></div>').html("I am a tab"),  //jquery object to stuff into the content
                    canDelete : false,                              //override the canDelete param on a per tab basis
                },
                {
                    tab : 'T2',
                    content : $('<div></div>').html("I am a tab 2"),
                },
                {
                    tab : 'T3',
                    content : $('<div></div>').html("I am a tab 3"),
                    show : true,                                    //boolean. This tab gets shown by default. If not specified, the first tab is shown
                    showContentCallback: function // if you don't want to show the content right away, add a callback method that returns the content...
                },
            ],
        }
    );

    useful methods would be:

    $('#tabs').kbaseTabs('showTab', 'T1');
    $('#tabs').kbaseTabs('addTab', tabObject);  //the tabObject defined up above

*/

define(['kbwidget', 'bootstrap', 'jquery', 'kbaseDeletePrompt'], (
    KBWidget,
    bootstrap,
    $,
    kbaseDeletePrompt
) => {
    'use strict';
    return KBWidget({
        name: 'kbaseTabs',

        version: '1.0.0',

        _accessors: ['tabsHeight'],

        options: {
            tabPosition: 'top',
            canDelete: false,
            borderColor: 'lightgray',
        },

        init: function (options) {
            this._super(options);

            this.data('tabs', {});
            this.data('nav', {});

            this.appendUI($(this.$elem));

            return this;
        },

        appendUI: function ($elem, tabs) {
            if (tabs == undefined) {
                tabs = this.options.tabs;
            }

            const $block = $('<div></div>').addClass('tabbable');
            const $tabs = $('<div></div>')
                .addClass('tab-content')
                .attr('id', 'tabs-content')
                .css('height', this.tabsHeight());
            const $nav = $('<ul role="tablist"></ul>')
                .addClass('nav nav-tabs')
                .attr('id', 'tabs-nav');
            $block.append($nav).append($tabs);
            /*if (this.options.tabPosition == 'top') {
                $block.addClass('tabs-above');
                $block.append($nav).append($tabs);
            }
            else if (this.options.tabPosition == 'bottom') {
                $block.addClass('tabs-below');
                $block.append($tabs).append($nav);
            }
            else if (this.options.tabPosition == 'left') {
                $block.addClass('tabs-left');
                $block.append($nav).append($tabs);
            }
            else if (this.options.tabPosition == 'right') {
                $block.addClass('tabs-right');
                $block.append($tabs).append($nav);
            }*/

            this._rewireIds($block, this);

            $elem.append($block);

            if (tabs) {
                $.each(
                    tabs,
                    $.proxy(function (idx, tab) {
                        this.addTab(tab);
                    }, this)
                );
            }
        },

        addTab: function (tab) {
            if (tab.canDelete == undefined) {
                tab.canDelete = this.options.canDelete;
            }

            const $tab = $('<div role="tabpanel"></div>').addClass('tab-pane fade');

            $tab.hasContent = false;
            if (tab.content) {
                $tab.append(tab.content);
                $tab.hasContent = true;
            }

            if (this.options.border) {
                $tab.css('border', 'solid ' + this.options.borderColor);
                $tab.css('border-width', '0px 1px 0px 1px');
                $tab.css('padding', '3px');
            }

            const $that = this; //thanks bootstrap! You suck!

            const $nav = $('<li role="tab"></li>')
                .css('white-space', 'nowrap')
                .append(
                    $('<a></a>')
                        .attr('href', '#')
                        .text(tab.tab)
                        .attr('data-tab', tab.tab)
                        .bind('click', function (e) {
                            e.preventDefault();
                            e.stopPropagation();

                            const previous = $that.data('tabs-nav').find('.active:last a')[0];

                            //we can't just call 'show' directly, since it requires an href or data-target attribute
                            //on the link which MUST be an idref to something else in the dom. We don't have those,
                            //so we just do what show does and call activate directly.
                            //
                            //oh, but we can't just say $(this).tab('activate',...) because bootstrap is specifically
                            //wired up not to pass along any arguments to methods invoked in this manner.
                            //
                            //Because bootstrap -sucks-.
                            $.fn.tab.Constructor.prototype.activate.call(
                                $(this),
                                $(this).parent('li'),
                                $that.data('tabs-nav')
                            );

                            $.fn.tab.Constructor.prototype.activate.call(
                                $(this),
                                $tab,
                                $tab.parent(),
                                function () {
                                    $(this).trigger({
                                        type: 'shown',
                                        relatedTarget: previous,
                                    });
                                }
                            );
                            if (!$tab.hasContent) {
                                if (tab.showContentCallback) {
                                    $tab.append(tab.showContentCallback($tab));
                                    if (!tab.dynamicContent) {
                                        $tab.hasContent = true;
                                    }
                                }
                            }
                        })<commit_msg>Add "onShown" tab method to allow for updating a tab upon activation<commit_after>/*

    Easy widget to serve as a tabbed container.

    var $tabs =  new kbaseTabs($('#tabs'), {
            tabPosition : 'bottom', //or left or right or top. Defaults to 'top'
            canDelete : true,       //whether or not the tab can be removed. Defaults to false.
            tabs : [
                {
                    tab : 'T1',                                     //name of the tab
                    content : $('<div></div>').html("I am a tab"),  //jquery object to stuff into the content
                    canDelete : false,                              //override the canDelete param on a per tab basis
                },
                {
                    tab : 'T2',
                    content : $('<div></div>').html("I am a tab 2"),
                },
                {
                    tab : 'T3',
                    content : $('<div></div>').html("I am a tab 3"),
                    show : true,                                    //boolean. This tab gets shown by default. If not specified, the first tab is shown
                    showContentCallback: function // if you don't want to show the content right away, add a callback method that returns the content...
                },
            ],
        }
    );

    useful methods would be:

    $('#tabs').kbaseTabs('showTab', 'T1');
    $('#tabs').kbaseTabs('addTab', tabObject);  //the tabObject defined up above

*/

define(['kbwidget', 'bootstrap', 'jquery', 'kbaseDeletePrompt'], (
    KBWidget,
    bootstrap,
    $,
    kbaseDeletePrompt
) => {
    'use strict';
    return KBWidget({
        name: 'kbaseTabs',

        version: '1.0.0',

        _accessors: ['tabsHeight'],

        options: {
            tabPosition: 'top',
            canDelete: false,
            borderColor: 'lightgray',
        },

        init: function (options) {
            this._super(options);

            this.data('tabs', {});
            this.data('nav', {});

            this.appendUI($(this.$elem));

            return this;
        },

        appendUI: function ($elem, tabs) {
            if (tabs == undefined) {
                tabs = this.options.tabs;
            }

            const $block = $('<div></div>').addClass('tabbable');
            const $tabs = $('<div></div>')
                .addClass('tab-content')
                .attr('id', 'tabs-content')
                .css('height', this.tabsHeight());
            const $nav = $('<ul role="tablist"></ul>')
                .addClass('nav nav-tabs')
                .attr('id', 'tabs-nav');
            $block.append($nav).append($tabs);
            /*if (this.options.tabPosition == 'top') {
                $block.addClass('tabs-above');
                $block.append($nav).append($tabs);
            }
            else if (this.options.tabPosition == 'bottom') {
                $block.addClass('tabs-below');
                $block.append($tabs).append($nav);
            }
            else if (this.options.tabPosition == 'left') {
                $block.addClass('tabs-left');
                $block.append($nav).append($tabs);
            }
            else if (this.options.tabPosition == 'right') {
                $block.addClass('tabs-right');
                $block.append($tabs).append($nav);
            }*/

            this._rewireIds($block, this);

            $elem.append($block);

            if (tabs) {
                $.each(
                    tabs,
                    $.proxy(function (idx, tab) {
                        this.addTab(tab);
                    }, this)
                );
            }
        },

        addTab: function (tab) {
            if (tab.canDelete == undefined) {
                tab.canDelete = this.options.canDelete;
            }

            const $tab = $('<div role="tabpanel"></div>').addClass('tab-pane fade');

            $tab.hasContent = false;
            if (tab.content) {
                $tab.append(tab.content);
                $tab.hasContent = true;
            }

            if (this.options.border) {
                $tab.css('border', 'solid ' + this.options.borderColor);
                $tab.css('border-width', '0px 1px 0px 1px');
                $tab.css('padding', '3px');
            }

            const $that = this; //thanks bootstrap! You suck!

            const $nav = $('<li role="tab"></li>')
                .css('white-space', 'nowrap')
                .append(
                    $('<a></a>')
                        .attr('href', '#')
                        .text(tab.tab)
                        .attr('data-tab', tab.tab)
                        .bind('click', function (e) {
                            e.preventDefault();
                            e.stopPropagation();

                            const previous = $that.data('tabs-nav').find('.active:last a')[0];

                            //we can't just call 'show' directly, since it requires an href or data-target attribute
                            //on the link which MUST be an idref to something else in the dom. We don't have those,
                            //so we just do what show does and call activate directly.
                            //
                            //oh, but we can't just say $(this).tab('activate',...) because bootstrap is specifically
                            //wired up not to pass along any arguments to methods invoked in this manner.
                            //
                            //Because bootstrap -sucks-.
                            $.fn.tab.Constructor.prototype.activate.call(
                                $(this),
                                $(this).parent('li'),
                                $that.data('tabs-nav')
                            );

                            $.fn.tab.Constructor.prototype.activate.call(
                                $(this),
                                $tab,
                                $tab.parent(),
                                function () {
                                    $(this).trigger({
                                        type: 'shown',
                                        relatedTarget: previous,
                                    });
                                }
                            );
                            if (!$tab.hasContent) {
                                if (tab.showContentCallback) {
                                    $tab.append(tab.showContentCallback($tab));
                                    if (!tab.dynamicContent) {
                                        $tab.hasContent = true;
                                    }
                                }
                            }
                            if (tab.onShown) {
                                try {
                                    tab.onShown();
                                } catch (ex) {
                                    console.error('Error in "onShown"', ex);
                                }
                            }
                        })
{'fraction_non_alphanumeric': 0.12722170252572498, 'fraction_numerical': 0.0021587392962509892, 'mean_word_length': 0.973867348388013, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 25, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '525311', 'n_tokens_mistral': 3415, 'n_tokens_neox': 3191, 'n_words': 789}