This will be toggled as well
+ */
+ var showHideUtil = function(element) {
+
+ var showHideId;
+
+ function init() {
+ if (!element) {
+ throw new Error('ShowHide utility cannot be setup without an element!');
+ }
+
+ if (element.classList.contains(SHOW_HIDE_INITIALIZED_CLASS)) {
+ return false;
+ }
+
+ // register click listener
+ addClickListener();
+
+ // param showHideId
+ if (element.dataset.showHideId) {
+ showHideId = element.dataset.showHideId;
+ }
+
+ // param showHideCollapsed
+ var collapsed = false;
+ if (element.dataset.showHideCollapsed !== undefined) {
+ collapsed = true;
+ }
+ if (showHideId) {
+ var localStorageCollapsed = getLocalStorage()[showHideId];
+ if (typeof localStorageCollapsed !== 'undefined') {
+ collapsed = localStorageCollapsed;
+ }
+ }
+ element.parentElement.classList.toggle(SHOW_HIDE_COLLAPSED_CLASS, collapsed);
+
+ // param showHideAlign
+ var alignment = element.dataset.showHideAlign;
+ if (alignment === 'right') {
+ element.classList.add(SHOW_HIDE_TOGGLE_RIGHT_CLASS);
+ }
+
+ // mark as initialized
+ element.classList.add(SHOW_HIDE_INITIALIZED_CLASS, SHOW_HIDE_TOGGLE_CLASS);
+
+ return {
+ name: SHOW_HIDE_UTIL_NAME,
+ element: element,
+ destroy: function() {},
+ };
+ }
+
+ function addClickListener() {
+ element.addEventListener('click', function clickListener() {
+ var newState = element.parentElement.classList.toggle(SHOW_HIDE_COLLAPSED_CLASS);
+
+ if (showHideId) {
+ setLocalStorage(showHideId, newState);
+ }
+ });
+ }
+
+ function setLocalStorage(id, state) {
+ var lsData = getLocalStorage();
+ lsData[id] = state;
+ window.localStorage.setItem(SHOW_HIDE_LOCAL_STORAGE_KEY, JSON.stringify(lsData));
+ }
+
+ function getLocalStorage() {
+ return JSON.parse(window.localStorage.getItem(SHOW_HIDE_LOCAL_STORAGE_KEY)) || {};
+ }
+
+ return init();
+ };
+
+ if (UtilRegistry) {
+ UtilRegistry.register({
+ name: SHOW_HIDE_UTIL_NAME,
+ selector: SHOW_HIDE_UTIL_SELECTOR,
+ setup: showHideUtil,
+ });
+ }
+
+})();
diff --git a/static/es/utils/tabber.js b/static/es/utils/tabber.js
new file mode 100644
index 000000000..e1c906d6b
--- /dev/null
+++ b/static/es/utils/tabber.js
@@ -0,0 +1,90 @@
+(function($) {
+
+ document.addEventListener('DOMContentLoaded', function() {
+ 'use strict';
+
+ // define plugin
+ $.fn.tabgroup = function() {
+
+ var $this = $(this);
+ var $openers = $('
');
+ $this.prepend($openers);
+
+ var openedByDefault = $this.data('tab-open') || 0;
+ var tabs = [];
+ var currentTab = {};
+
+ $this.find('.tab').each(function(i, t) {
+ var tab = $(t);
+ tab.data('tab-index', i);
+ var tabName = tab.data('tab-name') || 'Tab '+i;
+ var tabFile = tab.data('tab-file') || false;
+ var $opener = makeOpener(tabName, i);
+ $openers.append($opener);
+ if (tab.find('.tab-title')) {
+ tab.find('.tab-title').remove();
+ }
+ tab.hide();
+ var loaded = false;
+ tabs.push({index: i, name: tabName, file: tabFile, dom: tab, opener: $opener, loaded: loaded });
+ });
+
+ $this.on('click', 'a[href^="#"]', function(event) {
+ var $target = $(event.currentTarget);
+ var tab = getTabByName($target.attr('href').replace('#', ''));
+ if ( tab ) {
+ showTab(tab.index);
+ }
+ event.preventDefault();
+ });
+
+ function getTabByName(name) {
+ var it = -1;
+ $.each(tabs, function(i, t) {
+ if ( t.name.toLowerCase() === name.toLowerCase() ) {
+ it = i;
+ }
+ });
+ if ( it >= 0 ) {
+ return tabs[it];
+ } else {
+ return false;
+ }
+ }
+
+ function makeOpener(tabName, i) {
+ return $('
'+tabName+'').
+ on('click', function() {
+ showTab(i);
+ });
+ }
+
+ function showTab(i) {
+ tabs.forEach(function(t) {
+ t.dom.hide();
+ t.opener.removeClass('tab-visible');
+ });
+ currentTab = tabs[i];
+ if ( !currentTab.loaded && currentTab.file ){
+ $.get(currentTab.file, function(res) {
+ currentTab.dom.html(res);
+ currentTab.loaded = true;
+ });
+ }
+ currentTab.opener.addClass('tab-visible');
+ currentTab.dom.show();
+ }
+
+ showTab(openedByDefault);
+ currentTab = tabs[openedByDefault];
+
+ };
+
+ // apply plugin to all available tab-groups if on wide screen
+ if (window.innerWidth > 768) {
+ $('.tab-group').each(function(i, t) {
+ $(t).tabgroup();
+ });
+ }
+ });
+})($);