// turbolinks MUST BE THE LAST inclusion //= require hammer //= require js.cookie //= require bootstrap-sprockets //= require moment //= require bootstrap-datetimepicker //= require bootstrap-colorselector //= require bootstrap-tagsinput.min //= require bootstrap-checkbox.min //= require typeahead.bundle.min //= require nested_form_fields //= require jsPlumb-2.0.4-min //= require jsnetworkx //= require bootstrap-select //= require_directory ./repository_columns/columns_initializers //= require datatables //= require clndr.min //= require ajax-bootstrap-select.min //= require underscore //= require i18n.js //= require i18n/translations //= require users/settings/teams/invite_users_modal //= require repository_columns/index //= require perfect-scrollbar.min //= require shared/inline_editing //= require shared/barcode_search //= require activestorage //= require global_activities/side_pane //= require protocols/header //= require protocols/print //= require marvinjslauncher //= require jstree.min //= require_tree ./repositories/renderers //= require_directory ./shared //= require_directory ./repositories/validators //= require_directory ./dashboard //= require_directory ./sitewide //= require_directory ./access_permissions //= require sidebar //= require turbolinks // Initialize links for submitting forms. This is useful for submitting // forms with clicking on links outside form in cases when other than // GET method is used. function initFormSubmitLinks(el) { el = el || $(document.body); $(".form-submit-link", el).click(function () { var val = true; if ($(this).is("[data-confirm-form]")) { val = confirm($(this).data("confirm-form")); } // Only submit form if confirmed if (val) { animateLoading(); $("#" + $(this).data("submit-form")).submit(); } }); } /* Enable loading bars */ $(document) .bind("ajaxSend", function(){ animateLoading(); }) .bind("ajaxComplete", function(){ animateLoading(false); }); /* * Show/hide loading indicator on top of page. */ function animateLoading(start){ if (start === undefined) start = true; start = start !== false; if (start) { $("#loading-animation").addClass("animate"); } else { $("#loading-animation").removeClass("animate"); } } /* * Show/hide spinner for a given element. * Shows spinner if start is true or not given, hides it if false. * Optional parameter options for spin.js options. */ function animateSpinner(el, start) { // If overlaying the whole page, put the spinner in the middle of the page var overlayPage = _.isUndefined(el) || el === null; if (_.isUndefined(start)) start = true; if (start) { if (overlayPage) { $(document.body).append('
'); } else { $(el).append('
'); } } else { $(".loading-overlay").remove(); } } /** * Automatic handling of show/hide spinner. * @param {boolean} redirection Whether page is refreshed/redirected on success * @param {boolean} onElement Whether spinner is fixed on the center of fn * element or it's positions on the center of whole page */ $.fn.animateSpinner = function(redirection, onElement) { redirection = _.isUndefined(redirection) ? false : redirection; onElement = _.isUndefined(onElement) ? false : onElement; $(this) .on('ajax:beforeSend', function() { onElement ? animateSpinner($(this)) : animateSpinner(); }) .on('ajax:error', function(e, data) { animateSpinner(null, false); }) .on('ajax:success', function(e, data) { if (!redirection) { animateSpinner(null, false); } }); } /* * Prevents user from accidentally leaving page when server is busy * and notifies him with a message. * * NOTE: Don't prevent event propagation (ev.stopPropagation()), or * else all events occurring when alert is up will be ignored. */ function preventLeavingPage(prevent, msg) { busy = prevent; if (busy && !_.isUndefined(msg)) { busyMsg = msg; } } var busy = false; var busyMsg = I18n.t("general.busy"); window.onbeforeunload = function () { if (busy) { var currentMsg = busyMsg; // Reset to default message busyMsg = I18n.t("general.busy"); return currentMsg; } } /* * Disable Firefox caching to get rid of issues with pressing * browser back, like opening canvas in edit mode. */ $(window).unload(function () { $(window).unbind('unload'); }); var HelperModule = (function(){ var helpers = {}; helpers.hideFlashMsg = function() { var flash = $('.alert'); if (flash.length > 0) { window.setTimeout(function () { flash.fadeTo(500, 0).slideUp(500, function () { $(this).remove(); }); }, 3000); } } helpers.dismissAlert = function() { $('#alert-flash').on('click', function() { $('#alert-flash').alert('close'); }) } helpers.flashAlertMsg = function(message, type) { var alertType, fasSign; $('#notifications').html(''); if (type === 'success') { alertType = ' alert-success '; fasSign = ' fa-check-circle '; } else if (type === 'danger') { alertType = ' alert-danger '; fasSign = ' fa-exclamation-triangle '; } else if (type === 'info') { alertType = ' alert-info '; fasSign = ' fa-info-circle '; } else if (type === 'warning') { alertType = ' alert-warning '; fasSign = ' fa-exclamation-triangle '; } var htmlSnippet = '
' + ' ' + '' + message + '' + '' + '
'; $('#notifications').html(htmlSnippet); helpers.hideFlashMsg(); helpers.dismissAlert(); } $(document).on('turbolinks:load', function() { helpers.hideFlashMsg(); helpers.dismissAlert(); }); return helpers; })(); (function() { $(document).on('turbolinks:load', function() { // fix dropdown-menu style throughout the app $('.dropdown-header').parent('ul').addClass('custom-dropdown-menu'); }); // Close all open modals before caching $(document).on('turbolinks:before-cache', function() { $('.modal').off().modal('hide'); }); $(document).on('turbolinks:load', function() { /* Fix .selectpicker (bootstrap-select) to work with Turbolinks 5.x */ $(window).trigger('load.bs.select.data-api'); }); // Show warning if page has unsaved data $(document).on('turbolinks:before-visit', () => { let exit = true; let editing = $(`.${GLOBAL_CONSTANTS.HAS_UNSAVED_DATA_CLASS_NAME}`).length > 0; if (editing) { exit = confirm(I18n.t('general.leaving_unsaved_warning')); } return exit; }); const RESIZE_OBSERVER = new ResizeObserver(function(entries) { entries.forEach((entry) => { if (entry.target.offsetWidth <= parseInt(entry.target.getAttribute('data-width-breakpoint'))) { entry.target.classList.add('narrow'); } else { entry.target.classList.remove('narrow'); } }); }); $(document).on('turbolinks:load', function() { $('[data-width-breakpoint]').each(function() { RESIZE_OBSERVER.observe(this); }); }); }()); // Check that loaded page, not turbolinks preview function notTurbolinksPreview() { return !document.documentElement.hasAttribute("data-turbolinks-preview"); } const windowScrollEvents = {}; $(window).scroll(function() { $.each(windowScrollEvents, function(key, scroll_function){ scroll_function(); }) }) // Disable default validation bubbles // NOTE: invalid event doesn't bubble, that's // why need to bind to each element separately $(document).ajaxComplete(function() { setTimeout(function() { $('input,select,textarea').each(function() { $(this).on('invalid', function(e) { e.preventDefault(); return false; }); }); }, 10); }); // enable form validations on form submit $(document).on('ajax:beforeSend', 'form', function() { $(this).removeAttr('novalidate'); return this.reportValidity(); }); $(document).keyup(function(e) { if (e.keyCode == 27) { $('.dropdown').removeClass('open'); $('.atwho-user-popover').popover("hide"); $('.modal').modal("hide"); } }); window.I18n = I18n; // Multiple modal support // https://stackoverflow.com/a/24914782 $(document).on('shown.bs.modal', '.modal', function() { const zIndex = 2040 + 10 * $('.modal:visible').length; $(this).css('z-index', zIndex); setTimeout(() => $('.modal-backdrop').not('.modal-stack').css('z-index', zIndex - 1).addClass('modal-stack')); }); // User Name popover sitewide support let userNamePopover; const renderUserNamePopover = (url, fullName, email, html) => { return `
thumb
${fullName}

${html}

`; }; $(document).on('focus', '.atwho-user-popover', function() { if (!userNamePopover) { const atwhoUserName = $(this); const url = atwhoUserName.data('user-avatar-popover-absolute-url'); const fullName = atwhoUserName.data('full-name'); const email = atwhoUserName.data('email'); const html = atwhoUserName.data('popover-html'); atwhoUserName.attr('data-content', renderUserNamePopover(url, fullName, email, html)); } $(this).popover('show'); }).on('blur', '.atwho-user-popover', function() { $(this).popover('hide'); });