diff --git a/assets/js/app.js b/assets/js/app.js index 93069fd8..f10c9f2d 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -35,29 +35,14 @@ import '../bootstrap'; // Need jQuery? Install it with "yarn add jquery", then uncomment to require it. const $ = require('jquery'); -import './events_base' - //Only include javascript import '@fortawesome/fontawesome-free/css/all.css' -import 'datatables.net-bs4/css/dataTables.bootstrap4.css' -import 'datatables.net-buttons-bs4/css/buttons.bootstrap4.css' -import 'datatables.net-fixedheader-bs4/css/fixedHeader.bootstrap4.css' -import 'datatables.net-select-bs4/css/select.bootstrap4.css' -import 'bootstrap-select/dist/css/bootstrap-select.css' - -import "patternfly-bootstrap-treeview/src/css/bootstrap-treeview.css" - -import "bootstrap-fileinput/css/fileinput.css" - - require('bootstrap'); -// Import Bootstrap treeview -import "patternfly-bootstrap-treeview"; - import "./sidebar" import "./datatables"; +//import "./tab_remember"; import "./register_events"; /** diff --git a/assets/js/datatables.js b/assets/js/datatables.js index 30053f6c..e2ded416 100644 --- a/assets/js/datatables.js +++ b/assets/js/datatables.js @@ -1,15 +1,19 @@ "use strict"; +//Styles +import 'datatables.net-bs4/css/dataTables.bootstrap4.css' +import 'datatables.net-buttons-bs4/css/buttons.bootstrap4.css' +import 'datatables.net-fixedheader-bs4/css/fixedHeader.bootstrap4.css' +import 'datatables.net-select-bs4/css/select.bootstrap4.css' +import 'datatables.net-responsive-bs4/css/responsive.bootstrap4.css'; +//JS import 'datatables.net-bs4'; import 'datatables.net-buttons-bs4'; import 'datatables.net-buttons/js/buttons.colVis.js'; -//require( 'datatables.net-buttons/js/buttons.html5.js' ); -//require( 'datatables.net-buttons/js/buttons.print.js' ); import 'datatables.net-fixedheader-bs4'; import 'datatables.net-select-bs4'; import 'datatables.net-colreorder-bs4'; import 'datatables.net-responsive-bs4'; -import 'datatables.net-responsive-bs4/css/responsive.bootstrap4.css'; import './lib/datatables'; diff --git a/assets/js/events_base.js b/assets/js/events_base.js deleted file mode 100644 index 97e210b7..00000000 --- a/assets/js/events_base.js +++ /dev/null @@ -1,27 +0,0 @@ -function registerLoadHandler(fn) { - document.documentElement.addEventListener('turbo:load', fn); -} - - -registerLoadHandler(function() { - /** - * Register the button, to jump to the top of the page. - */ - $(document).on("ajaxUI:start", function registerJumpToTop() { - $(window).scroll(function () { - if ($(this).scrollTop() > 50) { - $('#back-to-top').fadeIn(); - } else { - $('#back-to-top').fadeOut(); - } - }); - // scroll body to 0px on click - $('#back-to-top').click(function () { - $('#back-to-top').tooltip('hide'); - $('body,html').animate({ - scrollTop: 0 - }, 800); - return false; - }).tooltip(); - }); -}) \ No newline at end of file diff --git a/assets/js/jquery.tristate.js b/assets/js/lib/jquery.tristate.js similarity index 100% rename from assets/js/jquery.tristate.js rename to assets/js/lib/jquery.tristate.js diff --git a/assets/js/tagsinput.js b/assets/js/lib/tagsinput.js similarity index 100% rename from assets/js/tagsinput.js rename to assets/js/lib/tagsinput.js diff --git a/assets/js/register_events.js b/assets/js/register_events.js index 8c9e11a6..83335123 100644 --- a/assets/js/register_events.js +++ b/assets/js/register_events.js @@ -1,8 +1,35 @@ 'use strict'; +//CSS +import 'bootstrap-select/dist/css/bootstrap-select.css' +import "bootstrap-fileinput/css/fileinput.css" + +//JS +import "bootstrap-select"; +import "./lib/jquery.tristate" +import "bootstrap-fileinput"; + +import 'corejs-typeahead'; +const Bloodhound = require('corejs-typeahead/dist/bloodhound.js'); +import './lib/tagsinput'; + + + const RegisterEventHelper = class { constructor() { this.registerToasts(); + this.registerTooltips(); + this.registerFileInput(); + this.registerJumpToTopBtn(); + + this.registerTriStateCheckboxes(); + + this.registerBootstrapSelectPicker(); + + this.registerSpecialCharInput(); + this.registerHoverPics(); + + this.registerAutocompleteTagsinput(); } registerLoadHandler(fn) { @@ -12,6 +39,189 @@ const RegisterEventHelper = class { registerToasts() { this.registerLoadHandler(() => $(".toast").toast('show')); } + + registerTooltips() { + this.registerLoadHandler(() => { + $(".tooltip").remove(); + $('a[title], button[title], span[title], h6[title], h3[title], i.fas[title]') + //@ts-ignore + .tooltip("hide").tooltip({container: "body", placement: "auto", boundary: 'window'}); + }); + } + + registerHoverPics() { + + } + + registerFileInput() { + this.registerLoadHandler(() => { + $(".file").fileinput(); + }); + } + + registerJumpToTopBtn() { + this.registerLoadHandler(() => { + $(window).scroll(function () { + if ($(this).scrollTop() > 50) { + $('#back-to-top').fadeIn(); + } else { + $('#back-to-top').fadeOut(); + } + }); + // scroll body to 0px on click + $('#back-to-top').click(function () { + $('#back-to-top').tooltip('hide'); + $('body,html').animate({ + scrollTop: 0 + }, 800); + return false; + }).tooltip(); + }); + } + + registerTriStateCheckboxes() { + this.registerLoadHandler(() => { + $(".tristate").tristate( { + checked: "true", + unchecked: "false", + indeterminate: "indeterminate", + }); + + $('.permission_multicheckbox:checkbox').change(function() { + //Find the other checkboxes in this row, and change their value + var $row = $(this).parents('tr'); + + //@ts-ignore + var new_state = $(this).tristate('state'); + + //@ts-ignore + $('.tristate:checkbox', $row).tristate('state', new_state); + }); + }) + } + + registerBootstrapSelectPicker() { + this.registerLoadHandler(() => { + $(".selectpicker").selectpicker({ + dropdownAlignRight: 'auto', + container: '#content', + }); + }); + } + + registerAutocompleteTagsinput() { + this.registerLoadHandler(() => { + $('input.tagsinput').each(function() { + + //Use typeahead if an autocomplete url was specified. + if($(this).data('autocomplete')) { + + //@ts-ignore + var engine = new Bloodhound({ + //@ts-ignore + datumTokenizer: Bloodhound.tokenizers.obj.whitespace(''), + //@ts-ignore + queryTokenizer: Bloodhound.tokenizers.obj.whitespace(''), + remote: { + url: $(this).data('autocomplete'), + wildcard: 'QUERY' + } + }); + + //@ts-ignore + $(this).tagsinput({ + typeaheadjs: { + name: 'tags', + source: engine.ttAdapter() + } + }); + + + } else { //Init tagsinput without typeahead + //@ts-ignore + $(this).tagsinput(); + } + }) + }); + } + + registerSpecialCharInput() { + this.registerLoadHandler(() => { + //@ts-ignore + $("input[type=text], textarea, input[type=search]").unbind("keydown").keydown(function (event) { + let greek = event.altKey; + + let greek_char = ""; + if (greek){ + switch(event.key) { + case "w": //Omega + greek_char = '\u2126'; + break; + case "u": + case "m": //Micro + greek_char = "\u00B5"; + break; + case "p": //Phi + greek_char = "\u03C6"; + break; + case "a": //Alpha + greek_char = "\u03B1"; + break; + case "b": //Beta + greek_char = "\u03B2"; + break; + case "c": //Gamma + greek_char = "\u03B3"; + break; + case "d": //Delta + greek_char = "\u03B4"; + break; + case "l": //Pound + greek_char = "\u00A3"; + break; + case "y": //Yen + greek_char = "\u00A5"; + break; + case "o": //Yen + greek_char = "\u00A4"; + break; + case "1": //Sum symbol + greek_char = "\u2211"; + break; + case "2": //Integral + greek_char = "\u222B"; + break; + case "3": //Less-than or equal + greek_char = "\u2264"; + break; + case "4": //Greater than or equal + greek_char = "\u2265"; + break; + case "5": //PI + greek_char = "\u03c0"; + break; + case "q": //Copyright + greek_char = "\u00A9"; + break; + case "e": //Euro + greek_char = "\u20AC"; + break; + } + + if(greek_char=="") return; + + let $txt = $(this); + //@ts-ignore + let caretPos = $txt[0].selectionStart; + let textAreaTxt = $txt.val().toString(); + $txt.val(textAreaTxt.substring(0, caretPos) + greek_char + textAreaTxt.substring(caretPos) ); + + } + }); + //@ts-ignore + this.greek_once = true; + }) + } } export default new RegisterEventHelper(); \ No newline at end of file diff --git a/assets/js/sidebar.js b/assets/js/sidebar.js index 92f16985..5a0db639 100644 --- a/assets/js/sidebar.js +++ b/assets/js/sidebar.js @@ -1,5 +1,8 @@ 'use strict'; +import "patternfly-bootstrap-treeview/src/css/bootstrap-treeview.css" +import "patternfly-bootstrap-treeview"; + const SidebarHelper = class { constructor() { this.BASE = $("body").data("base-url"); @@ -9,9 +12,50 @@ const SidebarHelper = class { } console.info("Base path is " + this.BASE); + this.registerSidebarHideButton(); this.fillTrees(); } + registerSidebarHideButton() + { + let $sidebar = $("#fixed-sidebar"); + let $container = $("#main"); + let $toggler = $('#sidebar-toggle-button'); + + function sidebarHide() { + $sidebar.hide(); + $container.removeClass('col-md-9 col-lg-10 offset-md-3 offset-lg-2'); + $container.addClass('col-12'); + $toggler.html(''); + $toggler.data('hidden', true); + localStorage.setItem('sidebarHidden', 'true'); + } + function sidebarShow() { + let $sidebar = $("#fixed-sidebar"); + $sidebar.show(); + let $container = $("#main"); + $container.removeClass('col-12'); + $container.addClass('col-md-9 col-lg-10 offset-md-3 offset-lg-2'); + $toggler.html(''); + $toggler.data('hidden', false); + localStorage.setItem('sidebarHidden', 'false'); + } + + //Make the state persistent over reloads + if(localStorage.getItem('sidebarHidden') === 'true') { + sidebarHide(); + } + + //Register handler + $toggler.click(function() { + if($(this).data('hidden')) { + sidebarShow(); + } else { + sidebarHide(); + } + }); + } + /** * Fill the trees with the given data. */ diff --git a/assets/js/tab_remember.js b/assets/js/tab_remember.js new file mode 100644 index 00000000..e302a08d --- /dev/null +++ b/assets/js/tab_remember.js @@ -0,0 +1,46 @@ +"use strict"; + +/** + * This listener keeps track of which tab is currently selected (using hash and localstorage) and will try to open + * that tab on reload. That means that if the user changes something, he does not have to switch back to the tab + * where he was before submit. + */ +let TabRememberHelper = new class { + constructor() { + document.addEventListener("turbo:load", () => { + //Determine which tab should be shown (use hash if specified, otherwise use localstorage) + var $activeTab = null; + if (location.hash) { + $activeTab = $('a[href=\'' + location.hash + '\']'); + } else if (localStorage.getItem('activeTab')) { + $activeTab = $('a[href="' + localStorage.getItem('activeTab') + '"]'); + } + + if ($activeTab) { + //Findout if the tab has any parent tab we have to show before + var parents = $($activeTab).parents('.tab-pane'); + parents.each(function (n) { + $('a[href="#' + $(this).attr('id') + '"]').tab('show'); + }); + //Finally show the active tab itself + $activeTab.tab('show'); + } + + $('body').on('click', 'a[data-toggle=\'tab\']', function (e) { + e.preventDefault() + var tab_name = this.getAttribute('href') + if (history.replaceState) { + history.replaceState(null, null, tab_name) + } else { + location.hash = tab_name + } + localStorage.setItem('activeTab', tab_name) + + $(this).tab('show'); + return false; + }); + }); + } +} + +//export default new TabRememberHelper(); \ No newline at end of file