Skip to content

Commit

Permalink
[TASK] Use JS module loader instead of requirejs when available
Browse files Browse the repository at this point in the history
  • Loading branch information
NamelessCoder committed Jan 21, 2025
1 parent 2d540b3 commit a677d80
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 34 deletions.
14 changes: 13 additions & 1 deletion Classes/Integration/HookSubscribers/EditDocumentController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,27 @@

class EditDocumentController
{
private static $assetLoaded = false;

Check failure on line 10 in Classes/Integration/HookSubscribers/EditDocumentController.php

View workflow job for this annotation

GitHub Actions / PHPStan, PHP 7.4 TYPO3 ^10.4

Property FluidTYPO3\Flux\Integration\HookSubscribers\EditDocumentController::$assetLoaded has no type specified.

Check failure on line 10 in Classes/Integration/HookSubscribers/EditDocumentController.php

View workflow job for this annotation

GitHub Actions / PHPStan, PHP 8.0 TYPO3 ^11.5

Property FluidTYPO3\Flux\Integration\HookSubscribers\EditDocumentController::$assetLoaded has no type specified.

Check failure on line 10 in Classes/Integration/HookSubscribers/EditDocumentController.php

View workflow job for this annotation

GitHub Actions / PHPStan, PHP 8.1 TYPO3 ^11.5

Property FluidTYPO3\Flux\Integration\HookSubscribers\EditDocumentController::$assetLoaded has no type specified.

Check failure on line 10 in Classes/Integration/HookSubscribers/EditDocumentController.php

View workflow job for this annotation

GitHub Actions / PHPStan, PHP 8.2 TYPO3 ^11.5

Property FluidTYPO3\Flux\Integration\HookSubscribers\EditDocumentController::$assetLoaded has no type specified.

Check failure on line 10 in Classes/Integration/HookSubscribers/EditDocumentController.php

View workflow job for this annotation

GitHub Actions / PHPStan, PHP 8.2 TYPO3 ^12.4

Property FluidTYPO3\Flux\Integration\HookSubscribers\EditDocumentController::$assetLoaded has no type specified.

Check failure on line 10 in Classes/Integration/HookSubscribers/EditDocumentController.php

View workflow job for this annotation

GitHub Actions / PHPStan, PHP 8.3 TYPO3 ^12.4

Property FluidTYPO3\Flux\Integration\HookSubscribers\EditDocumentController::$assetLoaded has no type specified.

/**
* Make sure the FluxColPosAssignment JavaScript module is loaded
*
* @codeCoverageIgnore
*/
public function requireColumnPositionJavaScript() : void
{
if (self::$assetLoaded) {
return;
}

/** @var PageRenderer $pageRenderer */
$pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
$pageRenderer->loadRequireJsModule('TYPO3/CMS/Flux/FluxColPosAssignment');
if (method_exists($pageRenderer, 'loadJavaScriptModule')) {
$pageRenderer->loadJavaScriptModule('@fluidtypo3/flux/FluxColPosAssignment.js');
} else {
$pageRenderer->loadRequireJsModule('TYPO3/CMS/Flux/FluxColPosAssignmentLegacy');
}

self::$assetLoaded = true;
}
}
8 changes: 6 additions & 2 deletions Classes/Integration/PreviewRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use FluidTYPO3\Flux\Provider\ProviderInterface;
use FluidTYPO3\Flux\Provider\ProviderResolver;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Utility\VersionNumberUtility;

class PreviewRenderer
{
Expand Down Expand Up @@ -55,8 +56,11 @@ public function renderPreview(array $row): ?array
protected function attachAssets(): void
{
if (!static::$assetsIncluded) {
$this->pageRenderer->addCssFile('EXT:flux/Resources/Public/css/flux.css');
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Flux/FluxCollapse');
$this->pageRenderer->addCssFile('EXT:flux/Resources/Public/css/flu.css');
if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '12.4', '<')) {
// Collapse feature is inoperable on v12 and above.
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Flux/FluxCollapse');
}

static::$assetsIncluded = true;
}
Expand Down
8 changes: 8 additions & 0 deletions Configuration/JavaScriptModules.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

