Compare commits

...

27 commits

Author SHA1 Message Date
Matt Friedman
e53683cd21
Merge b82d7d3f47 into bc470285fc 2025-06-15 00:05:55 -07:00
Marc Alexander
bc470285fc
Merge pull request #6770 from rxu/ticket/15214
[ticket/15214] Add event & functionality for assigning template event priority
2025-06-15 08:59:31 +02:00
rxu
1d7543c778
[ticket/15214] Address code review issues, add equal priority events test
PHPBB3-15214
2025-06-15 01:35:31 +07:00
Matt Friedman
b82d7d3f47
[ticket/17517] Revert back to var
PHPBB-17517
2025-06-01 09:45:57 -07:00
Matt Friedman
5553e7ae19
[ticket/17517] Clean up
PHPBB-17517
2025-06-01 08:30:11 -07:00
Matt Friedman
7d50f40dde
[ticket/17517] Remove global ignore of extension’s JS files
PHPBB-17517
2025-06-01 07:12:57 -07:00
Matt Friedman
2daabd34be
[ticket/17517] Refactor eslint config, remove unused rules
PHPBB-17517
2025-05-31 13:26:44 -07:00
Matt Friedman
35a1af5a11
[ticket/17517] Fix handling of twig JS files too
PHPBB-17517
2025-05-31 11:28:03 -07:00
Matt Friedman
216b71df9a
[ticket/17517] Update to latest eslint
PHPBB-17517
2025-05-31 11:15:04 -07:00
Matt Friedman
1210c5a03d
[ticket/17517] Update ESLINT to 8.57.1
PHPBB-17517
2025-05-31 10:16:39 -07:00
Matt Friedman
1c0f1ed3da
[ticket/17517] Eslint all phpbb JS files
PHPBB-17517
2025-05-31 10:13:10 -07:00
rxu
ccbdfb49c7
[ticket/15214] Adjust core event name and docblock
PHPBB3-15214
2025-05-21 11:25:35 +07:00
rxu
43cf7b73bd
[ticket/15214] Adjust event node logic
PHPBB3-15214
2025-05-21 10:47:27 +07:00
rxu
3a5247d01b
[ticket/15214] Get event dispatcher from environment rather than as dependency
Also this will allow to significantly reduce unrelated tests changes.

PHPBB3-15214
2025-05-20 17:36:15 +07:00
rxu
5e0dc9ef2e
[ticket/15214] Fix rebasing and some other issues
PHPBB3-15214
2025-05-20 16:24:38 +07:00
rxu
8338ff9e56
[ticket/15214] Fix Windows tests
PHPBB3-15214
2025-05-20 16:24:37 +07:00
toxyy
84e7e34a66
[ticket/15214] Fix tests again
Adding per rxu's recommendation

PHPBB3-15214
2025-05-20 16:24:37 +07:00
rxu
18bae795f0
[ticket/15214] Fix Windows tests
Purge Twig compiled cache in Windows.
Set appropriate folder access control options to do that.

PHPBB3-15214
2025-05-20 16:24:36 +07:00
rxu
09fd86ffb0
[ticket/15214] Fix test foo/foo extension listener
PHPBB3-15214
2025-05-20 16:24:34 +07:00
rxu
4a00212f2d
[ticket/15214] Optimize event node code and add template event order tests
PHPBB3-15214
2025-05-20 16:24:34 +07:00
toxyy
cb47d78d26
[ticket/15214] Update block, restart tests
Make docblock look a bit cleaner and restart the tests

PHPBB3-15214
2025-05-20 16:24:33 +07:00
toxyy
0eb98d51e2
[ticket/15214] Provide usage example within event docblock
Adds similar usage examples like the event core.permissions has

PHPBB3-15214
2025-05-20 16:24:32 +07:00
toxyy
82a5e20f3e
[ticket/15214] Replace arrow functions with anonymous functions
Arrow functions aren't added until PHP 7.4, so we can't use them yet.
Anonymous functions have been added since PHP 5.3

PHPBB3-15214
2025-05-20 16:24:32 +07:00
toxyy
71fe9d60c4
[ticket/15214] Add fixes for various other tests
Add new dispatch parameter to the template\twig\extension calls

PHPBB3-15214
2025-05-20 16:24:31 +07:00
toxyy
59b482a222
[ticket/15214] Test fix for test_bbcode_firstpass
Add new dispatch parameter to the template\twig\extension call

PHPBB3-15214
2025-05-20 16:24:30 +07:00
toxyy
d934c8c4b7
[ticket/15214] Test fix for test_helper_url_no_rewrite
Add new dispatch parameter to the template\twig\extension call

PHPBB3-15214
2025-05-20 16:24:29 +07:00
toxyy
d07aeb00d8
[ticket/15214] Add event & functionality for assigning template event priority
Event added to allow template events to be assigned priority per extension,
event location chosen so that it only fires once.
Twig node event class refactored to allow template event priority assignment,
compile calls are deferred until all locations are processed
per extension namespace.
Priority precedence mirrors Symfony priority, with higher numbers
being placed at the beginning of the array.
Duplicate priority assignment will currently have the later events
compiled before the others.

PHPBB3-15214
2025-05-20 16:24:24 +07:00
34 changed files with 5141 additions and 4280 deletions

4
.github/check-js.sh vendored
View file

@ -14,6 +14,6 @@ set +x
sudo npm install -g > /dev/null sudo npm install -g > /dev/null
npm ci > /dev/null npm ci > /dev/null
set -x set -x
node_modules/eslint/bin/eslint.js "phpBB/**/*.js" node_modules/eslint/bin/eslint.js "phpBB/**/*.js" --ignore-pattern "phpBB/ext/"
node_modules/eslint/bin/eslint.js "phpBB/**/*.js.twig" node_modules/eslint/bin/eslint.js "phpBB/**/*.js.twig" --ignore-pattern "phpBB/ext/"
node_modules/eslint/bin/eslint.js "gulpfile.js" node_modules/eslint/bin/eslint.js "gulpfile.js"

67
eslint.config.mjs Normal file
View file

@ -0,0 +1,67 @@
const { browser: browserGlobals, node: nodeGlobals, jquery: jqueryGlobals } = (await import('globals')).default;
// File patterns to ignore
const IGNORED_FILES = [
'phpBB/assets/javascript/cropper.js',
'phpBB/assets/javascript/hermite.js',
'phpBB/assets/javascript/jquery-cropper.js',
'phpBB/**/*.min.js',
'phpBB/vendor/**/*.js',
'phpBB/vendor-ext/**/*.js',
'phpBB/phpbb/**/*.js',
'phpBB/tests/**/*.js',
];
// ESLint rule configurations
const FORMATTING_RULES = {
'quotes': ['error', 'single'],
'comma-dangle': ['error', 'always-multiline'],
'block-spacing': 'error',
'array-bracket-spacing': ['error', 'always'],
'object-curly-spacing': ['error', 'always'],
'space-before-function-paren': ['error', 'never'],
'space-in-parens': 'off',
};
const CODE_QUALITY_RULES = {
'semi': ['error', 'always'],
'eqeqeq': ['error', 'always'],
'curly': ['error', 'multi-line'],
'no-var': 'error',
'prefer-const': 'error',
'no-console': 'off',
'no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
};
const DISABLED_STYLE_RULES = {
'multiline-comment-style': 'off',
'computed-property-spacing': 'off',
'capitalized-comments': 'off',
'no-lonely-if': 'off',
};
const mainConfig = {
files: ['**/*.js', '**/*.js.twig'],
linterOptions: {
reportUnusedDisableDirectives: false,
},
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
globals: {
...browserGlobals,
...nodeGlobals,
...jqueryGlobals,
},
},
rules: {
...FORMATTING_RULES,
...CODE_QUALITY_RULES,
...DISABLED_STYLE_RULES,
},
};
export default [
{ ignores: IGNORED_FILES },
mainConfig,
];

