htmljquerycsstabsjquery-terminal

How to create tabs for JQuery terminal


Im trying to create a tab system for my JQuery terminal, but I cant see how I can add functionality to it. For example, I want the X button to close the current tab, and a + button to open a new tab. Im not really good a javascript obviously, but how can I get started in getting this to work? I have seen an example from github that could help me, but I cant access it right now since my school blocks sites, so if you are reading this, can you get the code from here: https://gist.github.com/lawrenceamer/3f2d48be524ee0eca95ada3910d4294d and put it in stack overflow for me? Or give me tips in completing this?

This is the code I have made so far:

<link href="https://db.onlinewebfonts.com/c/1db29588408eadbd4406aae9238555eb?family=Consolas" rel="stylesheet"> <link href="thetabs.css" rel='stylesheet'>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<style>
@import url('https://fonts.cdnfonts.com/css/menlo');
</style>

<style>
iframe {
  width: 100%;
  height: 100%;
}
a {
font-family: Menlo;
}
.ui-tabs .ui-state-active:after {
  content: "x";
  position: absolute;
  top: 5px;
  right: 5px;
  font-size: 12px;
  cursor: pointer;
}
.tab {
  outline: none;
}
  #terminal-tabs {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    overflow: hidden;
  }
  
  #terminal-tabs ul {
    position: sticky;
    top: 0;
    z-index: 1;
  }
  body {
  zoom: reset !important;
}
  #tab-1,
  #tab-2,
  #tab-3 {
    flex-grow: 1;
    display: flex;
    overflow: auto;
  }
  
  #tab-1 iframe,
  #tab-2 iframe,
  #tab-3 iframe {
    width: 100%;
    height: 100%;
    border: none;
  }
</style>

<div id="terminal-tabs">
  <ul>
    <li><a href="#tab-1">My-Terminal   (1)</a></li>
    <li><a href="#tab-2">My-Terminal   (2)</a></li>
    <li><a href="#tab-3">My-Terminal   (3)</a></li>
    <li><a href="#tab-4">My-Terminal   (4)</a></li>
  </ul>
  <div id="tab-1">

     <!-- terminal is hosted here from iframe  -->
  </div>
  <div id="tab-2">

       <!-- terminal is hosted here from iframe  -->
  </div>
  <div id="tab-3">

 <!-- terminal is hosted here from iframe  -->
  </div>
    <div id="tab-4">

    <!-- terminal is hosted here from iframe  -->
  </div>
</div>



<script>

$(function() {
  $("#terminal-tabs").tabs();
});

$("#terminal-tabs").on("click", ".ui-tabs-close", function() {
  var panelId = $(this).closest("li").remove().attr("aria-controls");
  $("#" + panelId).remove();
  $("#terminal-tabs").tabs("refresh");
});
$("#terminal-tabs .ui-tabs-nav").append('<li class="ui-state-default ui-corner-top ui-tabs-new"><a href="#">+</a></li>');

$("#terminal-tabs").on("click", ".ui-tabs-new", function() {
  var newTabIndex = $("#terminal-tabs .ui-tabs-nav li").length - 1;
  $("#terminal-tabs").tabs("add", "#tab-" + newTabIndex, "Tab " + newTabIndex);
});
</script>