return [
'dependencies' => ['core', 'backend'],
'imports' => [
'@fluidtypo3/flux/' => 'EXT:flux/Resources/Public/JavaScript/',
]
];
65 changes: 36 additions & 29 deletions Resources/Public/JavaScript/FluxColPosAssignment.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,38 @@
* For the full copyright and license information, please read the
* LICENSE.md file that was distributed with this source code.
*/
define(['jquery'], function ($) {
function isVisibleSection(element) {
class FluxColPosAssignment
{
constructor()
{
var targetNodes = document.querySelectorAll('.t3-flex-container');
var observer = new MutationObserver(this.handleMutation);
Array.prototype.forEach.call(targetNodes, function (targetNode) {
observer.observe(targetNode, { childList: true, characterData: false });
});
}

isVisibleSection(element)
{
var classes = element.classList;
return element.nodeType === Node.ELEMENT_NODE && classes.contains('t3js-flex-section') && !classes.contains('t3js-flex-section-deleted');
}

function getSectionColPosInput(section) {
getSectionColPosInput(section)
{
return section.querySelector('.flux-flex-colPos-input');
}

function getSectionColPosText(section) {
getSectionColPosText(section)
{
return section.querySelector('.flux-flex-colPos-text');
}

function determineCurrentlyTakenColPos(container) {
determineCurrentlyTakenColPos(container)
{
return Array.prototype.reduce.call(container.childNodes, function (acc, containerChild) {
if (isVisibleSection(containerChild)) {
var value = getSectionColPosInput(containerChild).value;
if (colPosAssigner.isVisibleSection(containerChild)) {
var value = colPosAssigner.getSectionColPosInput(containerChild).value;
if (value !== '') {
acc.push(parseInt(value));
}
Expand All @@ -30,16 +44,18 @@ define(['jquery'], function ($) {
}, []);
}

function determineFreeColPos(minColPos, maxColPos, takenColPos) {
determineFreeColPos(minColPos, maxColPos, takenColPos)
{
for (var colPos = minColPos; colPos <= maxColPos; colPos++) {
if (takenColPos.indexOf(colPos) === -1) {
return colPos;
}
}
}

function handleAddedSection(section, container) {
var input = getSectionColPosInput(section);
handleAddedSection(section, container)
{
var input = colPosAssigner.getSectionColPosInput(section);
if (input === null || input.value !== '') {
return;
}
Expand All @@ -49,37 +65,28 @@ define(['jquery'], function ($) {
if (input.dataset.takenValues !== '') {
takenColPos = input.dataset.takenValues.split(',').map(function (colPosStr) { return parseInt(colPosStr); });
}
takenColPos = takenColPos.concat(determineCurrentlyTakenColPos(container));
takenColPos = takenColPos.concat(colPosAssigner.determineCurrentlyTakenColPos(container));

var colPos = determineFreeColPos(minColPos, maxColPos, takenColPos);
var colPos = colPosAssigner.determineFreeColPos(minColPos, maxColPos, takenColPos);
input.value = colPos;

var label = getSectionColPosText(section);
var label = colPosAssigner.getSectionColPosText(section);
label.innerText = colPos;
}

function handleMutation(mutationList) {
handleMutation(mutationList)
{
mutationList.forEach(function (mutation) {
Array.prototype.forEach.call(mutation.addedNodes, function (addedElement) {
if (!isVisibleSection(addedElement)) {
if (!colPosAssigner.isVisibleSection(addedElement)) {
return;
}
handleAddedSection(addedElement, mutation.target);
colPosAssigner.handleAddedSection(addedElement, mutation.target);
});
});
}
};

function init() {
var targetNodes = document.querySelectorAll('.t3-flex-container');
var observer = new MutationObserver(handleMutation);
Array.prototype.forEach.call(targetNodes, function (targetNode) {
observer.observe(targetNode, { childList: true, characterData: false });
});
}

$(function () {
init();
});
var colPosAssigner = new FluxColPosAssignment;

return {};
});
export default colPosAssigner;
85 changes: 85 additions & 0 deletions Resources/Public/JavaScript/FluxColPosAssignmentLegacy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* This file is part of the FluidTYPO3/Flux project under GPLv2 or later.
*
* For the full copyright and license information, please read the
* LICENSE.md file that was distributed with this source code.
*/
define(['jquery'], function ($) {
function isVisibleSection(element) {
var classes = element.classList;
return element.nodeType === Node.ELEMENT_NODE && classes.contains('t3js-flex-section') && !classes.contains('t3js-flex-section-deleted');
}

function getSectionColPosInput(section) {
return section.querySelector('.flux-flex-colPos-input');
}

function getSectionColPosText(section) {
return section.querySelector('.flux-flex-colPos-text');
}

function determineCurrentlyTakenColPos(container) {
return Array.prototype.reduce.call(container.childNodes, function (acc, containerChild) {
if (isVisibleSection(containerChild)) {
var value = getSectionColPosInput(containerChild).value;
if (value !== '') {
acc.push(parseInt(value));
}
}
return acc;
}, []);
}

function determineFreeColPos(minColPos, maxColPos, takenColPos) {
for (var colPos = minColPos; colPos <= maxColPos; colPos++) {
if (takenColPos.indexOf(colPos) === -1) {
return colPos;
}
}
}

function handleAddedSection(section, container) {
var input = getSectionColPosInput(section);
if (input === null || input.value !== '') {
return;
}
var minColPos = parseInt(input.dataset.minValue);
var maxColPos = parseInt(input.dataset.maxValue);
var takenColPos = [];
if (input.dataset.takenValues !== '') {
takenColPos = input.dataset.takenValues.split(',').map(function (colPosStr) { return parseInt(colPosStr); });
}
takenColPos = takenColPos.concat(determineCurrentlyTakenColPos(container));

var colPos = determineFreeColPos(minColPos, maxColPos, takenColPos);
input.value = colPos;

var label = getSectionColPosText(section);
label.innerText = colPos;
}

function handleMutation(mutationList) {
mutationList.forEach(function (mutation) {
Array.prototype.forEach.call(mutation.addedNodes, function (addedElement) {
if (!isVisibleSection(addedElement)) {
return;
}
handleAddedSection(addedElement, mutation.target);
});
});
}

function init() {
var targetNodes = document.querySelectorAll('.t3-flex-container');
var observer = new MutationObserver(handleMutation);
Array.prototype.forEach.call(targetNodes, function (targetNode) {
observer.observe(targetNode, { childList: true, characterData: false });
});
}

$(function () {
init();
});

return {};
});
12 changes: 10 additions & 2 deletions Tests/Unit/Integration/PreviewRendererTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,24 @@
use FluidTYPO3\Flux\Provider\ProviderResolver;
use FluidTYPO3\Flux\Tests\Unit\AbstractTestCase;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Utility\VersionNumberUtility;

class PreviewRendererTest extends AbstractTestCase
{
private PageRenderer $pageRenderer;
private ProviderResolver $providerResolver;
private string $registerMethodName;

protected function setUp(): void
{
if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '13.4', '>=')) {
$this->registerMethodName = 'loadJavaScriptModule';
} else {
$this->registerMethodName = 'loadRequireJsModule';
}

$this->pageRenderer = $this->getMockBuilder(PageRenderer::class)
->onlyMethods(['loadRequireJsModule'])
->onlyMethods([$this->registerMethodName])
->disableOriginalConstructor()
->getMock();
$this->providerResolver = $this->getMockBuilder(ProviderResolver::class)
Expand Down Expand Up @@ -56,7 +64,7 @@ public function testPreProcess(): void

public function testAttachAssets(): void
{
$this->pageRenderer->expects($this->atLeastOnce())->method('loadRequireJsModule');
$this->pageRenderer->expects($this->atLeastOnce())->method($this->registerMethodName);
$subject = new PreviewRenderer($this->pageRenderer, $this->providerResolver);
$this->callInaccessibleMethod($subject, 'attachAssets');
}
Expand Down

0 comments on commit a677d80

Please sign in to comment.