Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion Sources/Actions/QuickModerationInTopic.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ public function execute(): void
// Check the session = get or post.
User::$me->checkSession('request');

// Nothing ticked, nothing to do. Every branch below assumes at least
// one message: splitting takes the min() of them, and the other two
// hand the list to an {array_int:...}, which will not accept an empty
// one.
if (empty($this->messages)) {
Utils::redirectexit('topic=' . Topic::$topic_id . '.' . ($_REQUEST['start'] ?? 0));
}

if (isset($_REQUEST['restore_selected'])) {
$this->restore();
} elseif (isset($_REQUEST['split_selection'])) {
Expand All @@ -80,7 +88,7 @@ public function execute(): void
*/
protected function __construct()
{
$this->messages = array_map('intval', $_REQUEST['msgs']);
$this->messages = array_map('intval', (array) ($_REQUEST['msgs'] ?? []));
}

/**
Expand Down
84 changes: 59 additions & 25 deletions Themes/default/scripts/topic.js
Original file line number Diff line number Diff line change
Expand Up @@ -872,20 +872,41 @@ function InTopicModeration(oOptions)

InTopicModeration.prototype.init = function()
{
/*
* The topic draws two of these strips - one for the page and one for the
* mobile menu - and they share the containers, so the second instance
* finds the checkboxes the first one already made. Collect those once,
* under the message id each one carries, and listen to them as well
* rather than putting a second checkbox beside every post. This file is
* the only thing that emits a msgs[] input, so there is nothing else on
* the page for this to pick up.
*/
var oExisting = {};
var aCheckboxes = document.querySelectorAll('input[name="msgs[]"]');

for (var j = 0, m = aCheckboxes.length; j < m; j++)
oExisting[aCheckboxes[j].value] = aCheckboxes[j];

// Add checkboxes to all the messages.
for (var i = 0, n = this.opt.aMessageIds.length; i < n; i++)
{
// Create the checkbox.
var oCheckbox = document.createElement('input');
oCheckbox.type = 'checkbox';
oCheckbox.className = this.opt.sButtonStrip + '_check';
oCheckbox.name = 'msgs[]';
oCheckbox.value = this.opt.aMessageIds[i];
oCheckbox.onclick = this.handleClick.bind(this, oCheckbox);

// Append it to the container
var oCheckboxContainer = document.getElementById(this.opt.sCheckboxContainerMask + this.opt.aMessageIds[i]);
oCheckboxContainer.appendChild(oCheckbox);
var oCheckbox = oExisting[this.opt.aMessageIds[i]];

if (!oCheckbox)
{
// Create the checkbox.
oCheckbox = document.createElement('input');
oCheckbox.type = 'checkbox';
oCheckbox.className = this.opt.sButtonStrip + '_check';
oCheckbox.name = 'msgs[]';
oCheckbox.value = this.opt.aMessageIds[i];

oCheckboxContainer.appendChild(oCheckbox);
}

oCheckbox.addEventListener('click', this.handleClick.bind(this, oCheckbox));
oCheckboxContainer.style.display = '';
}

Expand All @@ -898,8 +919,8 @@ InTopicModeration.prototype.init = function()
else
{
oButtonStripDisplay = document.createElement('div');
oNewDiv.id = this.opt.sButtonStripDisplay;
oNewDiv.className = this.opt.sButtonStripClass || 'buttonlist floatbottom';
oButtonStripDisplay.id = this.opt.sButtonStripDisplay;
oButtonStripDisplay.className = this.opt.sButtonStripClass || 'buttonlist floatbottom';

oButtonStrip.appendChild(oButtonStripDisplay);
}
Expand Down Expand Up @@ -936,6 +957,14 @@ InTopicModeration.prototype.init = function()
['click', this.handleSubmit.bind(this, 'split')]
]
});

/*
* Nothing is selected yet, so put the buttons in the state that says so.
* They used to be built on the first click instead of here, which is why
* nothing hid them to begin with - and pressing one with an empty
* selection submits the form with no msgs[] at all.
*/
this.updateButtons();
}

InTopicModeration.prototype.handleClick = function(oCheckbox)
Expand All @@ -944,23 +973,28 @@ InTopicModeration.prototype.handleClick = function(oCheckbox)
// Keep stats on how many items were selected.
this.iNumSelected += oCheckbox.checked ? 1 : -1;

// Show the number of messages selected in each of the buttons.
if (this.opt.bCanRemove && !this.opt.bUseImageButton)
{
this.oRemoveButton.innerHTML = this.opt.sRemoveButtonLabel + ' [' + this.iNumSelected + ']';
this.oRemoveButton.style.display = this.iNumSelected < 1 ? "none" : "";
}
this.updateButtons();
}

if (this.opt.bCanRestore && !this.opt.bUseImageButton)
{
this.oRestoreButton.innerHTML = this.opt.sRestoreButtonLabel + ' [' + this.iNumSelected + ']';
this.oRestoreButton.style.display = this.iNumSelected < 1 ? "none" : "";
}
// Show the number of messages selected in each of the buttons, and hide them
// while that number is zero.
InTopicModeration.prototype.updateButtons = function()
{
var aButtons = [
[this.opt.bCanRemove, this.oRemoveButton, this.opt.sRemoveButtonLabel],
[this.opt.bCanRestore, this.oRestoreButton, this.opt.sRestoreButtonLabel],
[this.opt.bCanSplit, this.oSplitButton, this.opt.sSplitButtonLabel]
];

if (this.opt.bCanSplit && !this.opt.bUseImageButton)
for (var i = 0; i < aButtons.length; i++)
{
this.oSplitButton.innerHTML = this.opt.sSplitButtonLabel + ' [' + this.iNumSelected + ']';
this.oSplitButton.style.display = this.iNumSelected < 1 ? "none" : "";
if (!aButtons[i][0] || !aButtons[i][1])
continue;

if (!this.opt.bUseImageButton)
aButtons[i][1].innerHTML = aButtons[i][2] + ' [' + this.iNumSelected + ']';

aButtons[i][1].style.display = this.iNumSelected < 1 ? "none" : "";
}
}

Expand Down