1780
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -6,65 +6,6 @@
"directories": { "directories": {
"doc": "docs" "doc": "docs"
}, },
"eslintConfig": {
"extends": "xo",
"ignorePatterns": [
"phpBB/adm/style/admin.js",
"phpBB/adm/style/ajax.js",
"phpBB/adm/style/permissions.js",
"phpBB/adm/style/tooltip.js",
"phpBB/assets/javascript/core.js",
"phpBB/assets/javascript/cropper.js",
"phpBB/assets/javascript/editor.js",
"phpBB/assets/javascript/hermite.js",
"phpBB/assets/javascript/installer.js",
"phpBB/assets/javascript/jquery-cropper.js",
"phpBB/assets/javascript/plupload.js",
"phpBB/ext/**/*.js",
"phpBB/styles/prosilver/template/ajax.js",
"phpBB/styles/prosilver/template/forum_fn.js",
"phpBB/**/*.min.js",
"phpBB/vendor/**/*.js",
"phpBB/vendor-ext/**/*.js",
"phpBB/phpbb/**/*.js",
"phpBB/tests/**/*.js"
],
"rules": {
"quotes": [
"error",
"single"
],
"comma-dangle": [
"error",
"always-multiline"
],
"block-spacing": "error",
"array-bracket-spacing": [
"error",
"always"
],
"multiline-comment-style": "off",
"computed-property-spacing": "off",
"space-before-function-paren": [
"error",
"never"
],
"space-in-parens": "off",
"capitalized-comments": "off",
"object-curly-spacing": [
"error",
"always"
],
"no-lonely-if": "off",
"unicorn/prefer-module": "off"
},
"env": {
"es6": true,
"browser": true,
"node": true,
"jquery": true
}
},
"browserslist": [ "browserslist": [
"> 1%", "> 1%",
"not ie 11", "not ie 11",
@ -101,8 +42,8 @@
"devDependencies": { "devDependencies": {
"autoprefixer": "^10.4.4", "autoprefixer": "^10.4.4",
"cssnano": "^5.1.7", "cssnano": "^5.1.7",
"eslint": "^8.13.0", "eslint": "^9.28.0",
"eslint-config-xo": "^0.40.0", "globals": "^16.2.0",
"gulp": "^5.0.0", "gulp": "^5.0.0",
"gulp-concat": "^2.6.1", "gulp-concat": "^2.6.1",
"gulp-postcss": "^9.0.1", "gulp-postcss": "^9.0.1",

View file

@ -1,4 +1,5 @@
/* global phpbb */ /* global phpbb */
/* eslint no-var: 0 */
/** /**
* phpBB ACP functions * phpBB ACP functions
@ -7,19 +8,16 @@
/** /**
* Parse document block * Parse document block
*/ */
function parse_document(container) function parseDocument(container) {
{ var test = document.createElement('div');
var test = document.createElement('div'),
oldBrowser = (typeof test.style.borderRadius == 'undefined');
test.remove(); test.remove();
/** /**
* Navigation * Navigation
*/ */
container.find('#menu').each(function() { container.find('#menu').each(function() {
var menu = $(this), var menu = $(this);
blocks = menu.children('.menu-block'); var blocks = menu.children('.menu-block');
if (!blocks.length) { if (!blocks.length) {
return; return;
@ -31,6 +29,7 @@ function parse_document(container)
if (!parent.hasClass('active')) { if (!parent.hasClass('active')) {
parent.siblings().removeClass('active'); parent.siblings().removeClass('active');
} }
parent.toggleClass('active'); parent.toggleClass('active');
}); });
@ -47,12 +46,11 @@ function parse_document(container)
* Responsive tables * Responsive tables
*/ */
container.find('table').not('.not-responsive').each(function() { container.find('table').not('.not-responsive').each(function() {
var $this = $(this), var $this = $(this);
th = $this.find('thead > tr > th'), var th = $this.find('thead > tr > th');
columns = th.length, var headers = [];
headers = [], var totalHeaders = 0;
totalHeaders = 0, var i;
i, headersLength;
// Find columns // Find columns
$this.find('colgroup:first').children().each(function(i) { $this.find('colgroup:first').children().each(function(i) {
@ -71,21 +69,24 @@ function parse_document(container)
} }
// Find each header // Find each header
if (!$this.data('no-responsive-header')) if (!$this.data('no-responsive-header')) {
{
th.each(function(column) { th.each(function(column) {
var cell = $(this), var cell = $(this);
colspan = parseInt(cell.attr('colspan')), var colspan = parseInt(cell.attr('colspan'), 10);
dfn = cell.attr('data-dfn'), var dfn = cell.attr('data-dfn');
text = dfn ? dfn : $.trim(cell.text()); var text = dfn ? dfn : $.trim(cell.text());
if (text === ' ') {
text = '';
}
if (text == ' ') text = '';
colspan = isNaN(colspan) || colspan < 1 ? 1 : colspan; colspan = isNaN(colspan) || colspan < 1 ? 1 : colspan;
for (i=0; i<colspan; i++) { for (i = 0; i < colspan; i++) {
headers.push(text); headers.push(text);
} }
totalHeaders ++;
totalHeaders++;
if (dfn && !column) { if (dfn && !column) {
$this.addClass('show-header'); $this.addClass('show-header');
@ -104,19 +105,19 @@ function parse_document(container)
} }
$this.find('tbody > tr').each(function() { $this.find('tbody > tr').each(function() {
var row = $(this), var row = $(this);
cells = row.children('td'), var cells = row.children('td');
column = 0; var column = 0;
if (cells.length == 1) { if (cells.length === 1) {
row.addClass('big-column'); row.addClass('big-column');
return; return;
} }
cells.each(function() { cells.each(function() {
var cell = $(this), var cell = $(this);
colspan = parseInt(cell.attr('colspan')), var colspan = parseInt(cell.attr('colspan'), 10);
text = $.trim(cell.text()); var text = $.trim(cell.text());
if (headersLength <= column) { if (headersLength <= column) {
return; return;
@ -124,10 +125,9 @@ function parse_document(container)
if ((text.length && text !== '-') || cell.children().length) { if ((text.length && text !== '-') || cell.children().length) {
if (headers[column].length) { if (headers[column].length) {
cell.prepend($("<dfn>").css('display', 'none').text(headers[column])); cell.prepend($('<dfn>').css('display', 'none').text(headers[column]));
} }
} } else {
else {
cell.addClass('empty'); cell.addClass('empty');
} }
@ -145,8 +145,7 @@ function parse_document(container)
*/ */
container.find('table.responsive > tbody').each(function() { container.find('table.responsive > tbody').each(function() {
var items = $(this).children('tr'); var items = $(this).children('tr');
if (!items.length) if (!items.length) {
{
$(this).parent('table:first').addClass('responsive-hide'); $(this).parent('table:first').addClass('responsive-hide');
} }
}); });
@ -156,7 +155,7 @@ function parse_document(container)
*/ */
container.find('fieldset dt > span:last-child').each(function() { container.find('fieldset dt > span:last-child').each(function() {
var $this = $(this); var $this = $(this);
if ($this.html() == '&nbsp;') { if ($this.html() === '&nbsp;') {
$this.addClass('responsive-hide'); $this.addClass('responsive-hide');
} }
}); });
@ -180,25 +179,25 @@ function parse_document(container)
* Responsive tabs * Responsive tabs
*/ */
container.find('#tabs').not('[data-skip-responsive]').each(function() { container.find('#tabs').not('[data-skip-responsive]').each(function() {
var $this = $(this), var $this = $(this);
$body = $('body'), var $body = $('body');
ul = $this.children(), var ul = $this.children();
tabs = ul.children().not('[data-skip-responsive]'), var tabs = ul.children().not('[data-skip-responsive]');
links = tabs.children('a'), var links = tabs.children('a');
item = ul.append('<li class="tab responsive-tab" style="display:none;"><a href="javascript:void(0);" class="responsive-tab-link">&nbsp;</a><div class="dropdown tab-dropdown" style="display: none;"><div class="pointer"><div class="pointer-inner"></div></div><ul class="dropdown-contents" /></div></li>').find('li.responsive-tab'), var item = ul.append('<li class="tab responsive-tab" style="display:none;"><a href="javascript:void(0);" class="responsive-tab-link">&nbsp;</a><div class="dropdown tab-dropdown" style="display: none;"><div class="pointer"><div class="pointer-inner"></div></div><ul class="dropdown-contents" /></div></li>').find('li.responsive-tab');
menu = item.find('.dropdown-contents'), var menu = item.find('.dropdown-contents');
maxHeight = 0, var maxHeight = 0;
lastWidth = false, var lastWidth = false;
responsive = false; var responsive = false;
links.each(function() { links.each(function() {
var link = $(this); var link = $(this);
maxHeight = Math.max(maxHeight, Math.max(link.outerHeight(true), link.parent().outerHeight(true))); maxHeight = Math.max(maxHeight, Math.max(link.outerHeight(true), link.parent().outerHeight(true)));
}) });
function check() { function check() {
var width = $body.width(), var width = $body.width();
height = $this.height(); var height = $this.height();
if (!arguments.length && (!responsive || width <= lastWidth) && height <= maxHeight) { if (!arguments.length && (!responsive || width <= lastWidth) && height <= maxHeight) {
return; return;
@ -214,6 +213,7 @@ function parse_document(container)
if (item.hasClass('dropdown-visible')) { if (item.hasClass('dropdown-visible')) {
phpbb.toggleDropdown.call(item.find('a.responsive-tab-link').get(0)); phpbb.toggleDropdown.call(item.find('a.responsive-tab-link').get(0));
} }
return; return;
} }
@ -221,23 +221,29 @@ function parse_document(container)
item.show(); item.show();
menu.html(''); menu.html('');
var availableTabs = tabs.filter(':not(.activetab, .responsive-tab)'), var availableTabs = tabs.filter(':not(.activetab, .responsive-tab)');
total = availableTabs.length, var total = availableTabs.length;
i, tab; var i;
var tab;
for (i = total - 1; i >= 0; i --) { for (i = total - 1; i >= 0; i--) {
tab = availableTabs.eq(i); tab = availableTabs.eq(i);
menu.prepend(tab.clone(true).removeClass('tab')); menu.prepend(tab.clone(true).removeClass('tab'));
tab.hide(); tab.hide();
if ($this.height() <= maxHeight) { if ($this.height() <= maxHeight) {
menu.find('a').click(function() { check(true); }); menu.find('a').click(() => {
check(true);
});
return; return;
} }
} }
menu.find('a').click(function() { check(true); });
menu.find('a').click(() => {
check(true);
});
} }
phpbb.registerDropdown(item.find('a.responsive-tab-link'), item.find('.dropdown'), {visibleClass: 'activetab', verticalDirection: 'down'}); phpbb.registerDropdown(item.find('a.responsive-tab-link'), item.find('.dropdown'), { visibleClass: 'activetab', verticalDirection: 'down' });
check(true); check(true);
$(window).resize(check); $(window).resize(check);
@ -248,7 +254,7 @@ function parse_document(container)
* Run onload functions * Run onload functions
*/ */
(function($) { (function($) {
$(document).ready(function() { $(document).ready(() => {
// Swap .nojs and .hasjs // Swap .nojs and .hasjs
$('body.nojs').toggleClass('nojs hasjs'); $('body.nojs').toggleClass('nojs hasjs');
@ -257,12 +263,12 @@ function parse_document(container)
$('#' + this.getAttribute('data-focus')).focus(); $('#' + this.getAttribute('data-focus')).focus();
}); });
parse_document($('body')); parseDocument($('body'));
$('#questionnaire-form').css('display', 'none'); $('#questionnaire-form').css('display', 'none');
var $triggerConfiglist = $('#trigger-configlist'); var $triggerConfiglist = $('#trigger-configlist');
$triggerConfiglist.on('click', function () { $triggerConfiglist.on('click', function() {
var $configlist = $('#configlist'); var $configlist = $('#configlist');
$configlist.closest('.send-stats-data-row').toggleClass('send-stats-data-hidden'); $configlist.closest('.send-stats-data-row').toggleClass('send-stats-data-hidden');
$configlist.closest('.send-stats-row').find('.send-stats-data-row:first-child').toggleClass('send-stats-data-only-row'); $configlist.closest('.send-stats-row').find('.send-stats-data-row:first-child').toggleClass('send-stats-data-only-row');
@ -272,8 +278,8 @@ function parse_document(container)
$('#configlist').closest('.send-stats-data-row').addClass('send-stats-data-hidden'); $('#configlist').closest('.send-stats-data-row').addClass('send-stats-data-hidden');
// Do not underline actions icons on hover (could not be done via CSS) // Do not underline actions icons on hover (could not be done via CSS)
$('.actions a:has(i.acp-icon)').mouseover(function () { $('.actions a:has(i.acp-icon)').mouseover(function() {
$(this).css("text-decoration", "none"); $(this).css('text-decoration', 'none');
}); });
// Live update BBCode font icon preview // Live update BBCode font icon preview
@ -296,11 +302,11 @@ function parse_document(container)
const pageIconFont = document.getElementById('bbcode_font_icon'); const pageIconFont = document.getElementById('bbcode_font_icon');
if (pageIconFont) { if (pageIconFont) {
pageIconFont.addEventListener('keyup', function () { pageIconFont.addEventListener('keyup', function() {
updateIconClass(this.nextElementSibling, this.value); updateIconClass(this.nextElementSibling, this.value);
}); });
pageIconFont.addEventListener('blur', function () { pageIconFont.addEventListener('blur', function() {
updateIconClass(this.nextElementSibling, this.value); updateIconClass(this.nextElementSibling, this.value);
}); });
} }

View file

@ -1,29 +1,27 @@
/* global phpbb, statsData */ /* global phpbb, statsData */
/* eslint no-var: 0 */
(function($) { // Avoid conflicts with other libraries (function($) { // Avoid conflicts with other libraries
'use strict';
'use strict'; phpbb.prepareSendStats = function() {
phpbb.prepareSendStats = function () {
var $form = $('#acp_help_phpbb'); var $form = $('#acp_help_phpbb');
var $dark = $('#darkenwrapper'); var $dark = $('#darkenwrapper');
var $loadingIndicator; var $loadingIndicator;
$form.on('submit', function (event) { $form.on('submit', function(event) {
var $this = $(this), var $this = $(this);
currentTime = Math.floor(new Date().getTime() / 1000), var currentTime = Math.floor(new Date().getTime() / 1000);
statsTime = parseInt($this.find('input[name=help_send_statistics_time]').val(), 10); var statsTime = parseInt($this.find('input[name=help_send_statistics_time]').val(), 10);
event.preventDefault(); event.preventDefault();
$this.unbind('submit'); $this.unbind('submit');
// Skip ajax request if form is submitted too early or send stats // Skip ajax request if form is submitted too early or send stats
// checkbox is not checked // checkbox is not checked
if (!$this.find('input[name=help_send_statistics]').is(':checked') || if (!$this.find('input[name=help_send_statistics]').is(':checked') || statsTime > currentTime) {
statsTime > currentTime) {
$form.find('input[type=submit]').click(); $form.find('input[type=submit]').click();
setTimeout(function () { setTimeout(() => {
$form.find('input[type=submit]').click(); $form.find('input[type=submit]').click();
}, 300); }, 300);
return; return;
@ -36,6 +34,7 @@ phpbb.prepareSendStats = function () {
if (typeof console !== 'undefined' && console.log) { if (typeof console !== 'undefined' && console.log) {
console.log('AJAX error. status: ' + textStatus + ', message: ' + errorThrown); console.log('AJAX error. status: ' + textStatus + ', message: ' + errorThrown);
} }
phpbb.clearLoadingTimeout(); phpbb.clearLoadingTimeout();
var errorText = ''; var errorText = '';
@ -47,6 +46,7 @@ phpbb.prepareSendStats = function () {
errorText = $dark.attr('data-ajax-error-text'); errorText = $dark.attr('data-ajax-error-text');
} }
} }
phpbb.alert($dark.attr('data-ajax-error-title'), errorText); phpbb.alert($dark.attr('data-ajax-error-title'), errorText);
} }
@ -74,7 +74,7 @@ phpbb.prepareSendStats = function () {
var $sendStatisticsSuccess = $('<input />', { var $sendStatisticsSuccess = $('<input />', {
type: 'hidden', type: 'hidden',
name: 'send_statistics_response', name: 'send_statistics_response',
value: JSON.stringify(res) value: JSON.stringify(res),
}); });
$sendStatisticsSuccess.appendTo('p.submit-buttons'); $sendStatisticsSuccess.appendTo('p.submit-buttons');
@ -90,78 +90,77 @@ phpbb.prepareSendStats = function () {
data: statsData, data: statsData,
success: returnHandler, success: returnHandler,
error: errorHandler, error: errorHandler,
cache: false cache: false,
}).always(function() { }).always(() => {
if ($loadingIndicator && $loadingIndicator.is(':visible')) { if ($loadingIndicator && $loadingIndicator.is(':visible')) {
$loadingIndicator.fadeOut(phpbb.alertTime); $loadingIndicator.fadeOut(phpbb.alertTime);
} }
}); });
}); });
}; };
/** /**
* The following callbacks are for reording items. row_down * The following callbacks are for reording items. row_down
* is triggered when an item is moved down, and row_up is triggered when * is triggered when an item is moved down, and row_up is triggered when
* an item is moved up. It moves the row up or down, and deactivates / * an item is moved up. It moves the row up or down, and deactivates /
* activates any up / down icons that require it (the ones at the top or bottom). * activates any up / down icons that require it (the ones at the top or bottom).
*/ */
phpbb.addAjaxCallback('row_down', function(res) { phpbb.addAjaxCallback('row_down', function(res) {
if (typeof res.success === 'undefined' || !res.success) { if (typeof res.success === 'undefined' || !res.success) {
return; return;
} }
var $firstTr = $(this).parents('tr'), var $firstTr = $(this).parents('tr');
$secondTr = $firstTr.next(); var $secondTr = $firstTr.next();
$firstTr.insertAfter($secondTr); $firstTr.insertAfter($secondTr);
}); });
phpbb.addAjaxCallback('row_up', function(res) { phpbb.addAjaxCallback('row_up', function(res) {
if (typeof res.success === 'undefined' || !res.success) { if (typeof res.success === 'undefined' || !res.success) {
return; return;
} }
var $secondTr = $(this).parents('tr'), var $secondTr = $(this).parents('tr');
$firstTr = $secondTr.prev(); var $firstTr = $secondTr.prev();
$secondTr.insertBefore($firstTr); $secondTr.insertBefore($firstTr);
}); });
/** /**
* This callback replaces activate links with deactivate links and vice versa. * This callback replaces activate links with deactivate links and vice versa.
* It does this by replacing the text, and replacing all instances of "activate" * It does this by replacing the text, and replacing all instances of "activate"
* in the href with "deactivate", and vice versa. * in the href with "deactivate", and vice versa.
*/ */
phpbb.addAjaxCallback('activate_deactivate', function(res) { phpbb.addAjaxCallback('activate_deactivate', function(res) {
var $this = $(this), var $this = $(this);
newHref = $this.attr('href'); var newHref = $this.attr('href');
$this.text(res.text); $this.text(res.text);
if (newHref.indexOf('deactivate') !== -1) { if (newHref.indexOf('deactivate') === -1) {
newHref = newHref.replace('deactivate', 'activate');
} else {
newHref = newHref.replace('activate', 'deactivate'); newHref = newHref.replace('activate', 'deactivate');
} else {
newHref = newHref.replace('deactivate', 'activate');
} }
$this.attr('href', newHref); $this.attr('href', newHref);
}); });
/** /**
* The removes the parent row of the link or form that triggered the callback, * The removes the parent row of the link or form that triggered the callback,
* and is good for stuff like the removal of forums. * and is good for stuff like the removal of forums.
*/ */
phpbb.addAjaxCallback('row_delete', function(res) { phpbb.addAjaxCallback('row_delete', function(res) {
if (res.SUCCESS !== false) { if (res.SUCCESS !== false) {
$(this).parents('tr').remove(); $(this).parents('tr').remove();
} }
}); });
/** /**
* This callback generates the VAPID keys for the web push notification service. * This callback generates the VAPID keys for the web push notification service.
*/ */
phpbb.addAjaxCallback('generate_vapid_keys', () => { phpbb.addAjaxCallback('generate_vapid_keys', () => {
/** /**
* Generate VAPID keypair with public and private key string * Generate VAPID keypair with public and private key string
* *
@ -176,7 +175,7 @@ phpbb.addAjaxCallback('generate_vapid_keys', () => {
namedCurve: 'P-256', namedCurve: 'P-256',
}, },
true, true,
['deriveKey', 'deriveBits'] [ 'deriveKey', 'deriveBits' ],
); );
const privateKeyJwk = await crypto.subtle.exportKey('jwk', keyPair.privateKey); const privateKeyJwk = await crypto.subtle.exportKey('jwk', keyPair.privateKey);
@ -187,7 +186,7 @@ phpbb.addAjaxCallback('generate_vapid_keys', () => {
return { return {
privateKey: privateKeyString, privateKey: privateKeyString,
publicKey: publicKeyString publicKey: publicKeyString,
}; };
} catch (error) { } catch (error) {
console.error('Error generating keys with SubtleCrypto:', error); console.error('Error generating keys with SubtleCrypto:', error);
@ -199,38 +198,38 @@ phpbb.addAjaxCallback('generate_vapid_keys', () => {
if (!keyPair) { if (!keyPair) {
return; return;
} }
const publicKeyInput = document.querySelector('#webpush_vapid_public'); const publicKeyInput = document.querySelector('#webpush_vapid_public');
const privateKeyInput = document.querySelector('#webpush_vapid_private'); const privateKeyInput = document.querySelector('#webpush_vapid_private');
publicKeyInput.value = keyPair.publicKey; publicKeyInput.value = keyPair.publicKey;
privateKeyInput.value = keyPair.privateKey; privateKeyInput.value = keyPair.privateKey;
}) });
}) });
/** /**
* Handler for submitting permissions form in chunks * Handler for submitting permissions form in chunks
* This call will submit permissions forms in chunks of 5 fieldsets. * This call will submit permissions forms in chunks of 5 fieldsets.
*/ */
function submitPermissions() { function submitPermissions() {
var $form = $('form#set-permissions'), var $form = $('form#set-permissions');
fieldsetList = $form.find('fieldset[id^=perm]'), var fieldsetList = $form.find('fieldset[id^=perm]');
formDataSets = [], var formDataSets = [];
dataSetIndex = 0, var dataSetIndex = 0;
$submitAllButton = $form.find('input[type=submit][name^=action]')[0], var $submitAllButton = $form.find('input[type=submit][name^=action]')[0];
$submitButton = $form.find('input[type=submit][data-clicked=true]')[0]; var $submitButton = $form.find('input[type=submit][data-clicked=true]')[0];
// Set proper start values for handling refresh of page // Set proper start values for handling refresh of page
var permissionSubmitSize = 0, var permissionSubmitSize = 0;
permissionRequestCount = 0, var permissionRequestCount = 0;
forumIds = [], var forumIds = [];
permissionSubmitFailed = false, var permissionSubmitFailed = false;
clearIndicator = true, var clearIndicator = true;
$loadingIndicator;
if ($submitAllButton !== $submitButton) { if ($submitAllButton !== $submitButton) {
fieldsetList = $form.find('fieldset#' + $submitButton.closest('fieldset.permissions').id); fieldsetList = $form.find('fieldset#' + $submitButton.closest('fieldset.permissions').id);
} }
$.each(fieldsetList, function (key, value) { $.each(fieldsetList, (key, value) => {
dataSetIndex = Math.floor(key / 5); dataSetIndex = Math.floor(key / 5);
var $fieldset = $('fieldset#' + value.id); var $fieldset = $('fieldset#' + value.id);
if (key % 5 === 0) { if (key % 5 === 0) {
@ -244,21 +243,21 @@ function submitPermissions() {
if (roleInput.val()) { if (roleInput.val()) {
formDataSets[dataSetIndex] += '&' + roleInput.attr('name') + '=' + roleInput.val(); formDataSets[dataSetIndex] += '&' + roleInput.attr('name') + '=' + roleInput.val();
} else { } else {
formDataSets[dataSetIndex] += '&' + roleInput.attr('name') + '=' + formDataSets[dataSetIndex] += '&' + roleInput.attr('name') + '='
$fieldset.find('select[name="' + roleInput.attr('name') + '"]').val(); + $fieldset.find('select[name="' + roleInput.attr('name') + '"]').val();
} }
}); });
permissionSubmitSize = formDataSets.length; permissionSubmitSize = formDataSets.length;
// Add each forum ID to forum ID list to preserve selected forums // Add each forum ID to forum ID list to preserve selected forums
$.each($form.find('input[type=hidden][name^=forum_id]'), function (key, value) { $.each($form.find('input[type=hidden][name^=forum_id]'), (key, value) => {
if (value.name.match(/^forum_id\[([0-9]+)\]$/)) { if (value.name.match(/^forum_id\[([0-9]+)\]$/)) {
forumIds.push(value.value); forumIds.push(value.value);
} }
}); });
$loadingIndicator = phpbb.loadingIndicator(); var $loadingIndicator = phpbb.loadingIndicator();
/** /**
* Handler for submitted permissions form chunk * Handler for submitted permissions form chunk
@ -286,18 +285,18 @@ function submitPermissions() {
$alertBoxLink.attr('href', $alertBoxLink.attr('href').replace(/(&forum_id\[\]=[0-9]+)/g, '')); $alertBoxLink.attr('href', $alertBoxLink.attr('href').replace(/(&forum_id\[\]=[0-9]+)/g, ''));
const $previousPageForm = $('<form>').attr({ const $previousPageForm = $('<form>').attr({
action: $alertBoxLink.attr('href'), action: $alertBoxLink.attr('href'),
method: 'post' method: 'post',
}); });
$.each(forumIds, function (key, value) { $.each(forumIds, (key, value) => {
$previousPageForm.append($('<input>').attr({ $previousPageForm.append($('<input>').attr({
type: 'text', type: 'text',
name: 'forum_id[]', name: 'forum_id[]',
value: value value,
})); }));
}); });
$alertBoxLink.on('click', function (e) { $alertBoxLink.on('click', e => {
$('body').append($previousPageForm); $('body').append($previousPageForm);
e.preventDefault(); e.preventDefault();
$previousPageForm.submit(); $previousPageForm.submit();
@ -309,19 +308,19 @@ function submitPermissions() {
$alert.find('.alert_close').hide(); $alert.find('.alert_close').hide();
if (typeof res.REFRESH_DATA !== 'undefined') { if (typeof res.REFRESH_DATA !== 'undefined') {
setTimeout(function () { setTimeout(() => {
// Create forum to submit using POST. This will prevent // Create forum to submit using POST. This will prevent
// exceeding the maximum length of URLs // exceeding the maximum length of URLs
const $form = $('<form>').attr({ const $form = $('<form>').attr({
action: res.REFRESH_DATA.url.replace(/(&forum_id\[\]=[0-9]+)/g, ''), action: res.REFRESH_DATA.url.replace(/(&forum_id\[\]=[0-9]+)/g, ''),
method: 'post' method: 'post',
}); });
$.each(forumIds, function (key, value) { $.each(forumIds, (key, value) => {
$form.append($('<input>').attr({ $form.append($('<input>').attr({
type: 'text', type: 'text',
name: 'forum_id[]', name: 'forum_id[]',
value: value value,
})); }));
}); });
@ -329,7 +328,7 @@ function submitPermissions() {
// Hide the alert even if we refresh the page, in case the user // Hide the alert even if we refresh the page, in case the user
// presses the back button. // presses the back button.
$dark.fadeOut(phpbb.alertTime, function () { $dark.fadeOut(phpbb.alertTime, () => {
if (typeof $alert !== 'undefined') { if (typeof $alert !== 'undefined') {
$alert.hide(); $alert.hide();
} }
@ -355,44 +354,44 @@ function submitPermissions() {
} }
// Create AJAX request for each form data set // Create AJAX request for each form data set
$.each(formDataSets, function (key, formData) { $.each(formDataSets, (key, formData) => {
$.ajax({ $.ajax({
url: $form.action, url: $form.action,
type: 'POST', type: 'POST',
data: formData + '&' + $submitButton.name + '=' + encodeURIComponent($submitButton.value) + data: formData + '&' + $submitButton.name + '=' + encodeURIComponent($submitButton.value)
'&creation_time=' + $form.find('input[type=hidden][name=creation_time]')[0].value + + '&creation_time=' + $form.find('input[type=hidden][name=creation_time]')[0].value
'&form_token=' + $form.find('input[type=hidden][name=form_token]')[0].value + + '&form_token=' + $form.find('input[type=hidden][name=form_token]')[0].value
'&' + $form.children('input[type=hidden]').serialize() + + '&' + $form.children('input[type=hidden]').serialize()
'&' + $form.find('input[type=checkbox][name^=inherit]').serialize(), + '&' + $form.find('input[type=checkbox][name^=inherit]').serialize(),
success: handlePermissionReturn, success: handlePermissionReturn,
error: handlePermissionReturn error: handlePermissionReturn,
}); });
}); });
} }
$('[data-ajax]').each(function() { $('[data-ajax]').each(function() {
var $this = $(this), var $this = $(this);
ajax = $this.attr('data-ajax'); var ajax = $this.attr('data-ajax');
if (ajax !== 'false') { if (ajax !== 'false') {
var fn = (ajax !== 'true') ? ajax : null; var fn = (ajax === 'true') ? null : ajax;
phpbb.ajaxify({ phpbb.ajaxify({
selector: this, selector: this,
refresh: $this.attr('data-refresh') !== undefined, refresh: $this.attr('data-refresh') !== undefined,
callback: fn callback: fn,
}); });
} }
}); });
/** /**
* Automatically resize textarea * Automatically resize textarea
*/ */
$(function() { $(() => {
phpbb.resizeTextArea($('textarea:not(.no-auto-resize)'), {minHeight: 75}); phpbb.resizeTextArea($('textarea:not(.no-auto-resize)'), { minHeight: 75 });
var $setPermissionsForm = $('form#set-permissions'); var $setPermissionsForm = $('form#set-permissions');
if ($setPermissionsForm.length) { if ($setPermissionsForm.length) {
$setPermissionsForm.on('submit', function (e) { $setPermissionsForm.on('submit', e => {
submitPermissions(); submitPermissions();
e.preventDefault(); e.preventDefault();
}); });
@ -412,13 +411,11 @@ $(function() {
} else { } else {
dateoptionInput.value = this.value; dateoptionInput.value = this.value;
} }
}) });
} }
if ($('#acp_help_phpbb')) { if ($('#acp_help_phpbb')) {
phpbb.prepareSendStats(); phpbb.prepareSendStats();
} }
}); });
})(jQuery); // Avoid conflicts with other libraries })(jQuery); // Avoid conflicts with other libraries

View file

@ -1,4 +1,8 @@
/* global phpbb */ /* global phpbb */
/* eslint camelcase: 0 */
/* eslint no-undef: 0 */
/* eslint no-unused-vars: 0 */
/* eslint no-var: 0 */
/** /**
* Hide and show all checkboxes * Hide and show all checkboxes
@ -9,12 +13,11 @@ function display_checkboxes(status) {
var cb = document.getElementsByTagName('input'); var cb = document.getElementsByTagName('input');
var display; var display;
//show
if (status) { if (status) {
// show
display = 'inline'; display = 'inline';
} } else {
//hide // hide
else {
display = 'none'; display = 'none';
} }
@ -31,10 +34,10 @@ function display_checkboxes(status) {
* value = 0 (hidden) till 10 (fully visible) * value = 0 (hidden) till 10 (fully visible)
*/ */
function set_opacity(e, value) { function set_opacity(e, value) {
e.style.opacity = value/10; e.style.opacity = value / 10;
//IE opacity currently turned off, because of its astronomical stupidity // IE opacity currently turned off, because of its astronomical stupidity
//e.style.filter = 'alpha(opacity=' + value*10 + ')'; // e.style.filter = 'alpha(opacity=' + value*10 + ')';
} }
/** /**
@ -72,11 +75,11 @@ function reset_opacity(status, except_id) {
} }
} }
if (typeof(except_id) !== 'undefined') { if (typeof (except_id) !== 'undefined') {
set_opacity(document.getElementById('perm' + except_id), 10); set_opacity(document.getElementById('perm' + except_id), 10);
} }
//reset checkboxes too // reset checkboxes too
marklist('set-permissions', 'inherit', !status); marklist('set-permissions', 'inherit', !status);
} }
@ -86,13 +89,14 @@ function reset_opacity(status, except_id) {
* rb = array of radiobuttons * rb = array of radiobuttons
*/ */
function get_radio_status(index, rb) { function get_radio_status(index, rb) {
for (var i = index; i < rb.length; i = i + 3 ) { for (var i = index; i < rb.length; i += 3 ) {
if (rb[i].checked !== true) { if (rb[i].checked !== true) {
if (i > index) { if (i > index) {
//at least one is true, but not all (custom) // at least one is true, but not all (custom)
return 2; return 2;
} }
//first one is not true
// first one is not true
return 0; return 0;
} }
} }
@ -111,7 +115,7 @@ function set_colours(id, init, quick) {
var table = document.getElementById('table' + id); var table = document.getElementById('table' + id);
var tab = document.getElementById('tab' + id); var tab = document.getElementById('tab' + id);
if (typeof(quick) !== 'undefined') { if (typeof (quick) !== 'undefined') {
tab.className = 'permissions-preset-' + quick + ' activetab'; tab.className = 'permissions-preset-' + quick + ' activetab';
return; return;
} }
@ -161,7 +165,7 @@ function init_colours(block_id) {
} }
} }
tab.className = tab.className + ' activetab'; tab.className += ' activetab';
} }
/** /**
@ -170,6 +174,7 @@ function init_colours(block_id) {
* adv = we are opening advanced permissions * adv = we are opening advanced permissions
* view = called from view permissions * view = called from view permissions
*/ */
// eslint-disable-next-line max-params
function swap_options(pmask, fmask, cat, adv, view) { function swap_options(pmask, fmask, cat, adv, view) {
id = pmask + fmask + cat; id = pmask + fmask + cat;
active_option = active_pmask + active_fmask + active_cat; active_option = active_pmask + active_fmask + active_cat;
@ -196,14 +201,14 @@ function swap_options(pmask, fmask, cat, adv, view) {
display_checkboxes(true); display_checkboxes(true);
reset_opacity(1); reset_opacity(1);
} else if (adv) { } else if (adv) {
//Checkbox might have been clicked, but we need full visibility // Checkbox might have been clicked, but we need full visibility
display_checkboxes(true); display_checkboxes(true);
reset_opacity(1); reset_opacity(1);
} }
// set active tab // set active tab
old_tab.className = old_tab.className.replace(/\ activetab/g, ''); old_tab.className = old_tab.className.replace(/ activetab/g, '');
new_tab.className = new_tab.className + ' activetab'; new_tab.className += ' activetab';
if (id === active_option && adv !== true) { if (id === active_option && adv !== true) {
return; return;
@ -211,7 +216,7 @@ function swap_options(pmask, fmask, cat, adv, view) {
phpbb.toggleDisplay('options' + active_option, -1); phpbb.toggleDisplay('options' + active_option, -1);
//hiding and showing the checkbox // hiding and showing the checkbox
if (document.getElementById('checkbox' + active_pmask + active_fmask)) { if (document.getElementById('checkbox' + active_pmask + active_fmask)) {
phpbb.toggleDisplay('checkbox' + pmask + fmask, -1); phpbb.toggleDisplay('checkbox' + pmask + fmask, -1);
@ -227,6 +232,7 @@ function swap_options(pmask, fmask, cat, adv, view) {
if (!view) { if (!view) {
phpbb.toggleDisplay('advanced' + pmask + fmask, 1); phpbb.toggleDisplay('advanced' + pmask + fmask, 1);
} }
phpbb.toggleDisplay('options' + id, 1); phpbb.toggleDisplay('options' + id, 1);
active_pmask = pmask; active_pmask = pmask;
@ -248,7 +254,7 @@ function mark_options(id, s) {
var rb = t.getElementsByTagName('input'); var rb = t.getElementsByTagName('input');
for (var r = 0; r < rb.length; r++) { for (var r = 0; r < rb.length; r++) {
if (rb[r].id.substr(rb[r].id.length-1) === s) { if (rb[r].id.substr(rb[r].id.length - 1) === s) {
rb[r].checked = true; rb[r].checked = true;
} }
} }
@ -264,7 +270,7 @@ function mark_one_option(id, field_name, s) {
var rb = t.getElementsByTagName('input'); var rb = t.getElementsByTagName('input');
for (var r = 0; r < rb.length; r++) { for (var r = 0; r < rb.length; r++) {
if (rb[r].id.substr(rb[r].id.length-field_name.length-3, field_name.length) === field_name && rb[r].id.substr(rb[r].id.length-1) === s) { if (rb[r].id.substr(rb[r].id.length - field_name.length - 3, field_name.length) === field_name && rb[r].id.substr(rb[r].id.length - 1) === s) {
rb[r].checked = true; rb[r].checked = true;
} }
} }
@ -287,10 +293,10 @@ function reset_role(id) {
} }
// Before resetting the role dropdown, try and match any permission role // Before resetting the role dropdown, try and match any permission role
var parent = t.parentNode, var parent = t.parentNode;
roleId = match_role_settings(id.replace('role', 'perm')), var roleId = match_role_settings(id.replace('role', 'perm'));
text = no_role_assigned, var text = no_role_assigned;
index = 0; var index = 0;
// If a role permissions was matched, grab that option's value and index // If a role permissions was matched, grab that option's value and index
if (roleId) { if (roleId) {
@ -326,8 +332,10 @@ function set_role_settings(role_id, target_id) {
mark_options(target_id, 'u'); mark_options(target_id, 'u');
for (var r in settings) { for (var r in settings) {
if (Object.prototype.hasOwnProperty.call(settings, r)) {
mark_one_option(target_id, r, (settings[r] === 1) ? 'y' : 'n'); mark_one_option(target_id, r, (settings[r] === 1) ? 'y' : 'n');
} }
}
} }
/** /**
@ -337,9 +345,9 @@ function set_role_settings(role_id, target_id) {
* @return {number} The permission role identifier * @return {number} The permission role identifier
*/ */
function match_role_settings(id) { function match_role_settings(id) {
var fieldset = document.getElementById(id), var fieldset = document.getElementById(id);
radios = fieldset.getElementsByTagName('input'), var radios = fieldset.getElementsByTagName('input');
set = {}; var set = {};
// Iterate over all the radio buttons // Iterate over all the radio buttons
for (var i = 0; i < radios.length; i++) { for (var i = 0; i < radios.length; i++) {
@ -355,8 +363,7 @@ function match_role_settings(id) {
set = sort_and_stringify(set); set = sort_and_stringify(set);
// Iterate over the available role options and return the first match // Iterate over the available role options and return the first match
for (var r in role_options) for (var r in role_options) {
{
if (sort_and_stringify(role_options[r]) === set) { if (sort_and_stringify(role_options[r]) === set) {
return parseInt(r, 10); return parseInt(r, 10);
} }
@ -372,7 +379,7 @@ function match_role_settings(id) {
* @return {string} The sorted object as a string * @return {string} The sorted object as a string
*/ */
function sort_and_stringify(obj) { function sort_and_stringify(obj) {
return JSON.stringify(Object.keys(obj).sort().reduce(function (result, key) { return JSON.stringify(Object.keys(obj).sort().reduce((result, key) => {
result[key] = obj[key]; result[key] = obj[key];
return result; return result;
}, {})); }, {}));

View file

@ -1,4 +1,5 @@
/* global phpbb */ /* global phpbb */
/* eslint no-var: 0 */
/* /*
javascript for Bubble Tooltips by Alessandro Fulciniti javascript for Bubble Tooltips by Alessandro Fulciniti
@ -13,36 +14,35 @@ phpBB Development Team:
*/ */
(function($) { // Avoid conflicts with other libraries (function($) { // Avoid conflicts with other libraries
'use strict';
'use strict'; var tooltips = [];
var tooltips = []; /**
/**
* Enable tooltip replacements for selects * Enable tooltip replacements for selects
* @param {string} id ID tag of select * @param {string} id ID tag of select
* @param {string} headline Text that should appear on top of tooltip * @param {string} headline Text that should appear on top of tooltip
* @param {string} [subId] Sub ID that should only be using tooltips (optional) * @param {string} [subId] Sub ID that should only be using tooltips (optional)
*/ */
phpbb.enableTooltipsSelect = function (id, headline, subId) { phpbb.enableTooltipsSelect = function(id, headline, subId) {
var $links, hold; var $links;
hold = $('<span />', { var hold = $('<span />', {
id: '_tooltip_container', id: '_tooltip_container',
css: { css: {
position: 'absolute' position: 'absolute',
} },
}); });
$('body').append(hold); $('body').append(hold);
if (!id) { if (id) {
$links = $('.roles-options li');
} else {
$links = $('.roles-options li', '#' + id); $links = $('.roles-options li', '#' + id);
} else {
$links = $('.roles-options li');
} }
$links.each(function () { $links.each(function() {
var $this = $(this); var $this = $(this);
if (subId) { if (subId) {
@ -53,44 +53,42 @@ phpbb.enableTooltipsSelect = function (id, headline, subId) {
phpbb.prepareTooltips($this, headline); phpbb.prepareTooltips($this, headline);
} }
}); });
}; };
/** /**
* Prepare elements to replace * Prepare elements to replace
* *
* @param {jQuery} $element Element to prepare for tooltips * @param {jQuery} $element Element to prepare for tooltips
* @param {string} headText Text heading to display * @param {string} headText Text heading to display
*/ */
phpbb.prepareTooltips = function ($element, headText) { phpbb.prepareTooltips = function($element, headText) {
var $tooltip, text, $desc, $title; var text = $element.attr('data-title');
text = $element.attr('data-title');
if (text === null || text.length === 0) { if (text === null || text.length === 0) {
return; return;
} }
$title = $('<span />', { var $title = $('<span />', {
class: 'top', class: 'top',
css: { css: {
display: 'block' display: 'block',
} },
}) })
.append(document.createTextNode(headText)); .append(document.createTextNode(headText));
$desc = $('<span />', { var $desc = $('<span />', {
class: 'bottom', class: 'bottom',
html: text, html: text,
css: { css: {
display: 'block' display: 'block',
} },
}); });
$tooltip = $('<span />', { var $tooltip = $('<span />', {
class: 'tooltip', class: 'tooltip',
css: { css: {
display: 'block' display: 'block',
} },
}) })
.append($title) .append($title)
.append($desc); .append($desc);
@ -98,63 +96,61 @@ phpbb.prepareTooltips = function ($element, headText) {
tooltips[$element.attr('data-id')] = $tooltip; tooltips[$element.attr('data-id')] = $tooltip;
$element.on('mouseover', phpbb.showTooltip); $element.on('mouseover', phpbb.showTooltip);
$element.on('mouseout', phpbb.hideTooltip); $element.on('mouseout', phpbb.hideTooltip);
}; };
/** /**
* Show tooltip * Show tooltip
* *
* @param {object} $element Element passed by .on() * @param {object} $element Element passed by .on()
*/ */
phpbb.showTooltip = function ($element) { phpbb.showTooltip = function($element) {
var $this = $($element.target); var $this = $($element.target);
$('#_tooltip_container').append(tooltips[$this.attr('data-id')]); $('#_tooltip_container').append(tooltips[$this.attr('data-id')]);
phpbb.positionTooltip($this); phpbb.positionTooltip($this);
}; };
/** /**
* Hide tooltip * Hide tooltip
*/ */
phpbb.hideTooltip = function () { phpbb.hideTooltip = function() {
var d = document.getElementById('_tooltip_container'); var d = document.getElementById('_tooltip_container');
if (d.childNodes.length > 0) { if (d.childNodes.length > 0) {
d.removeChild(d.firstChild); d.removeChild(d.firstChild);
} }
}; };
/** /**
* Correct positioning of tooltip container * Correct positioning of tooltip container
* *
* @param {jQuery} $element Tooltip element that should be positioned * @param {jQuery} $element Tooltip element that should be positioned
*/ */
phpbb.positionTooltip = function ($element) { phpbb.positionTooltip = function($element) {
var offset;
$element = $element.parent(); $element = $element.parent();
offset = $element.offset(); var offset = $element.offset();
if ($('body').hasClass('rtl')) { if ($('body').hasClass('rtl')) {
$('#_tooltip_container').css({ $('#_tooltip_container').css({
top: offset.top + 30, top: offset.top + 30,
left: offset.left + 255 left: offset.left + 255,
}); });
} else { } else {
$('#_tooltip_container').css({ $('#_tooltip_container').css({
top: offset.top + 30, top: offset.top + 30,
left: offset.left - 205 left: offset.left - 205,
}); });
} }
}; };
/** /**
* Prepare roles drop down select * Prepare roles drop down select
*/ */
phpbb.prepareRolesDropdown = function () { phpbb.prepareRolesDropdown = function() {
var $options = $('.roles-options li'); var $options = $('.roles-options li');
// Display span and hide select // Display span and hide select
$('.roles-options > span').css('display', 'block'); $('.roles-options > span').css('display', 'block');
$('.roles-options > select').hide(); $('.roles-options > select').hide();
$('.roles-options > input[type=hidden]').each(function () { $('.roles-options > input[type=hidden]').each(function() {
var $this = $(this); var $this = $(this);
if ($this.attr('data-name') && !$this.attr('name')) { if ($this.attr('data-name') && !$this.attr('name')) {
@ -163,7 +159,7 @@ phpbb.prepareRolesDropdown = function () {
}); });
// Prepare highlighting of select options and settings update // Prepare highlighting of select options and settings update
$options.each(function () { $options.each(function() {
var $this = $(this); var $this = $(this);
var $rolesOptions = $this.closest('.roles-options'); var $rolesOptions = $this.closest('.roles-options');
var $span = $rolesOptions.children('span'); var $span = $rolesOptions.children('span');
@ -182,23 +178,25 @@ phpbb.prepareRolesDropdown = function () {
} }
// Prepare resetting drop down on form reset // Prepare resetting drop down on form reset
$this.closest('form').on('reset', function () { $this.closest('form').on('reset', () => {
$span.text($span.attr('data-default')); $span.text($span.attr('data-default'));
$rolesOptions.children('input[type=hidden]') $rolesOptions.children('input[type=hidden]')
.val($span.attr('data-default-val')); .val($span.attr('data-default-val'));
}); });
} }
$this.on('mouseover', function () { $this.on('mouseover', function() {
var $this = $(this); var $this = $(this);
$options.removeClass('roles-highlight'); $options.removeClass('roles-highlight');
$this.addClass('roles-highlight'); $this.addClass('roles-highlight');
}).on('click', function () { }).on('click', function() {
var $this = $(this); var $this = $(this);
var $rolesOptions = $this.closest('.roles-options'); var $rolesOptions = $this.closest('.roles-options');
// Update settings // Update settings
// eslint-disable-next-line no-undef
set_role_settings($this.attr('data-id'), $this.attr('data-target-id')); set_role_settings($this.attr('data-id'), $this.attr('data-target-id'));
// eslint-disable-next-line no-undef
init_colours($this.attr('data-target-id').replace('advanced', '')); init_colours($this.attr('data-target-id').replace('advanced', ''));
// Set selected setting // Set selected setting
@ -211,15 +209,14 @@ phpbb.prepareRolesDropdown = function () {
$('body').trigger('click'); $('body').trigger('click');
}); });
}); });
}; };
// Run onload functions for RolesDropdown and tooltips // Run onload functions for RolesDropdown and tooltips
$(function() { $(() => {
// Enable tooltips // Enable tooltips
phpbb.enableTooltipsSelect('set-permissions', $('#set-permissions').attr('data-role-description'), 'role'); phpbb.enableTooltipsSelect('set-permissions', $('#set-permissions').attr('data-role-description'), 'role');
// Prepare dropdown // Prepare dropdown
phpbb.prepareRolesDropdown(); phpbb.prepareRolesDropdown();
}); });
})(jQuery); // Avoid conflicts with other libraries })(jQuery); // Avoid conflicts with other libraries

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,11 @@
/* global phpbb */ /* global phpbb */
/* eslint camelcase: 0 */
/* eslint no-undef: 0 */
/* eslint no-unused-vars: 0 */
/* eslint no-var: 0 */
var form_name = 'postform';
var text_name = 'message';
/** /**
* bbCode control by subBlue design [ www.subBlue.com ] * bbCode control by subBlue design [ www.subBlue.com ]
@ -34,7 +41,7 @@ function initInsertions() {
var textarea = doc.forms[form_name].elements[text_name]; var textarea = doc.forms[form_name].elements[text_name];
if (is_ie && typeof(baseHeight) !== 'number') { if (is_ie && typeof (baseHeight) !== 'number') {
textarea.focus(); textarea.focus();
baseHeight = doc.selection.createRange().duplicate().boundingHeight; baseHeight = doc.selection.createRange().duplicate().boundingHeight;
@ -48,11 +55,11 @@ function initInsertions() {
* bbstyle * bbstyle
*/ */
function bbstyle(bbnumber) { function bbstyle(bbnumber) {
if (bbnumber !== -1) { if (bbnumber === -1) {
bbfontstyle(bbtags[bbnumber], bbtags[bbnumber+1]);
} else {
insert_text('[*]'); insert_text('[*]');
document.forms[form_name].elements[text_name].focus(); document.forms[form_name].elements[text_name].focus();
} else {
bbfontstyle(bbtags[bbnumber], bbtags[bbnumber + 1]);
} }
} }
@ -84,7 +91,7 @@ function bbfontstyle(bbopen, bbclose) {
return; return;
} }
//The new position for the cursor after adding the bbcode // The new position for the cursor after adding the bbcode
var caret_pos = getCaretPosition(textarea).start; var caret_pos = getCaretPosition(textarea).start;
var new_pos = caret_pos + bbopen.length; var new_pos = caret_pos + bbopen.length;
@ -96,11 +103,10 @@ function bbfontstyle(bbopen, bbclose) {
if (!isNaN(textarea.selectionStart)) { if (!isNaN(textarea.selectionStart)) {
textarea.selectionStart = new_pos; textarea.selectionStart = new_pos;
textarea.selectionEnd = new_pos; textarea.selectionEnd = new_pos;
} } else if (document.selection) {
// IE // IE
else if (document.selection) {
var range = textarea.createTextRange(); var range = textarea.createTextRange();
range.move("character", new_pos); range.move('character', new_pos);
range.select(); range.select();
storeCaret(textarea); storeCaret(textarea);
} }
@ -114,10 +120,10 @@ function bbfontstyle(bbopen, bbclose) {
function insert_text(text, spaces, popup) { function insert_text(text, spaces, popup) {
var textarea; var textarea;
if (!popup) { if (popup) {
textarea = document.forms[form_name].elements[text_name];
} else {
textarea = opener.document.forms[form_name].elements[text_name]; textarea = opener.document.forms[form_name].elements[text_name];
} else {
textarea = document.forms[form_name].elements[text_name];
} }
if (spaces) { if (spaces) {
@ -142,7 +148,7 @@ function insert_text(text, spaces, popup) {
var caret_pos = textarea.caretPos; var caret_pos = textarea.caretPos;
caret_pos.text = caret_pos.text.charAt(caret_pos.text.length - 1) === ' ' ? caret_pos.text + text + ' ' : caret_pos.text + text; caret_pos.text = caret_pos.text.charAt(caret_pos.text.length - 1) === ' ' ? caret_pos.text + text + ' ' : caret_pos.text + text;
} else { } else {
textarea.value = textarea.value + text; textarea.value += text;
} }
if (!popup) { if (!popup) {
@ -171,6 +177,7 @@ function addquote(post_id, username, l_wrote, attributes) {
// Backwards compatibility // Backwards compatibility
l_wrote = 'wrote'; l_wrote = 'wrote';
} }
if (typeof attributes !== 'object') { if (typeof attributes !== 'object') {
attributes = {}; attributes = {};
} }
@ -195,10 +202,10 @@ function addquote(post_id, username, l_wrote, attributes) {
if (divarea.innerHTML) { if (divarea.innerHTML) {
theSelection = divarea.innerHTML.replace(/<br>/ig, '\n'); theSelection = divarea.innerHTML.replace(/<br>/ig, '\n');
theSelection = theSelection.replace(/<br\/>/ig, '\n'); theSelection = theSelection.replace(/<br\/>/ig, '\n');
theSelection = theSelection.replace(/&lt\;/ig, '<'); theSelection = theSelection.replace(/&lt;/ig, '<');
theSelection = theSelection.replace(/&gt\;/ig, '>'); theSelection = theSelection.replace(/&gt;/ig, '>');
theSelection = theSelection.replace(/&amp\;/ig, '&'); theSelection = theSelection.replace(/&amp;/ig, '&');
theSelection = theSelection.replace(/&nbsp\;/ig, ' '); theSelection = theSelection.replace(/&nbsp;/ig, ' ');
} else if (document.all) { } else if (document.all) {
theSelection = divarea.innerText; theSelection = divarea.innerText;
} else if (divarea.textContent) { } else if (divarea.textContent) {
@ -213,7 +220,7 @@ function addquote(post_id, username, l_wrote, attributes) {
attributes.author = username; attributes.author = username;
insert_text(generateQuote(theSelection, attributes)); insert_text(generateQuote(theSelection, attributes));
} else { } else {
insert_text(username + ' ' + l_wrote + ':' + '\n'); insert_text(username + ' ' + l_wrote + ':\n');
var lines = split_lines(theSelection); var lines = split_lines(theSelection);
for (i = 0; i < lines.length; i++) { for (i = 0; i < lines.length; i++) {
insert_text('> ' + lines[i] + '\n'); insert_text('> ' + lines[i] + '\n');
@ -243,12 +250,14 @@ function generateQuote(text, attributes) {
quote += '=' + formatAttributeValue(attributes.author); quote += '=' + formatAttributeValue(attributes.author);
delete attributes.author; delete attributes.author;
} }
for (var name in attributes) { for (var name in attributes) {
if (attributes.hasOwnProperty(name)) { if (Object.hasOwn(attributes, name)) {
var value = attributes[name]; var value = attributes[name];
quote += ' ' + name + '=' + formatAttributeValue(value.toString()); quote += ' ' + name + '=' + formatAttributeValue(value.toString());
} }
} }
quote += ']'; quote += ']';
var newline = ((quote + text + '[/quote]').length > 80 || text.indexOf('\n') > -1) ? '\n' : ''; var newline = ((quote + text + '[/quote]').length > 80 || text.indexOf('\n') > -1) ? '\n' : '';
quote += newline + text + newline + '[/quote]'; quote += newline + text + newline + '[/quote]';
@ -271,19 +280,20 @@ function formatAttributeValue(str) {
// Return as-is if it contains none of: space, ' " \ or ] // Return as-is if it contains none of: space, ' " \ or ]
return str; return str;
} }
var singleQuoted = "'" + str.replace(/[\\']/g, '\\$&') + "'",
doubleQuoted = '"' + str.replace(/[\\"]/g, '\\$&') + '"'; var singleQuoted = '\'' + str.replace(/[\\']/g, '\\$&') + '\'';
var doubleQuoted = '"' + str.replace(/[\\"]/g, '\\$&') + '"';
return (singleQuoted.length < doubleQuoted.length) ? singleQuoted : doubleQuoted; return (singleQuoted.length < doubleQuoted.length) ? singleQuoted : doubleQuoted;
} }
function split_lines(text) { function split_lines(text) {
var lines = text.split('\n'); var lines = text.split('\n');
var splitLines = new Array(); var splitLines = [];
var j = 0; var j = 0;
var i; var i;
for(i = 0; i < lines.length; i++) { for (i = 0; i < lines.length; i++) {
if (lines[i].length <= 80) { if (lines[i].length <= 80) {
splitLines[j] = lines[i]; splitLines[j] = lines[i];
j++; j++;
@ -302,9 +312,10 @@ function split_lines(text) {
j++; j++;
} }
} }
while(splitAt !== -1); while (splitAt !== -1);
} }
} }
return splitLines; return splitLines;
} }
@ -312,12 +323,12 @@ function split_lines(text) {
* From http://www.massless.org/mozedit/ * From http://www.massless.org/mozedit/
*/ */
function mozWrap(txtarea, open, close) { function mozWrap(txtarea, open, close) {
var selLength = (typeof(txtarea.textLength) === 'undefined') ? txtarea.value.length : txtarea.textLength; var selLength = (typeof (txtarea.textLength) === 'undefined') ? txtarea.value.length : txtarea.textLength;
var selStart = txtarea.selectionStart; var selStart = txtarea.selectionStart;
var selEnd = txtarea.selectionEnd; var selEnd = txtarea.selectionEnd;
var scrollTop = txtarea.scrollTop; var scrollTop = txtarea.scrollTop;
var s1 = (txtarea.value).substring(0,selStart); var s1 = (txtarea.value).substring(0, selStart);
var s2 = (txtarea.value).substring(selStart, selEnd); var s2 = (txtarea.value).substring(selStart, selEnd);
var s3 = (txtarea.value).substring(selEnd, selLength); var s3 = (txtarea.value).substring(selEnd, selLength);
@ -326,8 +337,6 @@ function mozWrap(txtarea, open, close) {
txtarea.selectionEnd = selEnd + open.length; txtarea.selectionEnd = selEnd + open.length;
txtarea.focus(); txtarea.focus();
txtarea.scrollTop = scrollTop; txtarea.scrollTop = scrollTop;
return;
} }
/** /**
@ -358,9 +367,8 @@ function getCaretPosition(txtarea) {
if (txtarea.selectionStart || txtarea.selectionStart === 0) { if (txtarea.selectionStart || txtarea.selectionStart === 0) {
caretPos.start = txtarea.selectionStart; caretPos.start = txtarea.selectionStart;
caretPos.end = txtarea.selectionEnd; caretPos.end = txtarea.selectionEnd;
} } else if (document.selection) {
// dirty and slow IE way // dirty and slow IE way
else if (document.selection) {
// get current selection // get current selection
var range = document.selection.createRange(); var range = document.selection.createRange();
@ -404,7 +412,7 @@ function getCaretPosition(txtarea) {
phpbb.showDragNDrop(textarea); phpbb.showDragNDrop(textarea);
} }
$('textarea').on('keydown', function (e) { $('textarea').on('keydown', function(e) {
if (e.which === 13 && (e.metaKey || e.ctrlKey)) { if (e.which === 13 && (e.metaKey || e.ctrlKey)) {
$(this).closest('form').find(':submit').click(); $(this).closest('form').find(':submit').click();
} }

View file

@ -2,6 +2,9 @@
* Installer's AJAX frontend handler * Installer's AJAX frontend handler
*/ */
/* eslint no-prototype-builtins: 0 */
/* eslint no-var: 0 */
(function($) { // Avoid conflicts with other libraries (function($) { // Avoid conflicts with other libraries
'use strict'; 'use strict';
@ -46,7 +49,10 @@
var $warningContainer = $('#warning-container'); var $warningContainer = $('#warning-container');
var $logContainer = $('#log-container'); var $logContainer = $('#log-container');
var $title, $description, $msgElement, arraySize = messages.length; var $title;
var $description;
var $msgElement;
var arraySize = messages.length;
for (var i = 0; i < arraySize; i++) { for (var i = 0; i < arraySize; i++) {
$msgElement = $('<div />'); $msgElement = $('<div />');
$title = $('<strong />'); $title = $('<strong />');
@ -59,24 +65,19 @@
$msgElement.append($description); $msgElement.append($description);
} }
switch (type) { if (type === 'error') {
case 'error':
$msgElement.addClass('errorbox'); $msgElement.addClass('errorbox');
$errorContainer.append($msgElement); $errorContainer.append($msgElement);
break; } else if (type === 'warning') {
case 'warning':
$msgElement.addClass('warningbox'); $msgElement.addClass('warningbox');
$warningContainer.append($msgElement); $warningContainer.append($msgElement);
break; } else if (type === 'log') {
case 'log':
$msgElement.addClass('log'); $msgElement.addClass('log');
$logContainer.prepend($msgElement); $logContainer.prepend($msgElement);
$logContainer.addClass('show_log_container'); $logContainer.addClass('show_log_container');
break; } else if (type === 'success') {
case 'success':
$msgElement.addClass('successbox'); $msgElement.addClass('successbox');
$errorContainer.prepend($msgElement); $errorContainer.prepend($msgElement);
break;
} }
} }
} }
@ -84,10 +85,12 @@
/** /**
* Render a download box * Render a download box
*/ */
function addDownloadBox(downloadArray) function addDownloadBox(downloadArray) {
{
var $downloadContainer = $('#download-wrapper'); var $downloadContainer = $('#download-wrapper');
var $downloadBox, $title, $content, $link; var $downloadBox;
var $title;
var $content;
var $link;
for (var i = 0; i < downloadArray.length; i++) { for (var i = 0; i < downloadArray.length; i++) {
$downloadBox = $('<div />'); $downloadBox = $('<div />');
@ -116,8 +119,7 @@
/** /**
* Render update files' status * Render update files' status
*/ */
function addUpdateFileStatus(fileStatus) function addUpdateFileStatus(fileStatus) {
{
var $statusContainer = $('#file-status-wrapper'); var $statusContainer = $('#file-status-wrapper');
$statusContainer.html(fileStatus); $statusContainer.html(fileStatus);
} }
@ -140,8 +142,10 @@
* @param navObj * @param navObj
*/ */
function updateNavbarStatus(navObj) { function updateNavbarStatus(navObj) {
var navID, $stage, $stageListItem, $active; var navID;
$active = $('#activemenu'); var $stage;
var $stageListItem;
var $active = $('#activemenu');
if (navObj.hasOwnProperty('finished')) { if (navObj.hasOwnProperty('finished')) {
// This should be an Array // This should be an Array
@ -179,7 +183,11 @@
* @param progressObject * @param progressObject
*/ */
function setProgress(progressObject) { function setProgress(progressObject) {
var $statusText, $progressBar, $progressText, $progressFiller, $progressFillerText; var $statusText;
var $progressBar;
var $progressText;
var $progressFiller;
var $progressFillerText;
if (progressObject.task_name.length) { if (progressObject.task_name.length) {
if (!progressBarTriggered) { if (!progressBarTriggered) {
@ -246,8 +254,8 @@
} }
// Redirects user // Redirects user
function redirect(url, use_ajax) { function redirect(url, useAjax) {
if (use_ajax) { if (useAjax) {
resetPolling(); resetPolling();
var xhReq = createXhrObject(); var xhReq = createXhrObject();
@ -276,6 +284,7 @@
if (window.console) { if (window.console) {
console.log('Failed to parse JSON object\n\nMessage: ' + err.message + '\n\nServer Response: ' + messageJSON); console.log('Failed to parse JSON object\n\nMessage: ' + err.message + '\n\nServer Response: ' + messageJSON);
} else { } else {
// eslint-disable-next-line no-alert
alert('Failed to parse JSON object\n\nMessage: ' + err.message + '\n\nServer Response: ' + messageJSON); alert('Failed to parse JSON object\n\nMessage: ' + err.message + '\n\nServer Response: ' + messageJSON);
} }
@ -358,12 +367,14 @@
setTimeout(queryInstallerStatus, 5000); setTimeout(queryInstallerStatus, 5000);
} else { } else {
$('#loading_indicator').css('display', 'none'); $('#loading_indicator').css('display', 'none');
addMessage('error', addMessage('error', [
[{ {
// eslint-disable-next-line no-undef
title: installLang.title, title: installLang.title,
description: installLang.msg // eslint-disable-next-line no-undef
}] description: installLang.msg,
); },
]);
} }
} }
@ -385,7 +396,7 @@
} }
url = url.substring(0, position) + lookUp + '/installer/status'; url = url.substring(0, position) + lookUp + '/installer/status';
$.getJSON(url, function(data) { $.getJSON(url, data => {
processTimeoutResponse(data.status); processTimeoutResponse(data.status);
}); });
} }
@ -398,7 +409,10 @@
function pollContent(xhReq) { function pollContent(xhReq) {
var messages = xhReq.responseText; var messages = xhReq.responseText;
var msgSeparator = '}\n\n'; var msgSeparator = '}\n\n';
var unprocessed, messageEndIndex, endOfMessageIndex, message; var unprocessed;
var messageEndIndex;
var endOfMessageIndex;
var message;
do { do {
unprocessed = messages.substring(nextReadPosition); unprocessed = messages.substring(nextReadPosition);
@ -466,7 +480,7 @@
currentProgress = Math.floor(progressStart); currentProgress = Math.floor(progressStart);
clearInterval(progressTimer); clearInterval(progressTimer);
progressTimer = setInterval(function() { progressTimer = setInterval(() => {
incrementFiller($progressText, $progressFiller, $progressFillerText, progressLimit); incrementFiller($progressText, $progressFiller, $progressFillerText, progressLimit);
}, 10); }, 10);
} }
@ -487,7 +501,7 @@
function startPolling(xhReq) { function startPolling(xhReq) {
resetPolling(); resetPolling();
transmissionOver = false; transmissionOver = false;
pollTimer = setInterval(function () { pollTimer = setInterval(() => {
pollContent(xhReq); pollContent(xhReq);
}, 250); }, 250);
} }
@ -605,11 +619,13 @@
function interceptFormSubmit($form) { function interceptFormSubmit($form) {
if (!$form.length) { if (!$form.length) {
return; return;
} else if ($form.find('input[name="admin_name"]').length > 0) { }
if ($form.find('input[name="admin_name"]').length > 0) {
setAdminTimezone($form); setAdminTimezone($form);
} }
$form.find(':submit').bind('click', function (event) { $form.find(':submit').bind('click', function(event) {
event.preventDefault(); event.preventDefault();
submitForm($form, $(this)); submitForm($form, $(this));
}); });
@ -623,7 +639,8 @@
function setAdminTimezone($form) { function setAdminTimezone($form) {
// Set admin timezone if it does not exist yet // Set admin timezone if it does not exist yet
if ($form.find('input[name="admin_timezone"]').length === 0) { if ($form.find('input[name="admin_timezone"]').length === 0) {
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone; // eslint-disable-next-line new-cap
const { timeZone } = Intl.DateTimeFormat().resolvedOptions();
// Add timezone as form entry // Add timezone as form entry
const timezoneEntry = $('<input type="hidden" name="admin_timezone" value="' + timeZone + '">'); const timezoneEntry = $('<input type="hidden" name="admin_timezone" value="' + timeZone + '">');

View file

@ -1,16 +1,17 @@
/* global phpbb, plupload, attachInline */ /* global phpbb, plupload, attachInline, activateSubPanel */
/* eslint camelcase: 0 */
/* eslint no-var: 0 */
plupload.addI18n(phpbb.plupload.i18n); plupload.addI18n(phpbb.plupload.i18n);
phpbb.plupload.ids = []; phpbb.plupload.ids = [];
(function($) { // Avoid conflicts with other libraries (function($) { // Avoid conflicts with other libraries
'use strict';
'use strict'; /**
/**
* Set up the uploader. * Set up the uploader.
*/ */
phpbb.plupload.initialize = function() { phpbb.plupload.initialize = function() {
// Initialize the Plupload uploader. // Initialize the Plupload uploader.
phpbb.plupload.uploader.init(); phpbb.plupload.uploader.init();
@ -19,9 +20,9 @@ phpbb.plupload.initialize = function() {
phpbb.plupload.updateMultipartParams(phpbb.plupload.getSerializedData()); phpbb.plupload.updateMultipartParams(phpbb.plupload.getSerializedData());
// Only execute if Plupload initialized successfully. // Only execute if Plupload initialized successfully.
phpbb.plupload.uploader.bind('Init', function() { phpbb.plupload.uploader.bind('Init', () => {
phpbb.plupload.form = $(phpbb.plupload.config.form_hook)[0]; phpbb.plupload.form = $(phpbb.plupload.config.form_hook)[0];
let $attachRowTemplate = $('#attach-row-tpl'); const $attachRowTemplate = $('#attach-row-tpl');
$attachRowTemplate.removeClass('attach-row-tpl'); $attachRowTemplate.removeClass('attach-row-tpl');
phpbb.plupload.rowTpl = $attachRowTemplate[0].outerHTML; phpbb.plupload.rowTpl = $attachRowTemplate[0].outerHTML;
@ -31,7 +32,7 @@ phpbb.plupload.initialize = function() {
$('#attach-panel-multi').show(); $('#attach-panel-multi').show();
}); });
phpbb.plupload.uploader.bind('PostInit', function() { phpbb.plupload.uploader.bind('PostInit', () => {
// Point out the drag-and-drop zone if it's supported. // Point out the drag-and-drop zone if it's supported.
if (phpbb.plupload.uploader.features.dragdrop) { if (phpbb.plupload.uploader.features.dragdrop) {
$('#drag-n-drop-message').show(); $('#drag-n-drop-message').show();
@ -41,49 +42,50 @@ phpbb.plupload.initialize = function() {
if ($('#attach-panel-multi').is(':visible')) { if ($('#attach-panel-multi').is(':visible')) {
phpbb.plupload.uploader.refresh(); phpbb.plupload.uploader.refresh();
} }
$('[data-subpanel="attach-panel"]').one('click', function() {
$('[data-subpanel="attach-panel"]').one('click', () => {
phpbb.plupload.uploader.refresh(); phpbb.plupload.uploader.refresh();
}); });
}); });
}; };
/** /**
* Unsets all elements in the object uploader.settings.multipart_params whose keys * Unsets all elements in the object uploader.settings.multipart_params whose keys
* begin with 'attachment_data[' * begin with 'attachment_data['
*/ */
phpbb.plupload.clearParams = function() { phpbb.plupload.clearParams = function() {
var obj = phpbb.plupload.uploader.settings.multipart_params; var obj = phpbb.plupload.uploader.settings.multipart_params;
for (var key in obj) { for (var key in obj) {
if (!obj.hasOwnProperty(key) || key.indexOf('attachment_data[') !== 0) { if (!Object.prototype.hasOwnProperty.call(obj, key) || key.indexOf('attachment_data[') !== 0) {
continue; continue;
} }
delete phpbb.plupload.uploader.settings.multipart_params[key]; delete phpbb.plupload.uploader.settings.multipart_params[key];
} }
}; };
/** /**
* Update uploader.settings.multipart_params object with new data. * Update uploader.settings.multipart_params object with new data.
* *
* @param {object} obj * @param {object} obj
*/ */
phpbb.plupload.updateMultipartParams = function(obj) { phpbb.plupload.updateMultipartParams = function(obj) {
var settings = phpbb.plupload.uploader.settings; var { settings } = phpbb.plupload.uploader;
settings.multipart_params = $.extend(settings.multipart_params, obj); settings.multipart_params = $.extend(settings.multipart_params, obj);
}; };
/** /**
* Convert the array of attachment objects into an object that PHP would expect as POST data. * Convert the array of attachment objects into an object that PHP would expect as POST data.
* *
* @returns {object} An object in the form 'attachment_data[i][key]': value as * @returns {object} An object in the form 'attachment_data[i][key]': value as
* expected by the server * expected by the server
*/ */
phpbb.plupload.getSerializedData = function() { phpbb.plupload.getSerializedData = function() {
var obj = {}; var obj = {};
for (var i = 0; i < phpbb.plupload.data.length; i++) { for (var i = 0; i < phpbb.plupload.data.length; i++) {
var datum = phpbb.plupload.data[i]; var datum = phpbb.plupload.data[i];
for (var key in datum) { for (var key in datum) {
if (!datum.hasOwnProperty(key)) { if (!Object.prototype.hasOwnProperty.call(datum, key)) {
continue; continue;
} }
@ -97,37 +99,38 @@ phpbb.plupload.getSerializedData = function() {
obj.form_token = $pluploadForm.find('input[type=hidden][name="form_token"]').val(); obj.form_token = $pluploadForm.find('input[type=hidden][name="form_token"]').val();
return obj; return obj;
}; };
/** /**
* Get the index from the phpbb.plupload.data array where the given * Get the index from the phpbb.plupload.data array where the given
* attachment id appears. * attachment id appears.
* *
* @param {int} attachId The attachment id of the file. * @param {int} attachId The attachment id of the file.
* @returns {bool|int} Index of the file if exists, otherwise false. * @returns {bool|int} Index of the file if exists, otherwise false.
*/ */
phpbb.plupload.getIndex = function(attachId) { phpbb.plupload.getIndex = function(attachId) {
var index = $.inArray(Number(attachId), phpbb.plupload.ids); var index = $.inArray(Number(attachId), phpbb.plupload.ids);
return (index !== -1) ? index : false; return index === -1 ? false : index;
}; };
/** /**
* Set the data in phpbb.plupload.data and phpbb.plupload.ids arrays. * Set the data in phpbb.plupload.data and phpbb.plupload.ids arrays.
* *
* @param {Array} data Array containing the new data to use. In the form of * @param {Array} data Array containing the new data to use. In the form of
* array(index => object(property: value). Requires attach_id to be one of the object properties. * array(index => object(property: value). Requires attach_id to be one of the object properties.
*/ */
phpbb.plupload.setData = function(data) { phpbb.plupload.setData = function(data) {
// Make sure that the array keys are reset. // Make sure that the array keys are reset.
phpbb.plupload.ids = phpbb.plupload.data = []; phpbb.plupload.ids = [];
phpbb.plupload.data = [];
phpbb.plupload.data = data; phpbb.plupload.data = data;
for (var i = 0; i < data.length; i++) { for (var i = 0; i < data.length; i++) {
phpbb.plupload.ids.push(Number(data[i].attach_id)); phpbb.plupload.ids.push(Number(data[i].attach_id));
} }
}; };
/** /**
* Update the attachment data in the HTML and the phpbb & phpbb.plupload objects. * Update the attachment data in the HTML and the phpbb & phpbb.plupload objects.
* *
* @param {Array} data Array containing the new data to use. * @param {Array} data Array containing the new data to use.
@ -135,27 +138,26 @@ phpbb.plupload.setData = function(data) {
* @param {int} index The index from phpbb.plupload_ids that was affected by the action. * @param {int} index The index from phpbb.plupload_ids that was affected by the action.
* @param {Array} downloadUrl Optional array of download urls to update. * @param {Array} downloadUrl Optional array of download urls to update.
*/ */
phpbb.plupload.update = function(data, action, index, downloadUrl) { phpbb.plupload.update = function(data, action, index, downloadUrl) {
phpbb.plupload.updateBbcode(action, index); phpbb.plupload.updateBbcode(action, index);
phpbb.plupload.setData(data); phpbb.plupload.setData(data);
phpbb.plupload.updateRows(downloadUrl); phpbb.plupload.updateRows(downloadUrl);
phpbb.plupload.clearParams(); phpbb.plupload.clearParams();
phpbb.plupload.updateMultipartParams(phpbb.plupload.getSerializedData()); phpbb.plupload.updateMultipartParams(phpbb.plupload.getSerializedData());
}; };
/** /**
* Update the relevant elements and hidden data for all attachments. * Update the relevant elements and hidden data for all attachments.
* *
* @param {Array} downloadUrl Optional array of download urls to update. * @param {Array} downloadUrl Optional array of download urls to update.
*/ */
phpbb.plupload.updateRows = function(downloadUrl) { phpbb.plupload.updateRows = function(downloadUrl) {
for (var i = 0; i < phpbb.plupload.ids.length; i++) { for (var i = 0; i < phpbb.plupload.ids.length; i++) {
phpbb.plupload.updateRow(i, downloadUrl); phpbb.plupload.updateRow(i, downloadUrl);
} }
}; };
/** /**
* Insert a row for a new attachment. This expects an HTML snippet in the HTML * Insert a row for a new attachment. This expects an HTML snippet in the HTML
* using the id "attach-row-tpl" to be present. This snippet is cloned and the * using the id "attach-row-tpl" to be present. This snippet is cloned and the
* data for the file inserted into it. The row is then appended or prepended to * data for the file inserted into it. The row is then appended or prepended to
@ -163,7 +165,7 @@ phpbb.plupload.updateRows = function(downloadUrl) {
* *
* @param {object} file Plupload file object for the new attachment. * @param {object} file Plupload file object for the new attachment.
*/ */
phpbb.plupload.insertRow = function(file) { phpbb.plupload.insertRow = function(file) {
var row = $(phpbb.plupload.rowTpl); var row = $(phpbb.plupload.rowTpl);
row.attr('id', file.id); row.attr('id', file.id);
@ -175,22 +177,22 @@ phpbb.plupload.insertRow = function(file) {
} else { } else {
$('#file-list').append(row); $('#file-list').append(row);
} }
}; };
/** /**
* Update the relevant elements and hidden data for an attachment. * Update the relevant elements and hidden data for an attachment.
* *
* @param {int} index The index from phpbb.plupload.ids of the attachment to edit. * @param {int} index The index from phpbb.plupload.ids of the attachment to edit.
* @param {Array} downloadUrl Optional array of download urls to update. * @param {Array} downloadUrl Optional array of download urls to update.
*/ */
phpbb.plupload.updateRow = function(index, downloadUrl) { phpbb.plupload.updateRow = function(index, downloadUrl) {
var attach = phpbb.plupload.data[index], var attach = phpbb.plupload.data[index];
row = $('[data-attach-id="' + attach.attach_id + '"]'); var row = $('[data-attach-id="' + attach.attach_id + '"]');
// Add the link to the file // Add the link to the file
if (typeof downloadUrl !== 'undefined' && typeof downloadUrl[index] !== 'undefined') { if (typeof downloadUrl !== 'undefined' && typeof downloadUrl[index] !== 'undefined') {
var url = downloadUrl[index].replace('&amp;', '&'), var url = downloadUrl[index].replace('&amp;', '&');
link = $('<a></a>'); var link = $('<a></a>');
link.attr('href', url).html(attach.real_filename); link.attr('href', url).html(attach.real_filename);
row.find('.file-name').html(link); row.find('.file-name').html(link);
@ -198,21 +200,21 @@ phpbb.plupload.updateRow = function(index, downloadUrl) {
row.find('textarea').attr('name', 'comment_list[' + index + ']'); row.find('textarea').attr('name', 'comment_list[' + index + ']');
phpbb.plupload.updateHiddenData(row, attach, index); phpbb.plupload.updateHiddenData(row, attach, index);
}; };
/** /**
* Update hidden input data for an attachment. * Update hidden input data for an attachment.
* *
* @param {object} row jQuery object for the attachment row. * @param {object} row jQuery object for the attachment row.
* @param {object} attach Attachment data object from phpbb.plupload.data * @param {object} attach Attachment data object from phpbb.plupload.data
* @param {int} index Attachment index from phpbb.plupload.ids * @param {int} index Attachment index from phpbb.plupload.ids
*/ */
phpbb.plupload.updateHiddenData = function(row, attach, index) { phpbb.plupload.updateHiddenData = function(row, attach, index) {
row.find('input[type="hidden"]').remove(); row.find('input[type="hidden"]').remove();
for (var key in attach) { for (var key in attach) {
if (!attach.hasOwnProperty(key)) { if (!Object.prototype.hasOwnProperty.call(attach, key)) {
return; continue;
} }
var input = $('<input />') var input = $('<input />')
@ -221,9 +223,9 @@ phpbb.plupload.updateHiddenData = function(row, attach, index) {
.attr('value', attach[key]); .attr('value', attach[key]);
$(row).append(input); $(row).append(input);
} }
}; };
/** /**
* Deleting a file removes it from the queue and fires an AJAX event to the * Deleting a file removes it from the queue and fires an AJAX event to the
* server to tell it to remove the temporary attachment. The server * server to tell it to remove the temporary attachment. The server
* responds with the updated attachment data list so that any future * responds with the updated attachment data list so that any future
@ -232,13 +234,13 @@ phpbb.plupload.updateHiddenData = function(row, attach, index) {
* @param {object} row jQuery object for the attachment row. * @param {object} row jQuery object for the attachment row.
* @param {int} attachId Attachment id of the file to be removed. * @param {int} attachId Attachment id of the file to be removed.
*/ */
phpbb.plupload.deleteFile = function(row, attachId) { phpbb.plupload.deleteFile = function(row, attachId) {
// If there's no attach id, then the file hasn't been uploaded. Simply delete the row. // If there's no attach id, then the file hasn't been uploaded. Simply delete the row.
if (typeof attachId === 'undefined') { if (typeof attachId === 'undefined') {
var file = phpbb.plupload.uploader.getFile(row.attr('id')); var file = phpbb.plupload.uploader.getFile(row.attr('id'));
phpbb.plupload.uploader.removeFile(file); phpbb.plupload.uploader.removeFile(file);
row.slideUp(100, function() { row.slideUp(100, () => {
row.remove(); row.remove();
phpbb.plupload.hideEmptyList(); phpbb.plupload.hideEmptyList();
}); });
@ -250,6 +252,7 @@ phpbb.plupload.deleteFile = function(row, attachId) {
if (index === false) { if (index === false) {
return; return;
} }
var fields = {}; var fields = {};
fields['delete_file[' + index + ']'] = 1; fields['delete_file[' + index + ']'] = 1;
@ -289,7 +292,8 @@ phpbb.plupload.deleteFile = function(row, attachId) {
var file = phpbb.plupload.uploader.getFile(row.attr('id')); var file = phpbb.plupload.uploader.getFile(row.attr('id'));
phpbb.plupload.uploader.removeFile(file); phpbb.plupload.uploader.removeFile(file);
} }
row.slideUp(100, function() {
row.slideUp(100, () => {
row.remove(); row.remove();
// Hide the file list if it's empty now. // Hide the file list if it's empty now.
phpbb.plupload.hideEmptyList(); phpbb.plupload.hideEmptyList();
@ -300,22 +304,22 @@ phpbb.plupload.deleteFile = function(row, attachId) {
$.ajax(phpbb.plupload.config.url, { $.ajax(phpbb.plupload.config.url, {
type: 'POST', type: 'POST',
data: $.extend(fields, phpbb.plupload.getSerializedData()), data: $.extend(fields, phpbb.plupload.getSerializedData()),
headers: phpbb.plupload.config.headers headers: phpbb.plupload.config.headers,
}) })
.always(always) .always(always)
.done(done); .done(done);
}; };
/** /**
* Check the attachment list and hide its container if it's empty. * Check the attachment list and hide its container if it's empty.
*/ */
phpbb.plupload.hideEmptyList = function() { phpbb.plupload.hideEmptyList = function() {
if (!$('#file-list').children().length) { if (!$('#file-list').children().length) {
$('#file-list-container').slideUp(100); $('#file-list-container').slideUp(100);
} }
}; };
/** /**
* Update the indices used in inline attachment bbcodes. This ensures that the * Update the indices used in inline attachment bbcodes. This ensures that the
* bbcodes correspond to the correct file after a file is added or removed. * bbcodes correspond to the correct file after a file is added or removed.
* This should be called before the phpbb.plupload,data and phpbb.plupload.ids * This should be called before the phpbb.plupload,data and phpbb.plupload.ids
@ -324,10 +328,10 @@ phpbb.plupload.hideEmptyList = function() {
* @param {string} action The action that occurred -- either "addition" or "removal" * @param {string} action The action that occurred -- either "addition" or "removal"
* @param {int} index The index of the attachment from phpbb.plupload.ids that was affected. * @param {int} index The index of the attachment from phpbb.plupload.ids that was affected.
*/ */
phpbb.plupload.updateBbcode = function(action, index) { phpbb.plupload.updateBbcode = function(action, index) {
var textarea = $('#message', phpbb.plupload.form), const textarea = $('#message', phpbb.plupload.form);
text = textarea.val(), var text = textarea.val();
removal = (action === 'removal'); var removal = (action === 'removal');
// Return if the bbcode isn't used at all. // Return if the bbcode isn't used at all.
if (text.indexOf('[attachment=') === -1) { if (text.indexOf('[attachment=') === -1) {
@ -336,11 +340,12 @@ phpbb.plupload.updateBbcode = function(action, index) {
function runUpdate(i) { function runUpdate(i) {
var regex = new RegExp('\\[attachment=' + i + '\\](.*?)\\[\\/attachment\\]', 'g'); var regex = new RegExp('\\[attachment=' + i + '\\](.*?)\\[\\/attachment\\]', 'g');
text = text.replace(regex, function updateBbcode(_, fileName) { text = text.replace(regex, (_, fileName) => {
// Remove the bbcode if the file was removed. // Remove the bbcode if the file was removed.
if (removal && index === i) { if (removal && index === i) {
return ''; return '';
} }
var newIndex = i + ((removal) ? -1 : 1); var newIndex = i + ((removal) ? -1 : 1);
return '[attachment=' + newIndex + ']' + fileName + '[/attachment]'; return '[attachment=' + newIndex + ']' + fileName + '[/attachment]';
}); });
@ -360,9 +365,9 @@ phpbb.plupload.updateBbcode = function(action, index) {
} }
textarea.val(text); textarea.val(text);
}; };
/** /**
* Get Plupload file objects based on their upload status. * Get Plupload file objects based on their upload status.
* *
* @param {int} status Plupload status - plupload.DONE, plupload.FAILED, * @param {int} status Plupload status - plupload.DONE, plupload.FAILED,
@ -370,25 +375,25 @@ phpbb.plupload.updateBbcode = function(action, index) {
* *
* @returns {Array} The Plupload file objects matching the status. * @returns {Array} The Plupload file objects matching the status.
*/ */
phpbb.plupload.getFilesByStatus = function(status) { phpbb.plupload.getFilesByStatus = function(status) {
var files = []; var files = [];
$.each(phpbb.plupload.uploader.files, function(i, file) { $.each(phpbb.plupload.uploader.files, (i, file) => {
if (file.status === status) { if (file.status === status) {
files.push(file); files.push(file);
} }
}); });
return files; return files;
}; };
/** /**
* Check whether the user has reached the maximun number of files that he's allowed * Check whether the user has reached the maximun number of files that he's allowed
* to upload. If so, disables the uploader and marks the queued files as failed. Otherwise * to upload. If so, disables the uploader and marks the queued files as failed. Otherwise
* makes sure that the uploader is enabled. * makes sure that the uploader is enabled.
* *
* @returns {bool} True if the limit has been reached. False if otherwise. * @returns {bool} True if the limit has been reached. False if otherwise.
*/ */
phpbb.plupload.handleMaxFilesReached = function() { phpbb.plupload.handleMaxFilesReached = function() {
// If there is no limit, the user is an admin or moderator. // If there is no limit, the user is an admin or moderator.
if (!phpbb.plupload.maxFiles) { if (!phpbb.plupload.maxFiles) {
return false; return false;
@ -402,81 +407,87 @@ phpbb.plupload.handleMaxFilesReached = function() {
phpbb.plupload.uploader.trigger('Error', { message: phpbb.plupload.lang.TOO_MANY_ATTACHMENTS }); phpbb.plupload.uploader.trigger('Error', { message: phpbb.plupload.lang.TOO_MANY_ATTACHMENTS });
return true; return true;
} else if (phpbb.plupload.maxFiles > phpbb.plupload.ids.length) { }
if (phpbb.plupload.maxFiles > phpbb.plupload.ids.length) {
// Enable the uploader if the user is under the limit // Enable the uploader if the user is under the limit
phpbb.plupload.enableUploader(); phpbb.plupload.enableUploader();
} }
return false;
};
/** return false;
};
/**
* Disable the uploader * Disable the uploader
*/ */
phpbb.plupload.disableUploader = function() { phpbb.plupload.disableUploader = function() {
$('#add_files').addClass('disabled'); $('#add_files').addClass('disabled');
phpbb.plupload.uploader.disableBrowse(); phpbb.plupload.uploader.disableBrowse();
}; };
/** /**
* Enable the uploader * Enable the uploader
*/ */
phpbb.plupload.enableUploader = function() { phpbb.plupload.enableUploader = function() {
$('#add_files').removeClass('disabled'); $('#add_files').removeClass('disabled');
phpbb.plupload.uploader.disableBrowse(false); phpbb.plupload.uploader.disableBrowse(false);
}; };
/** /**
* Mark all queued files as failed. * Mark all queued files as failed.
* *
* @param {string} error Error message to present to the user. * @param {string} error Error message to present to the user.
*/ */
phpbb.plupload.markQueuedFailed = function(error) { phpbb.plupload.markQueuedFailed = function(error) {
var files = phpbb.plupload.getFilesByStatus(plupload.QUEUED); var files = phpbb.plupload.getFilesByStatus(plupload.QUEUED);
$.each(files, function(i, file) { $.each(files, (i, file) => {
$('#' + file.id).find('.file-progress').hide(); $('#' + file.id).find('.file-progress').hide();
phpbb.plupload.fileError(file, error); phpbb.plupload.fileError(file, error);
}); });
}; };
/** /**
* Marks a file as failed and sets the error message for it. * Marks a file as failed and sets the error message for it.
* *
* @param {object} file Plupload file object that failed. * @param {object} file Plupload file object that failed.
* @param {string} error Error message to present to the user. * @param {string} error Error message to present to the user.
*/ */
phpbb.plupload.fileError = function(file, error) { phpbb.plupload.fileError = function(file, error) {
file.status = plupload.FAILED; file.status = plupload.FAILED;
file.error = error; file.error = error;
$('#' + file.id).find('.file-status') $('#' + file.id).find('.file-status')
.addClass('file-error') .addClass('file-error')
.attr({ .attr({
'data-error-title': phpbb.plupload.lang.ERROR, 'data-error-title': phpbb.plupload.lang.ERROR,
'data-error-message': error 'data-error-message': error,
}); });
}; };
/**
/**
* Set up the Plupload object and get some basic data. * Set up the Plupload object and get some basic data.
*/ */
phpbb.plupload.uploader = new plupload.Uploader(phpbb.plupload.config); phpbb.plupload.uploader = new plupload.Uploader(phpbb.plupload.config);
phpbb.plupload.initialize(); phpbb.plupload.initialize();
/** /**
* Add a file filter to check for max file sizes per mime type. * Add a file filter to check for max file sizes per mime type.
*/ */
plupload.addFileFilter('mime_types_max_file_size', function(types, file, callback) { plupload.addFileFilter('mime_types_max_file_size', (types, file, callback) => {
if (file.size !== 'undefined') { if (file.size !== 'undefined') {
$(types).each(function(i, type) { $(types).each((i, type) => {
let extensions = [], const extensions = [];
extsArray = type.extensions.split(','); const extsArray = type.extensions.split(',');
$(extsArray).each(function(i, extension) { $(extsArray).each((i, extension) => {
/^\s*\*\s*$/.test(extension) ? extensions.push("\\.*") : extensions.push("\\." + extension.replace(new RegExp("[" + "/^$.*+?|()[]{}\\".replace(/./g, "\\$&") + "]", "g"), "\\$&")); if (/^\s*\*\s*$/.test(extension)) {
extensions.push('\\.*');
} else {
extensions.push('\\.' + extension.replace(new RegExp('[' + '/^$.*+?|()[]{}\\'.replace(/./g, '\\$&') + ']', 'g'), '\\$&'));
}
}); });
let regex = new RegExp("(" + extensions.join("|") + ")$", "i"); const regex = new RegExp('(' + extensions.join('|') + ')$', 'i');
if (regex.test(file.name)) { if (regex.test(file.name)) {
if (type.max_file_size !== 'undefined' && type.max_file_size) { if (type.max_file_size !== 'undefined' && type.max_file_size) {
@ -484,7 +495,7 @@ plupload.addFileFilter('mime_types_max_file_size', function(types, file, callbac
phpbb.plupload.uploader.trigger('Error', { phpbb.plupload.uploader.trigger('Error', {
code: plupload.FILE_SIZE_ERROR, code: plupload.FILE_SIZE_ERROR,
message: plupload.translate('File size error.'), message: plupload.translate('File size error.'),
file: file file,
}); });
callback(false); callback(false);
@ -499,44 +510,44 @@ plupload.addFileFilter('mime_types_max_file_size', function(types, file, callbac
} }
}); });
} }
}); });
var $fileList = $('#file-list'); var $fileList = $('#file-list');
/** /**
* Insert inline attachment bbcode. * Insert inline attachment bbcode.
*/ */
$fileList.on('click', '.file-inline-bbcode', function(e) { $fileList.on('click', '.file-inline-bbcode', function(e) {
var attachId = $(this).parents('.attach-row').attr('data-attach-id'), var attachId = $(this).parents('.attach-row').attr('data-attach-id');
index = phpbb.plupload.getIndex(attachId); var index = phpbb.plupload.getIndex(attachId);
attachInline(index, phpbb.plupload.data[index].real_filename); attachInline(index, phpbb.plupload.data[index].real_filename);
e.preventDefault(); e.preventDefault();
}); });
/** /**
* Delete a file. * Delete a file.
*/ */
$fileList.on('click', '.file-delete', function(e) { $fileList.on('click', '.file-delete', function(e) {
var row = $(this).parents('.attach-row'), var row = $(this).parents('.attach-row');
attachId = row.attr('data-attach-id'); var attachId = row.attr('data-attach-id');
phpbb.plupload.deleteFile(row, attachId); phpbb.plupload.deleteFile(row, attachId);
e.preventDefault(); e.preventDefault();
}); });
/** /**
* Display the error message for a particular file when the error icon is clicked. * Display the error message for a particular file when the error icon is clicked.
*/ */
$fileList.on('click', '.file-error', function(e) { $fileList.on('click', '.file-error', function(e) {
phpbb.alert($(this).attr('data-error-title'), $(this).attr('data-error-message')); phpbb.alert($(this).attr('data-error-title'), $(this).attr('data-error-message'));
e.preventDefault(); e.preventDefault();
}); });
/** /**
* Fires when an error occurs. * Fires when an error occurs.
*/ */
phpbb.plupload.uploader.bind('Error', function(up, error) { phpbb.plupload.uploader.bind('Error', (up, error) => {
error.file.name = plupload.xmlEncode(error.file.name); error.file.name = plupload.xmlEncode(error.file.name);
// The error message that Plupload provides for these is vague, so we'll be more specific. // The error message that Plupload provides for these is vague, so we'll be more specific.
@ -545,10 +556,11 @@ phpbb.plupload.uploader.bind('Error', function(up, error) {
} else if (error.code === plupload.FILE_SIZE_ERROR) { } else if (error.code === plupload.FILE_SIZE_ERROR) {
error.message = plupload.translate('File too large:') + ' ' + error.file.name; error.message = plupload.translate('File too large:') + ' ' + error.file.name;
} }
phpbb.alert(phpbb.plupload.lang.ERROR, error.message);
});
/** phpbb.alert(phpbb.plupload.lang.ERROR, error.message);
});
/**
* Fires before a given file is about to be uploaded. This allows us to * Fires before a given file is about to be uploaded. This allows us to
* send the real filename along with the chunk. This is necessary because * send the real filename along with the chunk. This is necessary because
* for some reason the filename is set to 'blob' whenever a file is chunked * for some reason the filename is set to 'blob' whenever a file is chunked
@ -556,15 +568,15 @@ phpbb.plupload.uploader.bind('Error', function(up, error) {
* @param {object} up The plupload.Uploader object * @param {object} up The plupload.Uploader object
* @param {object} file The plupload.File object that is about to be uploaded * @param {object} file The plupload.File object that is about to be uploaded
*/ */
phpbb.plupload.uploader.bind('BeforeUpload', function(up, file) { phpbb.plupload.uploader.bind('BeforeUpload', (up, file) => {
if (phpbb.plupload.handleMaxFilesReached()) { if (phpbb.plupload.handleMaxFilesReached()) {
return; return;
} }
phpbb.plupload.updateMultipartParams({ real_filename: file.name }); phpbb.plupload.updateMultipartParams({ real_filename: file.name });
}); });
/** /**
* Fired when a single chunk of any given file is uploaded. This parses the * Fired when a single chunk of any given file is uploaded. This parses the
* response from the server and checks for an error. If an error occurs it * response from the server and checks for an error. If an error occurs it
* is reported to the user and the upload of this particular file is halted * is reported to the user and the upload of this particular file is halted
@ -574,7 +586,7 @@ phpbb.plupload.uploader.bind('BeforeUpload', function(up, file) {
* been uploaded * been uploaded
* @param {object} response The response object from the server * @param {object} response The response object from the server
*/ */
phpbb.plupload.uploader.bind('ChunkUploaded', function(up, file, response) { phpbb.plupload.uploader.bind('ChunkUploaded', (up, file, response) => {
if (response.chunk >= response.chunks - 1) { if (response.chunk >= response.chunks - 1) {
return; return;
} }
@ -582,14 +594,14 @@ phpbb.plupload.uploader.bind('ChunkUploaded', function(up, file, response) {
var json = {}; var json = {};
try { try {
json = $.parseJSON(response.response); json = $.parseJSON(response.response);
} catch (e) { } catch {
file.status = plupload.FAILED; file.status = plupload.FAILED;
up.trigger('FileUploaded', file, { up.trigger('FileUploaded', file, {
response: JSON.stringify({ response: JSON.stringify({
error: { error: {
message: 'Error parsing server response.' message: 'Error parsing server response.',
} },
}) }),
}); });
} }
@ -603,17 +615,17 @@ phpbb.plupload.uploader.bind('ChunkUploaded', function(up, file, response) {
up.trigger('FileUploaded', file, { up.trigger('FileUploaded', file, {
response: JSON.stringify({ response: JSON.stringify({
error: { error: {
message: json.error.message message: json.error.message,
} },
}) }),
}); });
} }
}); });
/** /**
* Fires when files are added to the queue. * Fires when files are added to the queue.
*/ */
phpbb.plupload.uploader.bind('FilesAdded', function(up, files) { phpbb.plupload.uploader.bind('FilesAdded', (up, files) => {
// Prevent unnecessary requests to the server if the user already uploaded // Prevent unnecessary requests to the server if the user already uploaded
// the maximum number of files allowed. // the maximum number of files allowed.
if (phpbb.plupload.handleMaxFilesReached()) { if (phpbb.plupload.handleMaxFilesReached()) {
@ -631,11 +643,11 @@ phpbb.plupload.uploader.bind('FilesAdded', function(up, files) {
$fileListContainer.show(100); $fileListContainer.show(100);
} }
$.each(files, function(i, file) { $.each(files, (i, file) => {
phpbb.plupload.insertRow(file); phpbb.plupload.insertRow(file);
}); });
up.bind('UploadProgress', function(up, file) { up.bind('UploadProgress', (up, file) => {
$('.file-progress-bar', '#' + file.id).css('width', file.percent + '%'); $('.file-progress-bar', '#' + file.id).css('width', file.percent + '%');
$('#file-total-progress-bar').css('width', up.total.percent + '%'); $('#file-total-progress-bar').css('width', up.total.percent + '%');
}); });
@ -645,10 +657,9 @@ phpbb.plupload.uploader.bind('FilesAdded', function(up, files) {
// Start uploading the files once the user has selected them. // Start uploading the files once the user has selected them.
up.start(); up.start();
}); });
/**
/**
* Fires when an entire file has been uploaded. It checks for errors * Fires when an entire file has been uploaded. It checks for errors
* returned by the server otherwise parses the list of attachment data and * returned by the server otherwise parses the list of attachment data and
* appends it to the next file upload so that the server can maintain state * appends it to the next file upload so that the server can maintain state
@ -659,17 +670,17 @@ phpbb.plupload.uploader.bind('FilesAdded', function(up, files) {
* uploaded * uploaded
* @param {string} response The response string from the server * @param {string} response The response string from the server
*/ */
phpbb.plupload.uploader.bind('FileUploaded', function(up, file, response) { phpbb.plupload.uploader.bind('FileUploaded', (up, file, response) => {
var json = {}, var json = {};
row = $('#' + file.id), var row = $('#' + file.id);
error; var error;
// Hide the progress indicator. // Hide the progress indicator.
row.find('.file-progress').hide(); row.find('.file-progress').hide();
try { try {
json = JSON.parse(response.response); json = JSON.parse(response.response);
} catch (e) { } catch {
error = 'Error parsing server response.'; error = 'Error parsing server response.';
} }
@ -692,16 +703,16 @@ phpbb.plupload.uploader.bind('FileUploaded', function(up, file, response) {
row.attr('data-attach-id', file.attachment_data.attach_id); row.attr('data-attach-id', file.attachment_data.attach_id);
row.find('.file-inline-bbcode').show(); row.find('.file-inline-bbcode').show();
row.find('.file-status').addClass('file-uploaded'); row.find('.file-status').addClass('file-uploaded');
phpbb.plupload.update(json.data, 'addition', 0, [json.download_url]); phpbb.plupload.update(json.data, 'addition', 0, [ json.download_url ]);
} }
}); });
/** /**
* Fires when the entire queue of files have been uploaded. * Fires when the entire queue of files have been uploaded.
*/ */
phpbb.plupload.uploader.bind('UploadComplete', function() { phpbb.plupload.uploader.bind('UploadComplete', () => {
// Hide the progress bar // Hide the progress bar
setTimeout(function() { setTimeout(() => {
$('#file-total-progress-bar').fadeOut(500, function() { $('#file-total-progress-bar').fadeOut(500, function() {
$(this).css('width', 0).show(); $(this).css('width', 0).show();
}); });
@ -709,6 +720,5 @@ phpbb.plupload.uploader.bind('UploadComplete', function() {
// Re-enable the uploader // Re-enable the uploader
phpbb.plupload.enableUploader(); phpbb.plupload.enableUploader();
}); });
})(jQuery); // Avoid conflicts with other libraries })(jQuery); // Avoid conflicts with other libraries

View file

@ -161,6 +161,16 @@ class environment extends \Twig\Environment
return $this->assets_bag; return $this->assets_bag;
} }
/**
* Gets the event dispatcher instance
*
* @return dispatcher_interface
*/
public function get_phpbb_dispatcher()
{
return $this->phpbb_dispatcher;
}
/** /**
* Get the namespace look up order * Get the namespace look up order
* *

View file

@ -24,9 +24,13 @@ class event extends \Twig\Node\Node
/** @var \phpbb\template\twig\environment */ /** @var \phpbb\template\twig\environment */
protected $environment; protected $environment;
public function __construct(\Twig\Node\Expression\AbstractExpression $expr, \phpbb\template\twig\environment $environment, $lineno, $tag = null) /** @var array */
protected $template_event_priority_array;
public function __construct(\Twig\Node\Expression\AbstractExpression $expr, \phpbb\template\twig\environment $environment, $lineno, $tag = null, $template_event_priority_array = [])
{ {
$this->environment = $environment; $this->environment = $environment;
$this->template_event_priority_array = $template_event_priority_array;
parent::__construct(array('expr' => $expr), array(), $lineno, $tag); parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
} }
@ -42,10 +46,20 @@ class event extends \Twig\Node\Node
$location = $this->listener_directory . $this->getNode('expr')->getAttribute('name'); $location = $this->listener_directory . $this->getNode('expr')->getAttribute('name');
$template_event_listeners = [];
// Group and sort extension template events in according to their priority (0 by default if not set)
foreach ($this->environment->get_phpbb_extensions() as $ext_namespace => $ext_path) foreach ($this->environment->get_phpbb_extensions() as $ext_namespace => $ext_path)
{ {
$ext_namespace = str_replace('/', '_', $ext_namespace); $ext_namespace = str_replace('/', '_', $ext_namespace);
$priority_key = intval($this->template_event_priority_array[$ext_namespace][$location] ?? 0);
$template_event_listeners[$priority_key][] = $ext_namespace;
}
krsort($template_event_listeners);
$template_event_listeners = array_merge(...$template_event_listeners);
foreach ($template_event_listeners as $ext_namespace)
{
if ($this->environment->isDebug()) if ($this->environment->isDebug())
{ {
// If debug mode is enabled, lets check for new/removed EVENT // If debug mode is enabled, lets check for new/removed EVENT
@ -54,8 +68,7 @@ class event extends \Twig\Node\Node
// purge the cache when a new event template file is added) // purge the cache when a new event template file is added)
$compiler $compiler
->write("if (\$this->env->getLoader()->exists('@{$ext_namespace}/{$location}.html')) {\n") ->write("if (\$this->env->getLoader()->exists('@{$ext_namespace}/{$location}.html')) {\n")
->indent() ->indent();
;
} }
if ($this->environment->isDebug() || $this->environment->getLoader()->exists('@' . $ext_namespace . '/' . $location . '.html')) if ($this->environment->isDebug() || $this->environment->getLoader()->exists('@' . $ext_namespace . '/' . $location . '.html'))
@ -66,16 +79,14 @@ class event extends \Twig\Node\Node
// We set the namespace lookup order to be this extension first, then the main path // We set the namespace lookup order to be this extension first, then the main path
->write("\$this->env->setNamespaceLookUpOrder(array('{$ext_namespace}', '__main__'));\n") ->write("\$this->env->setNamespaceLookUpOrder(array('{$ext_namespace}', '__main__'));\n")
->write("\$this->env->loadTemplate(\$this->env->getTemplateClass('@{$ext_namespace}/{$location}.html'), '@{$ext_namespace}/{$location}.html')->display(\$context);\n") ->write("\$this->env->loadTemplate(\$this->env->getTemplateClass('@{$ext_namespace}/{$location}.html'), '@{$ext_namespace}/{$location}.html')->display(\$context);\n")
->write("\$this->env->setNamespaceLookUpOrder(\$previous_look_up_order);\n") ->write("\$this->env->setNamespaceLookUpOrder(\$previous_look_up_order);\n");
;
} }
if ($this->environment->isDebug()) if ($this->environment->isDebug())
{ {
$compiler $compiler
->outdent() ->outdent()
->write("}\n\n") ->write("}\n\n");
;
} }
} }
} }

View file

@ -18,6 +18,9 @@ class event extends \Twig\TokenParser\AbstractTokenParser
/** @var \phpbb\template\twig\environment */ /** @var \phpbb\template\twig\environment */
protected $environment; protected $environment;
/** @var array */
protected $template_event_priority_array;
/** /**
* Constructor * Constructor
* *
@ -26,6 +29,25 @@ class event extends \Twig\TokenParser\AbstractTokenParser
public function __construct(\phpbb\template\twig\environment $environment) public function __construct(\phpbb\template\twig\environment $environment)
{ {
$this->environment = $environment; $this->environment = $environment;
$phpbb_dispatcher = $this->environment->get_phpbb_dispatcher();
$template_event_priority_array = [];
/**
* Allows assigning priority to template event listeners
*
* @event core.twig_event_tokenparser_constructor
* @var array template_event_priority_array Array with template event priority assignments per extension namespace
*
* @since 4.0.0-a1
*/
if ($phpbb_dispatcher)
{
$vars = ['template_event_priority_array'];
extract($phpbb_dispatcher->trigger_event('core.twig_event_tokenparser_constructor', compact($vars)));
}
$this->template_event_priority_array = $template_event_priority_array;
unset($template_event_priority_array);
} }
/** /**
@ -42,7 +64,7 @@ class event extends \Twig\TokenParser\AbstractTokenParser
$stream = $this->parser->getStream(); $stream = $this->parser->getStream();
$stream->expect(\Twig\Token::BLOCK_END_TYPE); $stream->expect(\Twig\Token::BLOCK_END_TYPE);
return new \phpbb\template\twig\node\event($expr, $this->environment, $token->getLine(), $this->getTag()); return new \phpbb\template\twig\node\event($expr, $this->environment, $token->getLine(), $this->getTag(), $this->template_event_priority_array);
} }
/** /**

View file

@ -1,23 +1,24 @@
/* global phpbb */ /* global phpbb */
/* eslint camelcase: 0 */
/* eslint no-var: 0 */
(function($) { // Avoid conflicts with other libraries (function($) { // Avoid conflicts with other libraries
'use strict';
'use strict'; // This callback will mark all forum icons read
phpbb.addAjaxCallback('mark_forums_read', function(res) {
// This callback will mark all forum icons read
phpbb.addAjaxCallback('mark_forums_read', function(res) {
var readTitle = res.NO_UNREAD_POSTS; var readTitle = res.NO_UNREAD_POSTS;
var unreadTitle = res.UNREAD_POSTS; var unreadTitle = res.UNREAD_POSTS;
var iconsArray = { var iconsArray = {
forum_unread: 'forum_read', forum_unread: 'forum_read',
forum_unread_subforum: 'forum_read_subforum', forum_unread_subforum: 'forum_read_subforum',
forum_unread_locked: 'forum_read_locked' forum_unread_locked: 'forum_read_locked',
}; };
$('li.row').find('dl[class*="forum_unread"]').each(function() { $('li.row').find('dl[class*="forum_unread"]').each(function() {
var $this = $(this); var $this = $(this);
$.each(iconsArray, function(unreadClass, readClass) { $.each(iconsArray, (unreadClass, readClass) => {
if ($this.hasClass(unreadClass)) { if ($this.hasClass(unreadClass)) {
$this.removeClass(unreadClass).addClass(readClass); $this.removeClass(unreadClass).addClass(readClass);
} }
@ -37,25 +38,24 @@ phpbb.addAjaxCallback('mark_forums_read', function(res) {
$('[data-ajax="mark_forums_read"]').attr('href', res.U_MARK_FORUMS); $('[data-ajax="mark_forums_read"]').attr('href', res.U_MARK_FORUMS);
phpbb.closeDarkenWrapper(3000); phpbb.closeDarkenWrapper(3000);
}); });
/** /**
* This callback will mark all topic icons read * This callback will mark all topic icons read
* *
* @param {bool} [update_topic_links=true] Whether "Mark topics read" links * @param {bool} [update_topic_links=true] Whether "Mark topics read" links
* should be updated. Defaults to true. * should be updated. Defaults to true.
*/ */
phpbb.addAjaxCallback('mark_topics_read', function(res, updateTopicLinks) { phpbb.addAjaxCallback('mark_topics_read', (res, updateTopicLinks) => {
var readTitle = res.NO_UNREAD_POSTS; var readTitle = res.NO_UNREAD_POSTS;
var unreadTitle = res.UNREAD_POSTS; var unreadTitle = res.UNREAD_POSTS;
var iconsArray = { var iconsArray = {
global_unread: 'global_read', global_unread: 'global_read',
announce_unread: 'announce_read', announce_unread: 'announce_read',
sticky_unread: 'sticky_read', sticky_unread: 'sticky_read',
topic_unread: 'topic_read' topic_unread: 'topic_read',
}; };
var iconsState = ['', '_hot', '_hot_mine', '_locked', '_locked_mine', '_mine']; var iconsState = [ '', '_hot', '_hot_mine', '_locked', '_locked_mine', '_mine' ];
var unreadClassSelectors;
var classMap = {}; var classMap = {};
var classNames = []; var classNames = [];
@ -63,22 +63,23 @@ phpbb.addAjaxCallback('mark_topics_read', function(res, updateTopicLinks) {
updateTopicLinks = true; updateTopicLinks = true;
} }
$.each(iconsArray, function(unreadClass, readClass) { $.each(iconsArray, (unreadClass, readClass) => {
$.each(iconsState, function(key, value) { $.each(iconsState, (key, value) => {
// Only topics can be hot // Only topics can be hot
if ((value === '_hot' || value === '_hot_mine') && unreadClass !== 'topic_unread') { if ((value === '_hot' || value === '_hot_mine') && unreadClass !== 'topic_unread') {
return true; return true;
} }
classMap[unreadClass + value] = readClass + value; classMap[unreadClass + value] = readClass + value;
classNames.push(unreadClass + value); classNames.push(unreadClass + value);
}); });
}); });
unreadClassSelectors = '.' + classNames.join(',.'); var unreadClassSelectors = '.' + classNames.join(',.');
$('li.row').find(unreadClassSelectors).each(function() { $('li.row').find(unreadClassSelectors).each(function() {
var $this = $(this); var $this = $(this);
$.each(classMap, function(unreadClass, readClass) { $.each(classMap, (unreadClass, readClass) => {
if ($this.hasClass(unreadClass)) { if ($this.hasClass(unreadClass)) {
$this.removeClass(unreadClass).addClass(readClass); $this.removeClass(unreadClass).addClass(readClass);
} }
@ -95,32 +96,32 @@ phpbb.addAjaxCallback('mark_topics_read', function(res, updateTopicLinks) {
} }
phpbb.closeDarkenWrapper(3000); phpbb.closeDarkenWrapper(3000);
}); });
// This callback will mark all notifications read // This callback will mark all notifications read
phpbb.addAjaxCallback('notification.mark_all_read', function(res) { phpbb.addAjaxCallback('notification.mark_all_read', res => {
if (typeof res.success !== 'undefined') { if (typeof res.success !== 'undefined') {
phpbb.markNotifications($('[data-notification-unread="true"]'), 0); phpbb.markNotifications($('[data-notification-unread="true"]'), 0);
phpbb.toggleDropdown.call($('#notification-button')); phpbb.toggleDropdown.call($('#notification-button'));
phpbb.closeDarkenWrapper(3000); phpbb.closeDarkenWrapper(3000);
} }
}); });
// This callback will mark a notification read // This callback will mark a notification read
phpbb.addAjaxCallback('notification.mark_read', function(res) { phpbb.addAjaxCallback('notification.mark_read', function(res) {
if (typeof res.success !== 'undefined') { if (typeof res.success !== 'undefined') {
var unreadCount = Number($('#notification-button strong').html()) - 1; var unreadCount = Number($('#notification-button strong').html()) - 1;
phpbb.markNotifications($(this).parent('[data-notification-unread="true"]'), unreadCount); phpbb.markNotifications($(this).parent('[data-notification-unread="true"]'), unreadCount);
} }
}); });
/** /**
* Mark notification popup rows as read. * Mark notification popup rows as read.
* *
* @param {jQuery} $popup jQuery object(s) to mark read. * @param {jQuery} $popup jQuery object(s) to mark read.
* @param {int} unreadCount The new unread notifications count. * @param {int} unreadCount The new unread notifications count.
*/ */
phpbb.markNotifications = function($popup, unreadCount) { phpbb.markNotifications = function($popup, unreadCount) {
// Remove the unread status. // Remove the unread status.
$popup.removeClass('bg2'); $popup.removeClass('bg2');
$popup.find('a.mark_read').remove(); $popup.find('a.mark_read').remove();
@ -143,12 +144,12 @@ phpbb.markNotifications = function($popup, unreadCount) {
var $title = $('title'); var $title = $('title');
var originalTitle = $title.text().replace(/(\((\d+)\))/, ''); var originalTitle = $title.text().replace(/(\((\d+)\))/, '');
$title.text((unreadCount ? '(' + unreadCount + ')' : '') + originalTitle); $title.text((unreadCount ? '(' + unreadCount + ')' : '') + originalTitle);
}; };
// This callback finds the post from the delete link, and removes it. // This callback finds the post from the delete link, and removes it.
phpbb.addAjaxCallback('post_delete', function() { phpbb.addAjaxCallback('post_delete', function() {
var $this = $(this), var $this = $(this);
postId; var postId;
if ($this.attr('data-refresh') === undefined) { if ($this.attr('data-refresh') === undefined) {
postId = $this[0].href.split('&p=')[1]; postId = $this[0].href.split('&p=')[1];
@ -158,14 +159,15 @@ phpbb.addAjaxCallback('post_delete', function() {
post.nextAll('.bg2').removeClass('bg2').addClass('bg1'); post.nextAll('.bg2').removeClass('bg2').addClass('bg1');
posts1.removeClass('bg1').addClass('bg2'); posts1.removeClass('bg1').addClass('bg2');
} }
post.fadeOut(function() { post.fadeOut(function() {
$(this).remove(); $(this).remove();
}); });
} }
}); });
// This callback removes the approve / disapprove div or link. // This callback removes the approve / disapprove div or link.
phpbb.addAjaxCallback('post_visibility', function(res) { phpbb.addAjaxCallback('post_visibility', function(res) {
var remove = (res.visible) ? $(this) : $(this).parents('.post'); var remove = (res.visible) ? $(this) : $(this).parents('.post');
$(remove).css('pointer-events', 'none').fadeOut(function() { $(remove).css('pointer-events', 'none').fadeOut(function() {
$(this).remove(); $(this).remove();
@ -177,15 +179,15 @@ phpbb.addAjaxCallback('post_visibility', function(res) {
$(this).remove(); $(this).remove();
}); });
} }
}); });
// This removes the parent row of the link or form that fired the callback. // This removes the parent row of the link or form that fired the callback.
phpbb.addAjaxCallback('row_delete', function() { phpbb.addAjaxCallback('row_delete', function() {
$(this).parents('tr').remove(); $(this).parents('tr').remove();
}); });
// This handles friend / foe additions removals. // This handles friend / foe additions removals.
phpbb.addAjaxCallback('zebra', function(res) { phpbb.addAjaxCallback('zebra', res => {
var zebra; var zebra;
if (res.success) { if (res.success) {
@ -193,12 +195,12 @@ phpbb.addAjaxCallback('zebra', function(res) {
zebra.first().html(res.MESSAGE_TEXT); zebra.first().html(res.MESSAGE_TEXT);
zebra.not(':first').html('&nbsp;').prev().html('&nbsp;'); zebra.not(':first').html('&nbsp;').prev().html('&nbsp;');
} }
}); });
/** /**
* This callback updates the poll results after voting. * This callback updates the poll results after voting.
*/ */
phpbb.addAjaxCallback('vote_poll', function(res) { phpbb.addAjaxCallback('vote_poll', function(res) {
if (typeof res.success !== 'undefined') { if (typeof res.success !== 'undefined') {
var poll = $(this).closest('.topic_poll'); var poll = $(this).closest('.topic_poll');
var panel = poll.find('.panel'); var panel = poll.find('.panel');
@ -206,10 +208,11 @@ phpbb.addAjaxCallback('vote_poll', function(res) {
var mostVotes = 0; var mostVotes = 0;
// Set min-height to prevent the page from jumping when the content changes // Set min-height to prevent the page from jumping when the content changes
var updatePanelHeight = function (height) { var updatePanelHeight = function(height) {
height = (typeof height === 'undefined') ? panel.find('.inner').outerHeight() : height; height = (typeof height === 'undefined') ? panel.find('.inner').outerHeight() : height;
panel.css('min-height', height); panel.css('min-height', height);
}; };
updatePanelHeight(); updatePanelHeight();
// Remove the View results link // Remove the View results link
@ -217,13 +220,13 @@ phpbb.addAjaxCallback('vote_poll', function(res) {
poll.find('.poll_view_results').hide(500); poll.find('.poll_view_results').hide(500);
} }
if (!res.can_vote) { if (res.can_vote) {
poll.find('.polls, .poll_max_votes, .poll_vote, .poll_option_select').fadeOut(500, function () {
poll.find('.resultbar, .poll_option_percent, .poll_total_votes').show();
});
} else {
// If the user can still vote, simply slide down the results // If the user can still vote, simply slide down the results
poll.find('.resultbar, .poll_option_percent, .poll_total_votes').show(500); poll.find('.resultbar, .poll_option_percent, .poll_total_votes').show(500);
} else {
poll.find('.polls, .poll_max_votes, .poll_vote, .poll_option_select').fadeOut(500, () => {
poll.find('.resultbar, .poll_option_percent, .poll_total_votes').show();
});
} }
// Get the votes count of the highest poll option // Get the votes count of the highest poll option
@ -242,16 +245,16 @@ phpbb.addAjaxCallback('vote_poll', function(res) {
var optionId = $this.attr('data-poll-option-id'); var optionId = $this.attr('data-poll-option-id');
var voted = (typeof res.user_votes[optionId] !== 'undefined'); var voted = (typeof res.user_votes[optionId] !== 'undefined');
var mostVoted = (res.vote_counts[optionId] === mostVotes); var mostVoted = (res.vote_counts[optionId] === mostVotes);
var percent = (!res.total_votes) ? 0 : Math.round((res.vote_counts[optionId] / res.total_votes) * 100); var percent = res.total_votes ? Math.round((res.vote_counts[optionId] / res.total_votes) * 100) : 0;
var percentRel = (mostVotes === 0) ? 0 : Math.round((res.vote_counts[optionId] / mostVotes) * 100); var percentRel = (mostVotes === 0) ? 0 : Math.round((res.vote_counts[optionId] / mostVotes) * 100);
var altText;
altText = $this.attr('data-alt-text'); var altText = $this.attr('data-alt-text');
if (voted) { if (voted) {
$this.attr('title', $.trim(altText)); $this.attr('title', $.trim(altText));
} else { } else {
$this.attr('title', ''); $this.attr('title', '');
}; }
$this.toggleClass('voted', voted); $this.toggleClass('voted', voted);
$this.toggleClass('most-votes', mostVoted); $this.toggleClass('most-votes', mostVoted);
@ -260,7 +263,7 @@ phpbb.addAjaxCallback('vote_poll', function(res) {
var barTimeLapse = (res.can_vote) ? 500 : 1500; var barTimeLapse = (res.can_vote) ? 500 : 1500;
var newBarClass = (percent === 100) ? 'pollbar5' : 'pollbar' + (Math.floor(percent / 20) + 1); var newBarClass = (percent === 100) ? 'pollbar5' : 'pollbar' + (Math.floor(percent / 20) + 1);
setTimeout(function () { setTimeout(() => {
bar.animate({ width: percentRel + '%' }, 500) bar.animate({ width: percentRel + '%' }, 500)
.removeClass('pollbar1 pollbar2 pollbar3 pollbar4 pollbar5') .removeClass('pollbar1 pollbar2 pollbar3 pollbar4 pollbar5')
.addClass(newBarClass) .addClass(newBarClass)
@ -282,34 +285,34 @@ phpbb.addAjaxCallback('vote_poll', function(res) {
updatePanelHeight(); updatePanelHeight();
} }
$(this).delay(5000).fadeOut(500, function() { $(this).delay(5000).fadeOut(500, () => {
resizePanel(300); resizePanel(300);
}); });
}); });
// Remove the gap resulting from removing options // Remove the gap resulting from removing options
setTimeout(function() { setTimeout(() => {
resizePanel(500); resizePanel(500);
}, 1500); }, 1500);
var resizePanel = function (time) { var resizePanel = function(time) {
var panelHeight = panel.height(); var panelHeight = panel.height();
var innerHeight = panel.find('.inner').outerHeight(); var innerHeight = panel.find('.inner').outerHeight();
if (panelHeight !== innerHeight) { if (panelHeight !== innerHeight) {
panel.css({ minHeight: '', height: panelHeight }) panel.css({ minHeight: '', height: panelHeight })
.animate({ height: innerHeight }, time, function () { .animate({ height: innerHeight }, time, () => {
panel.css({ minHeight: innerHeight, height: '' }); panel.css({ minHeight: innerHeight, height: '' });
}); });
} }
}; };
} }
}); });
/** /**
* Show poll results when clicking View results link. * Show poll results when clicking View results link.
*/ */
$('.poll_view_results a').click(function(e) { $('.poll_view_results a').click(function(e) {
// Do not follow the link // Do not follow the link
e.preventDefault(); e.preventDefault();
@ -317,41 +320,38 @@ $('.poll_view_results a').click(function(e) {
$poll.find('.resultbar, .poll_option_percent, .poll_total_votes').show(500); $poll.find('.resultbar, .poll_option_percent, .poll_total_votes').show(500);
$poll.find('.poll_view_results').hide(500); $poll.find('.poll_view_results').hide(500);
}); });
$('[data-ajax]').each(function() { $('[data-ajax]').each(function() {
var $this = $(this); var $this = $(this);
var ajax = $this.attr('data-ajax'); var ajax = $this.attr('data-ajax');
var filter = $this.attr('data-filter'); var filter = $this.attr('data-filter');
if (ajax !== 'false') { if (ajax !== 'false') {
var fn = (ajax !== 'true') ? ajax : null; var fn = ajax === 'true' ? null : ajax;
filter = (filter !== undefined) ? phpbb.getFunctionByName(filter) : null; filter = filter === undefined ? null : phpbb.getFunctionByName(filter);
phpbb.ajaxify({ phpbb.ajaxify({
selector: this, selector: this,
refresh: $this.attr('data-refresh') !== undefined, refresh: $this.attr('data-refresh') !== undefined,
filter: filter, filter,
callback: fn callback: fn,
}); });
} }
}); });
/** /**
* This simply appends #preview to the action of the * This simply appends #preview to the action of the
* QR action when you click the Full Editor & Preview button * QR action when you click the Full Editor & Preview button
*/ */
$('#qr_full_editor').click(function() { $('#qr_full_editor').click(() => {
$('#qr_postform').attr('action', function(i, val) { $('#qr_postform').attr('action', (i, val) => val + '#preview');
return val + '#preview';
}); });
});
/**
/**
* Make the display post links to use JS * Make the display post links to use JS
*/ */
$('.display_post').click(function(e) { $('.display_post').click(function(e) {
// Do not follow the link // Do not follow the link
e.preventDefault(); e.preventDefault();
@ -359,27 +359,27 @@ $('.display_post').click(function(e) {
$('#post_content' + postId).show(); $('#post_content' + postId).show();
$('#profile' + postId).show(); $('#profile' + postId).show();
$('#post_hidden' + postId).hide(); $('#post_hidden' + postId).hide();
}); });
/** /**
* Display hidden post on post review page * Display hidden post on post review page
*/ */
$('.display_post_review').on('click', function(e) { $('.display_post_review').on('click', function(e) {
e.preventDefault(); e.preventDefault();
let $displayPostLink = $(this); const $displayPostLink = $(this);
$displayPostLink.closest('.post-ignore').removeClass('post-ignore'); $displayPostLink.closest('.post-ignore').removeClass('post-ignore');
$displayPostLink.hide(); $displayPostLink.hide();
}); });
/** /**
* Toggle the member search panel in memberlist.php. * Toggle the member search panel in memberlist.php.
* *
* If user returns to search page after viewing results the search panel is automatically displayed. * If user returns to search page after viewing results the search panel is automatically displayed.
* In any case the link will toggle the display status of the search panel and link text will be * In any case the link will toggle the display status of the search panel and link text will be
* appropriately changed based on the status of the search panel. * appropriately changed based on the status of the search panel.
*/ */
$('#member_search').click(function () { $('#member_search').click(function() {
var $memberlistSearch = $('#memberlist_search'); var $memberlistSearch = $('#memberlist_search');
$memberlistSearch.slideToggle('fast'); $memberlistSearch.slideToggle('fast');
@ -389,17 +389,18 @@ $('#member_search').click(function () {
if ($memberlistSearch.is(':visible')) { if ($memberlistSearch.is(':visible')) {
$('#username').focus(); $('#username').focus();
} }
return false;
});
/** return false;
});
/**
* Show to top button if available on page * Show to top button if available on page
*/ */
const $scrollTopButton = $('.to-top-button'); const $scrollTopButton = $('.to-top-button');
if ($scrollTopButton.length) { if ($scrollTopButton.length) {
// Show or hide the button based on scroll position // Show or hide the button based on scroll position
$(window).scroll(function () { $(window).scroll(function() {
if ($(this).scrollTop() > 300) { if ($(this).scrollTop() > 300) {
$scrollTopButton.fadeIn(); // Fade in the button $scrollTopButton.fadeIn(); // Fade in the button
} else { } else {
@ -408,20 +409,18 @@ if ($scrollTopButton.length) {
}); });
// Scroll smoothly to the top when the button is clicked // Scroll smoothly to the top when the button is clicked
$scrollTopButton.click(function (e) { $scrollTopButton.click(e => {
e.preventDefault(); // Prevent the default anchor link behavior e.preventDefault(); // Prevent the default anchor link behavior
$('html, body').animate({scrollTop: 0}, 500); // Smooth scroll to top $('html, body').animate({ scrollTop: 0 }, 500); // Smooth scroll to top
}); });
} }
/** /**
* Automatically resize textarea * Automatically resize textarea
*/ */
$(function() { $(() => {
var $textarea = $('textarea:not(#message-box textarea, .no-auto-resize)'); var $textarea = $('textarea:not(#message-box textarea, .no-auto-resize)');
phpbb.resizeTextArea($textarea, { minHeight: 75, maxHeight: 250 }); phpbb.resizeTextArea($textarea, { minHeight: 75, maxHeight: 250 });
phpbb.resizeTextArea($('textarea', '#message-box')); phpbb.resizeTextArea($('textarea', '#message-box'));
}); });
})(jQuery); // Avoid conflicts with other libraries })(jQuery); // Avoid conflicts with other libraries

View file

@ -1,4 +1,7 @@
/* global phpbb */ /* global phpbb */
/* eslint camelcase: 0 */
/* eslint no-unused-vars: 0 */
/* eslint no-var:0 */
/** /**
* phpBB forum functions * phpBB forum functions
@ -34,10 +37,10 @@ function popup(url, width, height, name) {
function pageJump(item) { function pageJump(item) {
'use strict'; 'use strict';
var page = parseInt(item.val(), 10), var page = parseInt(item.val(), 10);
perPage = item.attr('data-per-page'), var perPage = item.attr('data-per-page');
baseUrl = item.attr('data-base-url'), var baseUrl = item.attr('data-base-url');
startName = item.attr('data-start-name'); var startName = item.attr('data-start-name');
if (page !== null && !isNaN(page) && page === Math.floor(page) && page > 0) { if (page !== null && !isNaN(page) && page === Math.floor(page) && page > 0) {
if (baseUrl.indexOf('?') === -1) { if (baseUrl.indexOf('?') === -1) {
@ -78,39 +81,38 @@ function viewableArea(e, itself) {
e = e.parentNode; e = e.parentNode;
} }
if (!e.vaHeight) { if (e.vaHeight) {
// Restore viewable area height to the default
e.style.height = e.vaHeight + 'px';
e.style.overflow = 'auto';
e.style.maxHeight = e.vaMaxHeight;
e.vaHeight = false;
} else {
// Store viewable area height before changing style to auto // Store viewable area height before changing style to auto
e.vaHeight = e.offsetHeight; e.vaHeight = e.offsetHeight;
e.vaMaxHeight = e.style.maxHeight; e.vaMaxHeight = e.style.maxHeight;
e.style.height = 'auto'; e.style.height = 'auto';
e.style.maxHeight = 'none'; e.style.maxHeight = 'none';
e.style.overflow = 'visible'; e.style.overflow = 'visible';
} else {
// Restore viewable area height to the default
e.style.height = e.vaHeight + 'px';
e.style.overflow = 'auto';
e.style.maxHeight = e.vaMaxHeight;
e.vaHeight = false;
} }
} }
/** /**
* Alternate display of subPanels * Alternate display of subPanels
*/ */
jQuery(function($) { jQuery($ => {
'use strict'; 'use strict';
$('.sub-panels').each(function() { $('.sub-panels').each(function() {
var $childNodes = $('a[data-subpanel]', this);
var $childNodes = $('a[data-subpanel]', this), var panels = $childNodes.map(function() {
panels = $childNodes.map(function () {
return this.getAttribute('data-subpanel'); return this.getAttribute('data-subpanel');
}), });
showPanel = this.getAttribute('data-show-panel'); var showPanel = this.getAttribute('data-show-panel');
if (panels.length) { if (panels.length) {
activateSubPanel(showPanel, panels); activateSubPanel(showPanel, panels);
$childNodes.click(function () { $childNodes.click(function() {
activateSubPanel(this.getAttribute('data-subpanel'), panels); activateSubPanel(this.getAttribute('data-subpanel'), panels);
return false; return false;
}); });
@ -124,11 +126,13 @@ jQuery(function($) {
function activateSubPanel(p, panels) { function activateSubPanel(p, panels) {
'use strict'; 'use strict';
var i, showPanel; var i;
var showPanel;
if (typeof p === 'string') { if (typeof p === 'string') {
showPanel = p; showPanel = p;
} }
$('input[name="show_panel"]').val(showPanel); $('input[name="show_panel"]').val(showPanel);
if (typeof panels === 'undefined') { if (typeof panels === 'undefined') {
@ -148,7 +152,8 @@ function selectCode(a) {
// Get ID of code block // Get ID of code block
var e = a.parentNode.parentNode.getElementsByTagName('CODE')[0]; var e = a.parentNode.parentNode.getElementsByTagName('CODE')[0];
var s, r; var s;
var r;
// Not IE and IE9+ // Not IE and IE9+
if (window.getSelection) { if (window.getSelection) {
@ -164,12 +169,11 @@ function selectCode(a) {
s.removeAllRanges(); s.removeAllRanges();
s.addRange(r); s.addRange(r);
} }
} } else {
// Firefox and Opera // Firefox and Opera
else {
// workaround for bug # 42885 // workaround for bug # 42885
if (window.opera && e.innerHTML.substring(e.innerHTML.length - 4) === '<BR>') { if (window.opera && e.innerHTML.substring(e.innerHTML.length - 4) === '<BR>') {
e.innerHTML = e.innerHTML + '&nbsp;'; e.innerHTML += '&nbsp;';
} }
r = document.createRange(); r = document.createRange();
@ -177,17 +181,15 @@ function selectCode(a) {
s.removeAllRanges(); s.removeAllRanges();
s.addRange(r); s.addRange(r);
} }
} } else if (document.getSelection) {
// Some older browsers // Some older browsers
else if (document.getSelection) {
s = document.getSelection(); s = document.getSelection();
r = document.createRange(); r = document.createRange();
r.selectNodeContents(e); r.selectNodeContents(e);
s.removeAllRanges(); s.removeAllRanges();
s.addRange(r); s.addRange(r);
} } else if (document.selection) {
// IE // IE
else if (document.selection) {
r = document.body.createTextRange(); r = document.body.createTextRange();
r.moveToElementText(e); r.moveToElementText(e);
r.select(); r.select();
@ -229,10 +231,10 @@ function phpbbCheckKey(event) {
/** /**
* Apply onkeypress event for forcing default submit button on ENTER key press * Apply onkeypress event for forcing default submit button on ENTER key press
*/ */
jQuery(function($) { jQuery($ => {
'use strict'; 'use strict';
$('form input[type=text], form input[type=password]').on('keypress', function (e) { $('form input[type=text], form input[type=password]').on('keypress', function(e) {
var defaultButton = $(this).parents('form').find('input[type=submit].default-submit-action'); var defaultButton = $(this).parents('form').find('input[type=submit].default-submit-action');
if (!defaultButton || defaultButton.length <= 0) { if (!defaultButton || defaultButton.length <= 0) {
@ -258,10 +260,10 @@ jQuery(function($) {
function insertUser(formId, value) { function insertUser(formId, value) {
'use strict'; 'use strict';
var $form = jQuery(formId), var $form = jQuery(formId);
formName = $form.attr('data-form-name'), var formName = $form.attr('data-form-name');
fieldName = $form.attr('data-field-name'), var fieldName = $form.attr('data-field-name');
item = opener.document.forms[formName][fieldName]; var item = opener.document.forms[formName][fieldName];
if (item.value.length && item.type === 'textarea') { if (item.value.length && item.type === 'textarea') {
value = item.value + '\n' + value; value = item.value + '\n' + value;
@ -293,9 +295,9 @@ function insert_single_user(formId, user) {
function parseDocument($container) { function parseDocument($container) {
'use strict'; 'use strict';
var test = document.createElement('div'), var test = document.createElement('div');
oldBrowser = (typeof test.style.borderRadius === 'undefined'), var oldBrowser = (typeof test.style.borderRadius === 'undefined');
$body = $('body'); var $body = $('body');
/** /**
* Reset avatar dimensions when changing URL or EMAIL * Reset avatar dimensions when changing URL or EMAIL
@ -322,7 +324,7 @@ function parseDocument($container) {
$container.find('.pagination .dropdown-trigger').click(function() { $container.find('.pagination .dropdown-trigger').click(function() {
var $dropdownContainer = $(this).parent(); var $dropdownContainer = $(this).parent();
// Wait a little bit to make sure the dropdown has activated // Wait a little bit to make sure the dropdown has activated
setTimeout(function() { setTimeout(() => {
if ($dropdownContainer.hasClass('dropdown-visible')) { if ($dropdownContainer.hasClass('dropdown-visible')) {
$dropdownContainer.find('input.inputbox').focus(); $dropdownContainer.find('input.inputbox').focus();
} }
@ -333,19 +335,18 @@ function parseDocument($container) {
* Resize navigation (breadcrumbs) block to keep all links on same line * Resize navigation (breadcrumbs) block to keep all links on same line
*/ */
$container.find('.navlinks').each(function() { $container.find('.navlinks').each(function() {
var $this = $(this), var $this = $(this);
$left = $this.children().not('.rightside'), var $left = $this.children().not('.rightside');
$right = $this.children('.rightside'); var $right = $this.children('.rightside');
if ($left.length !== 1 || !$right.length) { if ($left.length !== 1 || !$right.length) {
return; return;
} }
function resize() { function resize() {
var width = 0, var width = 0;
diff = $left.outerWidth(true) - $left.width(), var diff = $left.outerWidth(true) - $left.width();
minWidth = Math.max($this.width() / 3, 240), var minWidth = Math.max($this.width() / 3, 240);
maxWidth;
$right.each(function() { $right.each(function() {
var $this = $(this); var $this = $(this);
@ -354,7 +355,7 @@ function parseDocument($container) {
} }
}); });
maxWidth = $this.width() - width - diff; var maxWidth = $this.width() - width - diff;
$left.css('max-width', Math.floor(Math.max(maxWidth, minWidth)) + 'px'); $left.css('max-width', Math.floor(Math.max(maxWidth, minWidth)) + 'px');
} }
@ -366,14 +367,14 @@ function parseDocument($container) {
* Makes breadcrumbs responsive * Makes breadcrumbs responsive
*/ */
$container.find('.breadcrumbs:not([data-skip-responsive])').each(function() { $container.find('.breadcrumbs:not([data-skip-responsive])').each(function() {
var $this = $(this), var $this = $(this);
$links = $this.find('.crumb'), var $links = $this.find('.crumb');
length = $links.length, var { length } = $links;
classes = ['wrapped-max', 'wrapped-wide', 'wrapped-medium', 'wrapped-small', 'wrapped-tiny'], var classes = [ 'wrapped-max', 'wrapped-wide', 'wrapped-medium', 'wrapped-small', 'wrapped-tiny' ];
classesLength = classes.length, var classesLength = classes.length;
maxHeight = 0, var maxHeight = 0;
lastWidth = false, var lastWidth = false;
wrapped = false; var wrapped = false;
// Set tooltips // Set tooltips
$this.find('a').each(function() { $this.find('a').each(function() {
@ -383,8 +384,8 @@ function parseDocument($container) {
// Function that checks breadcrumbs // Function that checks breadcrumbs
function check() { function check() {
var height = $this.height(), var height = $this.height();
width; var width;
// Test max-width set in code for .navlinks above // Test max-width set in code for .navlinks above
width = parseInt($this.css('max-width'), 10); width = parseInt($this.css('max-width'), 10);
@ -404,6 +405,7 @@ function parseDocument($container) {
return; return;
} }
} }
lastWidth = width; lastWidth = width;
if (wrapped) { if (wrapped) {
@ -454,23 +456,23 @@ function parseDocument($container) {
* responsive-show-all to list of classes * responsive-show-all to list of classes
*/ */
$container.find('.topiclist.responsive-show-all > li > dl').each(function() { $container.find('.topiclist.responsive-show-all > li > dl').each(function() {
var $this = $(this), var $this = $(this);
$block = $this.find('dt .responsive-show:last-child'), var $block = $this.find('dt .responsive-show:last-child');
first = true; var first = true;
// Create block that is visible only on mobile devices // Create block that is visible only on mobile devices
if (!$block.length) { if ($block.length) {
first = ($.trim($block.text()).length === 0);
} else {
$this.find('dt > .list-inner').append('<div class="responsive-show" style="display:none;" />'); $this.find('dt > .list-inner').append('<div class="responsive-show" style="display:none;" />');
$block = $this.find('dt .responsive-show:last-child'); $block = $this.find('dt .responsive-show:last-child');
} else {
first = ($.trim($block.text()).length === 0);
} }
// Copy contents of each column // Copy contents of each column
$this.find('dd').not('.mark').each(function() { $this.find('dd').not('.mark').each(function() {
var column = $(this), var column = $(this);
$children = column.children(), var $children = column.children();
html = column.html(); var html = column.html();
if ($children.length === 1 && $children.text() === column.text()) { if ($children.length === 1 && $children.text() === column.text()) {
html = $children.html(); html = $children.html();
@ -490,13 +492,13 @@ function parseDocument($container) {
* responsive-show-columns to list of classes * responsive-show-columns to list of classes
*/ */
$container.find('.topiclist.responsive-show-columns').each(function() { $container.find('.topiclist.responsive-show-columns').each(function() {
var $list = $(this), var $list = $(this);
headers = [], var headers = [];
headersLength = 0; var headersLength = 0;
// Find all headers, get contents // Find all headers, get contents
$list.prev('.topiclist').find('li.header dd').not('.mark').each(function() { $list.prev('.topiclist').find('li.header dd').not('.mark').each(function() {
headers.push($("<div>").text($(this).text()).html()); headers.push($('<div>').text($(this).text()).html());
headersLength++; headersLength++;
}); });
@ -506,23 +508,23 @@ function parseDocument($container) {
// Parse each row // Parse each row
$list.find('dl').each(function() { $list.find('dl').each(function() {
var $this = $(this), var $this = $(this);
$block = $this.find('dt .responsive-show:last-child'), var $block = $this.find('dt .responsive-show:last-child');
first = true; var first = true;
// Create block that is visible only on mobile devices // Create block that is visible only on mobile devices
if (!$block.length) { if ($block.length) {
first = ($.trim($block.text()).length === 0);
} else {
$this.find('dt > .list-inner').append('<div class="responsive-show" style="display:none;" />'); $this.find('dt > .list-inner').append('<div class="responsive-show" style="display:none;" />');
$block = $this.find('dt .responsive-show:last-child'); $block = $this.find('dt .responsive-show:last-child');
} else {
first = ($.trim($block.text()).length === 0);
} }
// Copy contents of each column // Copy contents of each column
$this.find('dd').not('.mark').each(function(i) { $this.find('dd').not('.mark').each(function(i) {
var column = $(this), var column = $(this);
children = column.children(), var children = column.children();
html = column.html(); var html = column.html();
if (children.length === 1 && children.text() === column.text()) { if (children.length === 1 && children.text() === column.text()) {
html = children.html(); html = children.html();
@ -544,24 +546,25 @@ function parseDocument($container) {
* Responsive tables * Responsive tables
*/ */
$container.find('table.table1').not('.not-responsive').each(function() { $container.find('table.table1').not('.not-responsive').each(function() {
var $this = $(this), var $this = $(this);
$th = $this.find('thead > tr > th'), var $th = $this.find('thead > tr > th');
headers = [], var headers = [];
totalHeaders = 0, var totalHeaders = 0;
i, headersLength; var i;
// Find each header // Find each header
$th.each(function(column) { $th.each(function(column) {
var cell = $(this), var cell = $(this);
colspan = parseInt(cell.attr('colspan'), 10), var colspan = parseInt(cell.attr('colspan'), 10);
dfn = cell.attr('data-dfn'), var dfn = cell.attr('data-dfn');
text = dfn ? dfn : cell.text(); var text = dfn ? dfn : cell.text();
colspan = isNaN(colspan) || colspan < 1 ? 1 : colspan; colspan = isNaN(colspan) || colspan < 1 ? 1 : colspan;
for (i = 0; i < colspan; i++) { for (i = 0; i < colspan; i++) {
headers.push(text); headers.push(text);
} }
totalHeaders++; totalHeaders++;
if (dfn && !column) { if (dfn && !column) {
@ -569,7 +572,7 @@ function parseDocument($container) {
} }
}); });
headersLength = headers.length; var headersLength = headers.length;
// Add header text to each cell as <dfn> // Add header text to each cell as <dfn>
$this.addClass('responsive'); $this.addClass('responsive');
@ -580,9 +583,9 @@ function parseDocument($container) {
} }
$this.find('tbody > tr').each(function() { $this.find('tbody > tr').each(function() {
var row = $(this), var row = $(this);
cells = row.children('td'), var cells = row.children('td');
column = 0; var column = 0;
if (cells.length === 1) { if (cells.length === 1) {
row.addClass('big-column'); row.addClass('big-column');
@ -590,9 +593,9 @@ function parseDocument($container) {
} }
cells.each(function() { cells.each(function() {
var cell = $(this), var cell = $(this);
colspan = parseInt(cell.attr('colspan'), 10), var colspan = parseInt(cell.attr('colspan'), 10);
text = $.trim(cell.text()); var text = $.trim(cell.text());
if (headersLength <= column) { if (headersLength <= column) {
return; return;
@ -600,7 +603,7 @@ function parseDocument($container) {
if ((text.length && text !== '-') || cell.children().length) { if ((text.length && text !== '-') || cell.children().length) {
if (headers[column].length) { if (headers[column].length) {
cell.prepend($("<dfn>").css('display', 'none').text(headers[column])); cell.prepend($('<dfn>').css('display', 'none').text(headers[column]));
} }
} else { } else {
cell.addClass('empty'); cell.addClass('empty');
@ -626,15 +629,15 @@ function parseDocument($container) {
* Responsive tabs * Responsive tabs
*/ */
$container.find('#tabs, #minitabs').not('[data-skip-responsive]').each(function() { $container.find('#tabs, #minitabs').not('[data-skip-responsive]').each(function() {
var $this = $(this), var $this = $(this);
$ul = $this.children(), var $ul = $this.children();
$tabs = $ul.children().not('[data-skip-responsive]'), var $tabs = $ul.children().not('[data-skip-responsive]');
$links = $tabs.children('a'), var $links = $tabs.children('a');
$item = $ul.append('<li class="tab responsive-tab" style="display:none;"><a href="javascript:void(0);" class="responsive-tab-link">&nbsp;</a><div class="dropdown tab-dropdown" style="display: none;"><div class="pointer"><div class="pointer-inner"></div></div><ul class="dropdown-contents" /></div></li>').find('li.responsive-tab'), var $item = $ul.append('<li class="tab responsive-tab" style="display:none;"><a href="javascript:void(0);" class="responsive-tab-link">&nbsp;</a><div class="dropdown tab-dropdown" style="display: none;"><div class="pointer"><div class="pointer-inner"></div></div><ul class="dropdown-contents" /></div></li>').find('li.responsive-tab');
$menu = $item.find('.dropdown-contents'), var $menu = $item.find('.dropdown-contents');
maxHeight = 0, var maxHeight = 0;
lastWidth = false, var lastWidth = false;
responsive = false; var responsive = false;
$links.each(function() { $links.each(function() {
var $this = $(this); var $this = $(this);
@ -642,8 +645,8 @@ function parseDocument($container) {
}); });
function check() { function check() {
var width = $body.width(), var width = $body.width();
height = $this.height(); var height = $this.height();
if (!arguments.length && (!responsive || width <= lastWidth) && height <= maxHeight) { if (!arguments.length && (!responsive || width <= lastWidth) && height <= maxHeight) {
return; return;
@ -658,6 +661,7 @@ function parseDocument($container) {
if ($item.hasClass('dropdown-visible')) { if ($item.hasClass('dropdown-visible')) {
phpbb.toggleDropdown.call($item.find('a.responsive-tab-link').get(0)); phpbb.toggleDropdown.call($item.find('a.responsive-tab-link').get(0));
} }
return; return;
} }
@ -665,29 +669,31 @@ function parseDocument($container) {
$item.show(); $item.show();
$menu.html(''); $menu.html('');
var $availableTabs = $tabs.filter(':not(.activetab, .responsive-tab)'), var $availableTabs = $tabs.filter(':not(.activetab, .responsive-tab)');
total = $availableTabs.length, var total = $availableTabs.length;
i, $tab; var i;
var $tab;
for (i = total - 1; i >= 0; i--) { for (i = total - 1; i >= 0; i--) {
$tab = $availableTabs.eq(i); $tab = $availableTabs.eq(i);
$menu.prepend($tab.clone(true).removeClass('tab')); $menu.prepend($tab.clone(true).removeClass('tab'));
$tab.hide(); $tab.hide();
if ($this.height() <= maxHeight) { if ($this.height() <= maxHeight) {
$menu.find('a').click(function() { $menu.find('a').click(() => {
check(true); check(true);
}); });
return; return;
} }
} }
$menu.find('a').click(function() {
$menu.find('a').click(() => {
check(true); check(true);
}); });
} }
var $tabLink = $item.find('a.responsive-tab-link'); var $tabLink = $item.find('a.responsive-tab-link');
phpbb.registerDropdown($tabLink, $item.find('.dropdown'), { phpbb.registerDropdown($tabLink, $item.find('.dropdown'), {
visibleClass: 'activetab' visibleClass: 'activetab',
}); });
check(true); check(true);
@ -708,23 +714,26 @@ function parseDocument($container) {
* Replace responsive text * Replace responsive text
*/ */
$container.find('[data-responsive-text]').each(function() { $container.find('[data-responsive-text]').each(function() {
var $this = $(this), var $this = $(this);
fullText = $this.text(), var fullText = $this.text();
responsiveText = $this.attr('data-responsive-text'), var responsiveText = $this.attr('data-responsive-text');
responsive = false; var responsive = false;
function check() { function check() {
if ($(window).width() > 700) { if ($(window).width() > 700) {
if (!responsive) { if (!responsive) {
return; return;
} }
$this.text(fullText); $this.text(fullText);
responsive = false; responsive = false;
return; return;
} }
if (responsive) { if (responsive) {
return; return;
} }
$this.text(responsiveText); $this.text(responsiveText);
responsive = true; responsive = true;
} }
@ -737,7 +746,7 @@ function parseDocument($container) {
/** /**
* Run onload functions * Run onload functions
*/ */
jQuery(function($) { jQuery($ => {
'use strict'; 'use strict';
// Swap .nojs and .hasjs // Swap .nojs and .hasjs

View file

@ -16,8 +16,6 @@
*/ */
class phpbb_functional_extension_controller_test extends phpbb_functional_test_case class phpbb_functional_extension_controller_test extends phpbb_functional_test_case
{ {
protected $phpbb_extension_manager;
private static $helper; private static $helper;
protected static $fixtures = array( protected static $fixtures = array(

View file

@ -16,8 +16,6 @@
*/ */
class phpbb_functional_extension_global_lang_test extends phpbb_functional_test_case class phpbb_functional_extension_global_lang_test extends phpbb_functional_test_case
{ {
protected $phpbb_extension_manager;
private static $helper; private static $helper;
protected static $fixtures = array( protected static $fixtures = array(

View file

@ -17,8 +17,6 @@ require_once __DIR__ . '/../../phpBB/includes/acp/acp_modules.php';
*/ */
class phpbb_functional_extension_module_test extends phpbb_functional_test_case class phpbb_functional_extension_module_test extends phpbb_functional_test_case
{ {
protected $phpbb_extension_manager;
private static $helper; private static $helper;
protected static $fixtures = array( protected static $fixtures = array(

View file

@ -16,8 +16,6 @@
*/ */
class phpbb_functional_extension_permission_lang_test extends phpbb_functional_test_case class phpbb_functional_extension_permission_lang_test extends phpbb_functional_test_case
{ {
protected $phpbb_extension_manager;
private static $helper; private static $helper;
protected static $fixtures = array( protected static $fixtures = array(

View file

@ -0,0 +1,105 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
/**
* @group functional
*/
class phpbb_functional_extension_template_event_order_test extends phpbb_functional_test_case
{
static private $helper;
static protected $fixtures = [
'./',
];
static public function setUpBeforeClass(): void
{
parent::setUpBeforeClass();
self::$helper = new phpbb_test_case_helpers(__CLASS__);
self::$helper->copy_ext_fixtures(__DIR__ . '/fixtures/ext/', self::$fixtures);
}
static public function tearDownAfterClass(): void
{
parent::tearDownAfterClass();
self::$helper->restore_original_ext_dir();
}
protected function setUp(): void
{
parent::setUp();
$this->purge_cache();
}
protected function tearDown(): void
{
$this->uninstall_ext('foo/bar');
$this->uninstall_ext('foo/foo');
parent::tearDown();
}
protected static function setup_extensions()
{
return ['foo/bar', 'foo/foo'];
}
/**
* Check extensions template event listener prioritizing
*/
public function test_different_template_event_priority()
{
global $phpbb_root_path;
$crawler = self::request('GET', 'index.php');
$quick_links_menu = $crawler->filter('ul[role="menu"]')->eq(0);
$quick_links_menu_nodes_count = (int) $quick_links_menu->filter('li')->count();
// Ensure foo/foo template event goes before foo/bar one
$this->assertStringContainsString('FOO_FOO_QUICK_LINK', $quick_links_menu->filter('li')->eq($quick_links_menu_nodes_count - 4)->filter('span')->text());
$this->assertStringContainsString('FOO_BAR_QUICK_LINK', $quick_links_menu->filter('li')->eq($quick_links_menu_nodes_count - 3)->filter('span')->text());
// Change template events order to default, put foo/bar event before foo/foo one
$this->disable_ext('foo/bar');
$this->disable_ext('foo/foo');
$this->assertTrue(copy(__DIR__ . '/fixtures/ext/foo/bar/event/template_event_order_higher.php', $phpbb_root_path . 'ext/foo/bar/event/template_event_order.php'));
$this->assertTrue(copy(__DIR__ . '/fixtures/ext/foo/foo/event/template_event_order_lower.php', $phpbb_root_path . 'ext/foo/foo/event/template_event_order.php'));
$this->install_ext('foo/bar');
$this->install_ext('foo/foo');
$crawler = self::request('GET', 'index.php');
$quick_links_menu = $crawler->filter('ul[role="menu"]')->eq(0);
$quick_links_menu_nodes_count = (int) $quick_links_menu->filter('li')->count();
// Ensure foo/foo template event goes before foo/bar one
$this->assertStringContainsString('FOO_BAR_QUICK_LINK', $quick_links_menu->filter('li')->eq($quick_links_menu_nodes_count - 4)->filter('span')->text());
$this->assertStringContainsString('FOO_FOO_QUICK_LINK', $quick_links_menu->filter('li')->eq($quick_links_menu_nodes_count - 3)->filter('span')->text());
}
/**
* Check extensions template event listener equal (default - 0) priority rendering
* Should render in the order of reading listener files from the filesystem
*/
public function test_same_template_event_priority()
{
global $phpbb_root_path;
$crawler = self::request('GET', 'index.php');
// Ensure foo/bar template event goes before foo/foo one (assuming they have been read from the filesystem in alphabetical order)
$this->assertStringContainsString('FOO_BAR_FORUMLIST_BODY_BEFORE', $crawler->filter('p[id*="forumlist_body_before"]')->eq(0)->text());
$this->assertStringContainsString('FOO_FOO_FORUMLIST_BODY_BEFORE', $crawler->filter('p[id*="forumlist_body_before"]')->eq(1)->text());
}
}

View file

@ -14,7 +14,13 @@ services:
class: foo\bar\event\permission class: foo\bar\event\permission
tags: tags:
- { name: event.listener } - { name: event.listener }
foo_bar.listener.user_setup: foo_bar.listener.user_setup:
class: foo\bar\event\user_setup class: foo\bar\event\user_setup
tags: tags:
- { name: event.listener } - { name: event.listener }
foo_bar.listener.template_event_order:
class: foo\bar\event\template_event_order
tags:
- { name: event.listener }

View file

@ -0,0 +1,38 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace foo\bar\event;
/**
* Event listener
*/
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class template_event_order implements EventSubscriberInterface
{
static public function getSubscribedEvents()
{
return array(
'core.twig_event_tokenparser_constructor' => 'set_template_event_priority',
);
}
public function set_template_event_priority($event)
{
$template_event_priority_array = $event['template_event_priority_array'];
$template_event_priority_array['foo_bar'] = [
'event/navbar_header_quick_links_after' => -1,
];
$event['template_event_priority_array'] = $template_event_priority_array;
}
}

View file

@ -0,0 +1,38 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace foo\bar\event;
/**
* Event listener
*/
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class template_event_order implements EventSubscriberInterface
{
static public function getSubscribedEvents()
{
return array(
'core.twig_event_tokenparser_constructor' => 'set_template_event_priority',
);
}
public function set_template_event_priority($event)
{
$template_event_priority_array = $event['template_event_priority_array'];
$template_event_priority_array['foo_bar'] = [
'event/navbar_header_quick_links_after' => 1,
];
$event['template_event_priority_array'] = $template_event_priority_array;
}
}

View file

@ -0,0 +1 @@
<p id="foo_bar_forumlist_body_before">{{ lang('FOO_BAR_FORUMLIST_BODY_BEFORE') }}</p>

View file

@ -0,0 +1 @@
<li><span>{{ lang('FOO_BAR_QUICK_LINK') }}</span></li>

View file

@ -1,3 +1,8 @@
services: services:
foo_foo.controller: foo_foo.controller:
class: foo\foo\controller\controller class: foo\foo\controller\controller
foo_foo.listener.template_event_order:
class: foo\foo\event\template_event_order
tags:
- { name: event.listener }

View file

@ -0,0 +1,38 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace foo\foo\event;
/**
* Event listener
*/
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class template_event_order implements EventSubscriberInterface
{
static public function getSubscribedEvents()
{
return array(
'core.twig_event_tokenparser_constructor' => 'set_template_event_priority',
);
}
public function set_template_event_priority($event)
{
$template_event_priority_array = $event['template_event_priority_array'];
$template_event_priority_array['foo_foo'] = [
'event/navbar_header_quick_links_after' => 1,
];
$event['template_event_priority_array'] = $template_event_priority_array;
}
}

View file

@ -0,0 +1,38 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace foo\foo\event;
/**
* Event listener
*/
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class template_event_order implements EventSubscriberInterface
{
static public function getSubscribedEvents()
{
return array(
'core.twig_event_tokenparser_constructor' => 'set_template_event_priority',
);
}
public function set_template_event_priority($event)
{
$template_event_priority_array = $event['template_event_priority_array'];
$template_event_priority_array['foo_foo'] = [
'event/navbar_header_quick_links_after' => -1,
];
$event['template_event_priority_array'] = $template_event_priority_array;
}
}

View file

@ -0,0 +1 @@
<p id="foo_foo_forumlist_body_before">{{ lang('FOO_FOO_FORUMLIST_BODY_BEFORE') }}</p>

View file

@ -0,0 +1 @@
<li><span>{{ lang('FOO_FOO_QUICK_LINK') }}</span></li>

View file

@ -16,8 +16,6 @@
*/ */
class phpbb_functional_metadata_manager_test extends phpbb_functional_test_case class phpbb_functional_metadata_manager_test extends phpbb_functional_test_case
{ {
protected $phpbb_extension_manager;
private static $helper; private static $helper;
protected static $fixtures = array( protected static $fixtures = array(

View file

@ -644,7 +644,7 @@ class phpbb_functional_test_case extends phpbb_test_case
$meta_refresh = $crawler->filter('meta[http-equiv="refresh"]'); $meta_refresh = $crawler->filter('meta[http-equiv="refresh"]');
// Wait for extension to be fully enabled // Wait for extension to be fully disabled
while (count($meta_refresh)) while (count($meta_refresh))
{ {
preg_match('#url=.+/(adm+.+)#', $meta_refresh->attr('content'), $match); preg_match('#url=.+/(adm+.+)#', $meta_refresh->attr('content'), $match);