in pontoon/base/static/js/main.js [143:453]
$(function () {
/*
* If Google Analytics is enabled, the translate frontend will send additional about Ajax calls.
*
* To send an event to GA, We pass following informations:
* event category - hardcoded 'ajax' string.
* event action - hardcoded 'request' string.
* event label - contains url that was called by $.ajax() call.
*
* GA Analytics enriches every event with additional information like e.g. browser, resolution, country etc.
*/
$(document).ajaxComplete(function (event, jqXHR, settings) {
if (typeof ga !== 'function') {
return;
}
ga('send', 'event', 'ajax', 'request', settings.url);
});
/*
* Display Pontoon Add-On Promotion, if:
*
* - Promotion not dismissed
* - Add-On not installed
* - Page loaded on Firefox or Chrome (add-on not available for other browsers)
*/
setTimeout(function () {
const dismissed = !$('#addon-promotion').length;
const installed = window.PontoonAddon && window.PontoonAddon.installed;
if (!dismissed && !installed) {
const isFirefox = navigator.userAgent.indexOf('Firefox') !== -1;
const isChrome = navigator.userAgent.indexOf('Chrome') !== -1;
let downloadHref = '';
if (isFirefox) {
downloadHref =
'https://addons.mozilla.org/firefox/addon/pontoon-tools/';
}
if (isChrome) {
downloadHref =
'https://chrome.google.com/webstore/detail/pontoon-add-on/gnbfbnpjncpghhjmmhklfhcglbopagbb';
}
if (downloadHref) {
$('#addon-promotion').find('.get').attr('href', downloadHref);
$('body').addClass('addon-promotion-active');
}
}
// window.PontoonAddon is made available by the Pontoon Add-On,
// but not immediatelly after the DOM is ready
}, 1000);
// Dismiss Add-On Promotion
$('#addon-promotion .dismiss').click(function () {
Pontoon.NProgressUnbind();
$.ajax({
url: '/dismiss-addon-promotion/',
success: function () {
$('body').removeClass('addon-promotion-active');
},
});
Pontoon.NProgressBind();
});
// Hide Add-On Promotion if Add-On installed while active
window.addEventListener('message', (event) => {
// only allow messages from authorized senders (extension content script, or Pontoon itself)
if (event.origin !== window.origin || event.source !== window) {
return;
}
let data;
switch (typeof event.data) {
case 'object':
data = event.data;
break;
case 'string':
// backward compatibility
// TODO: remove some reasonable time after https://github.com/MikkCZ/pontoon-addon/pull/155 is released
// and convert this switch into a condition
try {
data = JSON.parse(event.data);
} catch {
return;
}
break;
}
if (data && data._type === 'PontoonAddonInfo' && data.value) {
if (data.value.installed === true) {
$('body').removeClass('addon-promotion-active');
}
}
});
Pontoon.NProgressBind();
// Log display of the unread notification icon
if ($('#notifications').is('.unread')) {
Pontoon.logUxAction(
'Render: Unread notifications icon',
'Notifications 1.0',
{
pathname: window.location.pathname,
},
);
}
// Initialize the timeago plugin on the notifications
$('time.timeago').timeago();
// Log clicks on the notifications icon
$('#notifications .button').click(function () {
if ($('#notifications').is('.opened')) {
return;
}
Pontoon.logUxAction('Click: Notifications icon', 'Notifications 1.0', {
pathname: window.location.pathname,
unread: $('#notifications').is('.unread'),
});
});
// Display any notifications
const notifications = $('.notification li');
if (notifications.length) {
Pontoon.endLoader(notifications.text());
}
// Close notification on click
$('body > header').on('click', '.notification', function () {
Pontoon.closeNotification();
});
// Mark notifications as read when notification menu opens
$('#notifications.unread .button').click(function () {
Pontoon.markAllNotificationsAsRead();
});
function getRedirectUrl() {
return window.location.pathname + window.location.search;
}
// Sign out button action
$('.sign-out a, #sign-out a').on('click', function (ev) {
const $this = $(this),
$form = $this.find('form');
ev.preventDefault();
$form.prop('action', $this.prop('href') + '?next=' + getRedirectUrl());
$form.submit();
});
// Show/hide menu on click
$('body').on('click', '.selector', function (e) {
if (!$(this).siblings('.menu').is(':visible')) {
e.stopPropagation();
$('.menu:not(".permanent")').hide();
$('.select').removeClass('opened');
$(this)
.siblings('.menu')
.show()
.end()
.parents('.select')
.addClass('opened');
$('.menu:not(".permanent"):visible input[type=search]')
.focus()
.trigger('input');
}
});
// Hide menus on click outside
$('body').bind('click.main', function () {
$('.menu:not(".permanent")').hide();
$('.select').removeClass('opened');
$('.menu:not(".permanent") li').removeClass('hover');
});
// Menu hover
$('body')
.on('mouseenter', '.menu li', function () {
// Ignore on nested menus
if ($(this).parents('li').length) {
return false;
}
$('.menu li.hover').removeClass('hover');
$(this).toggleClass('hover');
})
.on('mouseleave', '.menu li', function () {
// Ignore on nested menus
if ($(this).parents('li').length) {
return false;
}
$('.menu li.hover').removeClass('hover');
});
// Menu search
$('body')
.on('click', '.menu input[type=search]', function (e) {
e.stopPropagation();
})
.on('input.search', '.menu input[type=search]', function (e) {
// Tab
if (e.which === 9) {
return;
}
const ul = $(this).parent().siblings('ul'),
val = $(this).val(),
// Only search a limited set if defined
limited = ul.find('li.limited').length > 0 ? '.limited' : '';
ul.find('li' + limited)
.show()
.end()
.find('li' + limited + ':not(":containsi(\'' + val + '\')")')
.hide();
if (ul.find('li:not(".no-match"):visible').length === 0) {
ul.find('.no-match').show();
} else {
ul.find('.no-match').hide();
}
})
.on('keydown.search', '.menu input[type=search]', function (e) {
// Prevent form submission on Enter
if (e.which === 13) {
return false;
}
});
// General keyboard shortcuts
generalShortcutsHandler = function (e) {
const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
function moveMenu(type) {
const options =
type === 'up' ? ['first', 'last', -1] : ['last', 'first', 1];
const items = menu.find(
'li:visible:not(.horizontal-separator, :has(li))',
);
let element = null;
if (
hovered.length === 0 ||
menu.find('li:not(:has(li)):visible:' + options[0]).is('.hover')
) {
menu.find('li.hover').removeClass('hover');
element = items[options[1]]();
} else {
const current = menu.find('li.hover'),
next = items.index(current) + options[2];
current.removeClass('hover');
element = $(items.get(next));
}
if (element) {
const behavior = mediaQuery.matches ? 'auto' : 'smooth';
element.addClass('hover');
element[0].scrollIntoView({
behavior: behavior,
block: 'nearest',
});
}
}
const key = e.which;
if ($('.menu:not(".permanent")').is(':visible')) {
// eslint-disable-next-line no-var
var menu = $('.menu:not(".permanent"):visible'),
hovered = menu.find('li.hover');
// Skip for the tabs
if (menu.is('.tabs')) {
return;
}
// Up arrow
if (key === 38) {
moveMenu('up');
return false;
}
// Down arrow
if (key === 40) {
moveMenu('down');
return false;
}
// Enter: confirm
if (key === 13) {
const a = hovered.find('a');
if (a.length > 0) {
a.click();
} else {
hovered.click();
}
return false;
}
// Escape: close
if (key === 27) {
$('body').click();
return false;
}
}
};
$('html').on('keydown', generalShortcutsHandler);
});