diff --git a/assets/js/app.js b/assets/js/app.js index a393a474..df469a78 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -17,15 +17,6 @@ * along with this program. If not, see . */ -/* - * Welcome to your app's main JavaScript file! - * - * We recommend including the built version of this JavaScript file - * (and its CSS file) in your base layout (base.html.twig). - */ - -// any CSS you require will output into a single css file (app.css in this case) - // Main CSS files import '../css/app.css'; @@ -46,57 +37,4 @@ import "./register_events"; import "./tristate_checkboxes"; //Define jquery globally -window.$ = window.jQuery = require("jquery") - - -/** - - require('bootstrap-select'); -require('jquery-form'); -require('corejs-typeahead/dist/typeahead.bundle.min'); -window.Bloodhound = require('corejs-typeahead/dist/bloodhound.js'); - -; - - - -require('bootstrap-fileinput'); - -require('./datatables.js'); - -window.bootbox = require('bootbox'); - -require("marked"); -window.DOMPurify = require("dompurify"); - -// Includes required for tag input -require('./tagsinput.js'); -require('../css/tagsinput.css'); - -//Tristate checkbox support -require('./jquery.tristate.js'); - -require('darkmode-js'); - -//Equation rendering -require('katex'); -window.renderMathInElement = require('katex/contrib/auto-render/auto-render').default; -import 'katex/dist/katex.css'; - -window.ClipboardJS = require('clipboard'); - -require('../ts_src/ajax_ui'); -//import {ajaxUI} from "../ts_src/ajax_ui"; - -//window.ajaxUI = ajaxUI; - -//Require all events; -require('../ts_src/event_listeners'); - - -//Start AjaxUI AFTER all event has been registered -//$(document).ready(ajaxUI.start()); - -*/ - -//console.log('Hello Webpack Encore! Edit me in assets/js/app.js'); \ No newline at end of file +window.$ = window.jQuery = require("jquery") \ No newline at end of file diff --git a/assets/ts_src/ajax_ui.ts b/assets/ts_src/ajax_ui.ts deleted file mode 100644 index 0ff6825b..00000000 --- a/assets/ts_src/ajax_ui.ts +++ /dev/null @@ -1,605 +0,0 @@ -/* - * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). - * - * Copyright (C) 2019 - 2020 Jan Böhmer (https://github.com/jbtronics) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * Extract the title (The name between the tags) of a HTML snippet. - * @param {string} html The HTML code which should be searched. - * @returns {string} The title extracted from the html. - */ -function extractTitle(html : string) : string { - let title : string = ""; - let regex = /<title>(.*?)<\/title>/gi; - if (regex.test(html)) { - let matches = html.match(regex); - for(let match in matches) { - title = $(matches[match]).text(); - } - } - return title; -} - - -class AjaxUI { - - protected BASE = "/"; - - private trees_filled : boolean = false; - - private statePopped : boolean = false; - - public xhr : XMLHttpRequest; - - public constructor() - { - //Make back in the browser go back in history - window.onpopstate = this.onPopState; - $(document).ajaxError(this.onAjaxError.bind(this)); - //$(document).ajaxComplete(this.onAjaxComplete.bind(this)); - } - - /** - * Starts the ajax ui und execute handlers registered in addStartAction(). - * Should be called in a document.ready, after handlers are set. - */ - public start(disabled : boolean = false) - { - if(disabled) { - return; - } - - console.info("AjaxUI started!"); - - this.BASE = $("body").data("base-url"); - //If path doesn't end with slash, add it. - if(this.BASE[this.BASE.length - 1] !== '/') { - this.BASE = this.BASE + '/'; - } - console.info("Base path is " + this.BASE); - - //Show flash messages - $(".toast").toast('show'); - - - /** - * Save the XMLHttpRequest that jQuery used, to the class, so we can acess the responseURL property. - * This is a work-around as long jQuery does not implement this property in its jQXHR objects. - */ - //@ts-ignore - jQuery.ajaxSettings.xhr = function () { - //@ts-ignore - let xhr = new window.XMLHttpRequest(); - //Save the XMLHttpRequest to the class. - ajaxUI.xhr = xhr; - return xhr; - }; - - - this.registerLinks(); - this.registerForm(); - this.fillTrees(); - - this.initDataTables(); - - //Trigger start event - $(document).trigger("ajaxUI:start"); - } - - /** - * Fill the trees with the given data. - */ - public fillTrees() - { - let categories = localStorage.getItem("tree_datasource_tree-categories"); - let devices = localStorage.getItem("tree_datasource_tree-devices"); - let tools = localStorage.getItem("tree_datasource_tree-tools"); - - if(categories == null) { - categories = "categories"; - } - - if(devices == null) { - devices = "devices"; - } - - if(tools == null) { - tools = "tools"; - } - - this.treeLoadDataSource("tree-categories", categories); - this.treeLoadDataSource("tree-devices", devices); - this.treeLoadDataSource("tree-tools", tools); - - this.trees_filled = true; - - //Register tree btns to expand all, or to switch datasource. - $(".tree-btns").click(function (event) { - event.preventDefault(); - $(this).parents("div.dropdown").removeClass('show'); - //$(this).closest(".dropdown-menu").removeClass('show'); - $(".dropdown-menu.show").removeClass("show"); - let mode = $(this).data("mode"); - let target = $(this).data("target"); - let text = $(this).text() + " \n<span class='caret'></span>"; //Add caret or it will be removed, when written into title - - if (mode==="collapse") { - // @ts-ignore - $('#' + target).treeview('collapseAll', { silent: true }); - } - else if(mode==="expand") { - // @ts-ignore - $('#' + target).treeview('expandAll', { silent: true }); - } else { - localStorage.setItem("tree_datasource_" + target, mode); - ajaxUI.treeLoadDataSource(target, mode); - } - - return false; - }); - } - - /** - * Load the given url into the tree with the given id. - * @param target_id - * @param datasource - */ - protected treeLoadDataSource(target_id, datasource) { - let text : string = $(".tree-btns[data-mode='" + datasource + "']").html(); - text = text + " \n<span class='caret'></span>"; //Add caret or it will be removed, when written into title - switch(datasource) { - case "categories": - ajaxUI.initTree("#" + target_id, 'tree/categories'); - break; - case "locations": - ajaxUI.initTree("#" + target_id, 'tree/locations'); - break; - case "footprints": - ajaxUI.initTree("#" + target_id, 'tree/footprints'); - break; - case "manufacturers": - ajaxUI.initTree("#" + target_id, 'tree/manufacturers'); - break; - case "suppliers": - ajaxUI.initTree("#" + target_id, 'tree/suppliers'); - break; - case "tools": - ajaxUI.initTree("#" + target_id, 'tree/tools'); - break; - case "devices": - ajaxUI.initTree("#" + target_id, 'tree/devices'); - ajaxUI.initTree("#" + target_id, 'tree/devices'); - break; - } - - $( "#" + target_id + "-title").html(text); - } - - /** - * Fill a treeview with data from the given url. - * @param tree The Jquery selector for the tree (e.g. "#tree-tools") - * @param url The url from where the data should be loaded - */ - public initTree(tree, url) { - //let contextmenu_handler = this.onNodeContextmenu; - $.getJSON(ajaxUI.BASE + url, function (data) { - // @ts-ignore - $(tree).treeview({ - data: data, - enableLinks: false, - showIcon: false, - showBorder: true, - searchResultBackColor: '#ffc107', - searchResultColor: '#000', - onNodeSelected: function(event, data) { - if(data.href) { - ajaxUI.navigateTo(data.href); - } - }, - //onNodeContextmenu: contextmenu_handler, - expandIcon: "fas fa-plus fa-fw fa-treeview", collapseIcon: "fas fa-minus fa-fw fa-treeview"}) - .on('initialized', function() { - $(this).treeview('collapseAll', { silent: true }); - - //Implement searching if needed. - if($(this).data('treeSearch')) { - let _this = this; - let $search = $($(this).data('treeSearch')); - $search.on( 'input', function() { - $(_this).treeview('collapseAll', { silent: true }); - $(_this).treeview('search', [$search.val()]); - }); - } - }); - }); - } - - - /** - * Register all links, for loading via ajax. - */ - public registerLinks() - { - // Unbind all old handlers, so the things are not executed multiple times. - $('a').not(".link-external, [data-no-ajax], .page-link, [href^='javascript'], [href^='#']").unbind('click').click(function (event) { - let a = $(this); - let href = $.trim(a.attr("href")); - //Ignore links without href attr and nav links ('they only have a #) - if(href != null && href != "" && href.charAt(0) !== '#') { - event.preventDefault(); - ajaxUI.navigateTo(href); - } - } - ); - console.debug('Links registered!'); - } - - protected getFormOptions() : JQueryFormOptions - { - return { - success: this.onAjaxComplete, - beforeSerialize: function($form, options) : boolean { - - //Update the content of textarea fields using CKEDITOR before submitting. - //@ts-ignore - if(typeof CKEDITOR !== 'undefined') { - //@ts-ignore - for (let name in CKEDITOR.instances) { - //@ts-ignore - CKEDITOR.instances[name].updateElement(); - } - } - - //Check every checkbox field, so that it will be submitted (only valid fields are submitted) - $form.find("input[type=checkbox].tristate").prop('checked', true); - - return true; - }, - beforeSubmit: function (arr, $form, options) : boolean { - //When data-with-progbar is specified, then show progressbar. - if($form.data("with-progbar") != undefined) { - ajaxUI.showProgressBar(); - } - return true; - } - }; - } - - /** - * Register all forms for loading via ajax. - */ - public registerForm() - { - - let options = this.getFormOptions(); - - $('form').not('[data-no-ajax]').ajaxForm(options); - - console.debug('Forms registered!'); - } - - - /** - * Submits the given form via ajax. - * @param form The form that will be submmitted. - * @param btn The btn via which the form is submitted - */ - public submitForm(form, btn = null) - { - let options = ajaxUI.getFormOptions(); - - if(btn) { - options.data = {}; - options.data[$(btn).attr('name')] = $(btn).attr('value'); - } - - $(form).ajaxSubmit(options); - } - - - /** - * Show the progressbar - */ - public showProgressBar() - { - //Blur content background - $('#content').addClass('loading-content'); - - // @ts-ignore - $('#progressModal').modal({ - keyboard: false, - backdrop: false, - show: true - }); - } - - /** - * Hides the progressbar. - */ - public hideProgressBar() - { - // @ts-ignore - $('#progressModal').modal('hide'); - //Remove the remaining things of the modal - $('.modal-backdrop').remove(); - $('body').removeClass('modal-open'); - $('body, .navbar').css('padding-right', ""); - - } - - - /** - * Navigates to the given URL - * @param url The url which should be opened. - * @param show_loading Show the loading bar during loading. - */ - public navigateTo(url : string, show_loading : boolean = true) - { - if(show_loading) { - this.showProgressBar(); - } - $.ajax(url, { - success: this.onAjaxComplete - }); - //$.ajax(url).promise().done(this.onAjaxComplete); - } - - /** - * Called when an error occurs on loading ajax. Outputs the message to the console. - */ - private onAjaxError (event, request, settings) { - 'use strict'; - //Ignore aborted requests. - if (request.statusText =='abort' || request.status == 0) { - return; - } - - //Ignore ajax errors with 200 code (like the ones during 2FA authentication) - if(request.status == 200) { - return; - } - - console.error("Error getting the ajax data from server!"); - console.log(event); - console.log(request); - console.log(settings); - - ajaxUI.hideProgressBar(); - - //Create error text - let title = request.statusText; - - switch(request.status) { - case 500: - title = 'Internal Server Error!'; - break; - case 404: - title = "Site not found!"; - break; - case 403: - title = "Permission denied!"; - break; - } - - var alert = bootbox.alert( - { - size: 'large', - message: function() { - let msg = "Error getting data from Server! <b>Status Code: " + request.status + "</b>"; - - msg += '<br><br><a class=\"btn btn-link\" data-toggle=\"collapse\" href=\"#iframe_div\" >' + 'Show response' + "</a>"; - msg += "<div class=\" collapse\" id='iframe_div'><iframe height='512' width='100%' id='iframe'></iframe></div>"; - - return msg; - }, - title: title, - callback: function () { - //Remove blur - $('#content').removeClass('loading-content'); - } - - }); - - //@ts-ignore - alert.init(function (){ - var dstFrame = document.getElementById('iframe'); - //@ts-ignore - var dstDoc = dstFrame.contentDocument || dstFrame.contentWindow.document; - dstDoc.write(request.responseText); - dstDoc.close(); - }); - - - - //If it was a server error and response is not empty, show it to user. - if(request.status == 500 && request.responseText !== "") - { - console.log("Response:" + request.responseText); - } - } - - /** - * This function gets called every time, the "back" button in the browser is pressed. - * We use it to load the content from history stack via ajax and to rewrite url, so we only have - * to load #content-data - * @param event - */ - private onPopState(event) - { - let page : string = location.href; - ajaxUI.statePopped = true; - ajaxUI.navigateTo(page); - } - - /** - * This function takes the response of an ajax requests, and does the things we need to do for our AjaxUI. - * This includes inserting the content and pushing history. - * @param responseText - * @param textStatus - * @param jqXHR - */ - private onAjaxComplete(responseText: string, textStatus: string, jqXHR: any) - { - console.debug("Ajax load completed!"); - - - ajaxUI.hideProgressBar(); - - /* We need to do the url checking before the parseHTML, so that we dont get wrong url name, caused by scripts - in the new content */ - // @ts-ignore - let url = this.url; - //Check if we were redirect to a new url, then we should use that as new url. - if(ajaxUI.xhr.responseURL) { - url = ajaxUI.xhr.responseURL; - } - - - //Parse response to DOM structure - //We need to preserve javascript, so the table ca - let dom = $.parseHTML(responseText, document, true); - //And replace the content container - $("#content").replaceWith($("#content", dom)); - //Replace login menu too (so everything is up to date) - $("#login-content").replaceWith($('#login-content', dom)); - - //Replace flash messages and show them - $("#message-container").replaceWith($('#message-container', dom)); - $(".toast").toast('show'); - - //Set new title - let title = extractTitle(responseText); - document.title = title; - - //Push to history, if we currently arent poping an old value. - if(!ajaxUI.statePopped) { - history.pushState(null, title, url); - } else { - //Clear pop state - ajaxUI.statePopped = false; - } - - //Do things on the new dom - ajaxUI.registerLinks(); - ajaxUI.registerForm(); - ajaxUI.initDataTables(); - - //Trigger reload event - $(document).trigger("ajaxUI:reload"); - } - - /** - * Init all datatables marked with data-datatable based on their data-settings attribute. - */ - protected initDataTables() - { - //@ts-ignore - $($.fn.DataTable.tables()).DataTable().fixedHeader.disable(); - //@ts-ignore - $($.fn.DataTable.tables()).DataTable().destroy(); - - //Find all datatables and init it. - let $tables = $('[data-datatable]'); - $.each($tables, function(index, table) { - let $table = $(table); - let settings = $table.data('settings'); - - //@ts-ignore - var promise = $('#part_list').initDataTables(settings, - { - colReorder: true, - responsive: true, - "fixedHeader": { header: $(window).width() >= 768, //Only enable fixedHeaders on devices with big screen. Fixes scrolling issues on smartphones. - headerOffset: $("#navbar").height()}, - "buttons": [ { - "extend": 'colvis', - 'className': 'mr-2 btn-light', - "text": "<i class='fa fa-cog'></i>" - }], - "select": $table.data('select') ?? false, - "rowCallback": function( row, data, index ) { - //Check if we have a level, then change color of this row - if (data.level) { - let style = ""; - switch(data.level) { - case "emergency": - case "alert": - case "critical": - case "error": - style = "table-danger"; - break; - case "warning": - style = "table-warning"; - break; - case "notice": - style = "table-info"; - break; - } - - if (style){ - $(row).addClass(style); - } - } - } - }); - - //Register links. - promise.then(function() { - ajaxUI.registerLinks(); - - //Set the correct title in the table. - let title = $('#part-card-header-src'); - $('#part-card-header').html(title.html()); - $(document).trigger('ajaxUI:dt_loaded'); - - - if($table.data('part_table')) { - //@ts-ignore - $('#dt').on( 'select.dt deselect.dt', function ( e, dt, items ) { - let selected_elements = dt.rows({selected: true}); - let count = selected_elements.count(); - - if(count > 0) { - $('#select_panel').removeClass('d-none'); - } else { - $('#select_panel').addClass('d-none'); - } - - $('#select_count').text(count); - - let selected_ids_string = selected_elements.data().map(function(value, index) { - return value['id']; } - ).join(","); - - $('#select_ids').val(selected_ids_string); - - } ); - } - - //Attach event listener to update links after new page selection: - $('#dt').on('draw.dt column-visibility.dt', function() { - ajaxUI.registerLinks(); - $(document).trigger('ajaxUI:dt_loaded'); - }); - }); - }); - - console.debug('Datatables inited.'); - } -} - -export let ajaxUI = new AjaxUI(); \ No newline at end of file diff --git a/assets/ts_src/event_listeners.ts b/assets/ts_src/event_listeners.ts deleted file mode 100644 index 0634b66d..00000000 --- a/assets/ts_src/event_listeners.ts +++ /dev/null @@ -1,349 +0,0 @@ -/* - * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). - * - * Copyright (C) 2019 - 2020 Jan Böhmer (https://github.com/jbtronics) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ - -import {ajaxUI} from "./ajax_ui"; -import "bootbox"; -import "marked"; -import * as marked from "marked"; -import {parse} from "marked"; -import * as ZXing from "@zxing/library"; - -/************************************ - * - * In this file all the functions that has to be called using AjaxUIoperation are registered. - * You can use AjaxUI:start and AjaxUI:reload events. - * - ***********************************/ - -// Add bootstrap treeview on divs with data-tree-data attribute -$(document).on("ajaxUI:start ajaxUI:reload", function() { - $("[data-tree-data]").each(function(index, element) { - let data = $(element).data('treeData'); - - //@ts-ignore - $(element).treeview({ - data: data, - enableLinks: false, - showIcon: false, - showBorder: true, - searchResultBackColor: '#ffc107', - searchResultColor: '#000', - showTags: true, - //@ts-ignore - wrapNode: true, - //@ts-ignore - tagsClass: 'badge badge-secondary badge-pill pull-right', - expandIcon: "fas fa-plus fa-fw fa-treeview", collapseIcon: "fas fa-minus fa-fw fa-treeview", - onNodeSelected: function(event, data) { - if(data.href) { - ajaxUI.navigateTo(data.href); - } - } - }).on('initialized', function() { - $(this).treeview('collapseAll', { silent: true }); - let selected = $(this).treeview('getSelected'); - $(this).treeview('revealNode', [ selected, {silent: true } ]); - - //Implement searching if needed. - if($(this).data('treeSearch')) { - let _this = this; - let $search = $($(this).data('treeSearch')); - $search.on( 'input', function() { - $(_this).treeview('collapseAll', { silent: true }); - $(_this).treeview('search', [$search.val()]); - }); - } - - //Add tree expand and reduce buttons if needed. - if($(this).data('treeReduce')) { - let _this = this; - let $btn = $($(this).data('treeReduce')); - $btn.click(function () { - $(_this).treeview('collapseAll'); - }); - } - if($(this).data('treeExpand')) { - let _this = this; - let $btn = $($(this).data('treeExpand')); - $btn.click(function () { - $(_this).treeview('expandAll'); - }); - } - }); - - }); -}); - -$(document).on("ajaxUI:start ajaxUI:reload", function() { - $("[data-delete-form]").unbind('submit').submit(function (event) { - event.preventDefault(); - - let form = this; - - //Get the submit button - let btn = document.activeElement; - - let title = $(this).data("title"); - let message = $(this).data("message"); - - bootbox.confirm({ - message: message, title: title, callback: function (result) { - //If the dialog was confirmed, then submit the form. - if (result) { - ajaxUI.submitForm(form, btn); - } - } - }); - - return false; - }); - - //Register for forms with delete-buttons - $("[data-delete-btn]").parents('form').unbind('submit').submit(function (event) { - event.preventDefault(); - let form = this; - //Get the submit button - let btn = document.activeElement; - - let title = $(btn).data("title"); - let message = $(btn).data("message"); - - //If not the button with the message was pressed, then simply submit the form. - if(!btn.hasAttribute('data-delete-btn')) { - ajaxUI.submitForm(form, btn); - } - - bootbox.confirm({ - message: message, title: title, callback: function (result) { - //If the dialog was confirmed, then submit the form. - if (result) { - ajaxUI.submitForm(form, btn); - } - } - }); - - }); - -}); - -$(document).on("ajaxUI:start ajaxUI:reload", function() { - //@ts-ignore - $(".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); - }); -}); - -//Re initialize fileinputs on reload -$(document).on("ajaxUI:reload", function () { - //@ts-ignore - $(".file").fileinput(); -}); - - -/** - * 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. - */ -$(document).on("ajaxUI:reload ajaxUI:start", function () { - //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; - }); -}); - -/** - * Load the higher resolution version of hover pictures. - */ -$(document).on("ajaxUI:reload ajaxUI:start ajaxUI:dt_loaded", function () { - - $('.hoverpic[data-thumbnail]').popover({ - html: true, - trigger: 'hover', - placement: 'right', - container: 'body', - content: function () { - return '<img class="img-fluid" src="' + $(this).data('thumbnail') + '" />'; - } - }); -}); - - -//Register typeaheads -$(document).on("ajaxUI:reload ajaxUI:start attachment:create", function () { - $('input[data-autocomplete]').each(function() { - //@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).typeahead({ - hint: true, - highlight: true, - minLength: 1 - }, - { - name: 'states', - source: engine, - limit: 250, - templates: { - suggestion: function(data) { - if (typeof data === "string") { - return "<div>" + data + "</div>"; - } else if(typeof data === "object" && typeof data.image === "string") { - return "<div class='row m-0'><div class='col-2 pl-0 pr-1'><img class='typeahead-image' src='" + data.image + "'/></div><div class='col-10'>" + data.name + "</div></div>" - } - }, - }, - display: 'name', - }); - - //Make the typeahead input fill the container (remove block-inline attr) - $(this).parent(".twitter-typeahead").css('display', 'block'); - }) -}); - - -$(document).on("ajaxUI:start ajaxUI:reload attachment:create", function() { - let updater = function() { - //@ts-ignore - let selected_option = $(this)[0].selectedOptions[0]; - let filter_string = $(selected_option).data('filetype_filter'); - //Find associated file input - - let $row = $(this).parents('tr'); - //Set accept filter - $('input[type="file"]', $row).prop('accept', filter_string); - }; - - //Register a change handler on all change listeners, and update it when the events are triggered - $('select.attachment_type_selector').change(updater).each(updater); -}); - - -$(document).on("ajaxUI:start ajaxUI:reload", function() { - function setTooltip(btn, message) { - $(btn).tooltip('hide') - .attr('data-original-title', message) - .tooltip('show'); - } - - function hideTooltip(btn) { - setTimeout(function() { - $(btn).tooltip('hide'); - }, 1000); - } - - //@ts-ignore - var clipboard = new ClipboardJS('.btn[data-clipboard-target], .btn[data-clipboard-text], .btn[data-clipboard-action]'); - clipboard.on('success', function(e) { - setTooltip(e.trigger, 'Copied!'); - hideTooltip(e.trigger); - }); - - clipboard.on('error', function(e) { - setTooltip(e.trigger, 'Failed!'); - hideTooltip(e.trigger); - }); -}); - -//Register U2F on page reload too... -$(document).on("ajaxUI:reload", function() { - //@ts-ignore - window.u2fauth.ready(function () { - const form = document.getElementById('u2fForm') - if (!form) { - return - } - const type = form.dataset.action - - if (type === 'auth') { - //@ts-ignore - u2fauth.authenticate() - } else if (type === 'reg' && form.addEventListener) { - form.addEventListener('submit', function (event) { - event.preventDefault() - //@ts-ignore - u2fauth.register() - }, false) - } - }) -}); - -//Need for proper body padding, with every navbar height -$(window).resize(function () { - let height : number = $('#navbar').height() + 10; - $('body').css('padding-top', height); - $('#fixed-sidebar').css('top', height); -}); - -$(window).on('load', function () { - let height : number = $('#navbar').height() + 10; - $('body').css('padding-top', height); - $('#fixed-sidebar').css('top', height); -}); \ No newline at end of file