(Note: I also understand that stackoverflow is not just a site where you could ask anything and expect an answer back, but I mostly do coding on a school pc since I dont have a working pc right now, and so I try to work with what I have. And yes, I have tried to do some research on this because google exists, but with my school's blocking system, there are alot of limitations.)


Solution

  • let count = 0;
    terminal_tabs({
        echo(...args) {
           this.echo(args);
        }
    }, {
        checkArity: false,
        greetings: 'This is really working'
    });
    
    function terminal_tabs(interpreter, option) {
        new_terminal(interpreter, option);
        $('.cloak').removeClass('cloak');
    
        $('.tabs').on('click', 'li.tab', function() {
            var li = $(this);
            tab_activate(this);
            return false;
        }).on('click', 'li.tab .close', function() {
            remove_tab(this);
            return false;
        }).on('click', 'li.new', () => new_terminal(interpreter, option));
        
    }
    
    function remove_tab(el) {
        el = $(el);
        const $li = el.closest('li');
        const $tabs = el.closest('.tabs');
        const index = $li.index();
        const $terminals = $tabs.find('.content > div');
        const $term = $terminals.eq(index).terminal();
        if ($terminals.length > 1 && $term.is('.active')) {
            const $other = $term.prev();
            if (!$other.length) {
                $other = $term.next();
            }
            const $new_li = $tabs.find('> ul li').eq($other.index());
            tab_activate($new_li);
        }
        $term.destroy().remove();
        $li.remove();
    }
    
    function tab_activate(li) {
        const $li = $(li);
        const index = $li.index();
        $li.addClass('active').siblings().removeClass('active');
        const $content = $li.closest('ul').next();
        const $tab = $content.children()
             .eq(index)
             .addClass('active');
        $tab.siblings()
            .removeClass('active');
    }
    
    
    function new_terminal(interpreter = $.noop, options = null, label = null) {
        const id = ++count;
        options = options ?? {
            greetings: `Welcome to jQuery Terminal, no: ${id}.\n`
        };
        const $term = $('<div/>').terminal(interpreter, options);
        label = options.label ?? `Terminal &lt;${id}&gt;`;
        const $li = $(`<li class="tab">
                       <a href="#">${label}</a>
                       <span class="close">&times</span>
                     </li>`);
        const $content = $('.tabs .content');
        if ($content.is(':empty')) {
            $li.add($term).addClass('active');
        }
        const $add = $('.tabs > ul li.new');
        $li.insertBefore($add);
        $content.append($term);
        tab_activate($li);
    }
    body {
        margin: 0;
        padding: 0;
        background: black;
    }
    :root {
        --size: 1.4;
        --color: #18B70A;
        --glow: 1;
    }
    .tabs.cloak {
        display: none;
    }
    body, html {
        height: 100%;
    }
    /* tabs */
    .tabs {
        --gap: 10px;
        display: flex;
        flex-direction: column;
        --original-background: var(--backgroud, #000);
    }
    .tabs, .tabs .content > div {
        height: 100%;
    }
    .tabs > ul {
        list-style: none;
        margin: 0;
        padding: var(--gap, 10px) var(--gap, 10px) 0;
        font-family: var(--font, monospace);
    
    }
    .tabs > ul > li {
        border-color: var(--color, #aaa);
        border-radius: 3px 3px 0 0;
        border-style: solid;
        border-width: 1px 1px 0;
        cursor: pointer;
        display: inline-block;
        padding: 6px 14px;
        position: relative;
        text-align: center;
        font-size: calc(var(--size, 1) * 12px);
    }
    .tabs > ul > li > * {
        background: var(--background, #000);
        color: var(--color, #aaa);
        text-shadow: 0 0 calc(var(--glow) * 5px) var(--color, #ccc);
    }
    .tabs > ul > li .close, .tabs > ul > li.new a {
        display: inline-block;
        line-height: 0.9em;
        padding: 0 2px;
        border-radius: 50%;
    }
    .tabs > ul > li .close:hover, .tabs > ul > li.new a:hover {
        --background: var(--link-color, #3377FF);
        --color: var(--original-background, #000);
    }
    .tabs > ul > li + li {
        margin-left: var(--gap, 10px);
    }
    .tabs > ul > li a {
        text-decoration: none;
    }
    .tabs > ul > li.active::after {
        background-color: var(--background, #000);
        bottom: -1px;
        content: '';
        height: 1px;
        left: 0;
        position: absolute;
        width: 100%;
    }
    .tabs .content {
        border-top: solid 1px var(--color, #ccc);
        list-style: none;
        margin: 0;
        padding: 0;
        flex-grow: 1;
    }
    .tabs .content > :not(.active) {
        display: none;
    }
    <script src="https://cdn.jsdelivr.net/npm/jquery"></script>
    <script src="https://cdn.jsdelivr.net/npm/jquery.terminal/js/jquery.terminal.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/jquery.terminal/css/jquery.terminal.css" rel="stylesheet"/>
    <div class="tabs cloak">
        <ul>
            <li class="new">
                <a href="#">+</a>
            </li>
        </ul>
        <div class="content"></div>
    </div>