[TASK] Migrate SelectElementTree to TypeScript 16/60316/4
authorAndreas Fernandez <a.fernandez@scripting-base.de>
Sat, 23 Mar 2019 10:32:52 +0000 (11:32 +0100)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Sat, 13 Apr 2019 14:01:32 +0000 (16:01 +0200)
This patch migrates FormEngine's SelectElementTree to TypeScript.
Also, a terrible hack that puts the local tree initialitation callback
into global scope has been removed.

Resolves: #87987
Releases: master
Change-Id: Ib34ae7fe4ac1e197af2183b8890cc72e13a900e9
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/60316
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Steffen Frese <steffenf14@gmail.com>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Steffen Frese <steffenf14@gmail.com>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectTreeElement.ts [new file with mode: 0644]
Build/types/TYPO3/index.d.ts
typo3/sysext/backend/Classes/Form/Element/SelectTreeElement.php
typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTree.js
typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTreeElement.js

diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectTreeElement.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectTreeElement.ts
new file mode 100644 (file)
index 0000000..3118412
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+* This file is part of the TYPO3 CMS project.
+*
+* It is free software; you can redistribute it and/or modify it under
+* the terms of the GNU General Public License, either version 2
+* of the License, or any later version.
+*
+* For the full copyright and license information, please read the
+* LICENSE.txt file that was distributed with this source code.
+*
+* The TYPO3 project - inspiring people to share!
+*/
+
+import SelectTree = require('TYPO3/CMS/Backend/FormEngine/Element/SelectTree');
+
+class SelectTreeElement {
+  private readonly treeWrapper: HTMLElement = null;
+  private readonly recordField: HTMLInputElement = null;
+  private readonly callback: Function = null;
+
+  constructor(treeWrapperId: string, treeRecordFieldId: string, callback: Function) {
+    this.treeWrapper = <HTMLElement>document.querySelector('#' + treeWrapperId);
+    this.recordField = <HTMLInputElement>document.querySelector('#' + treeRecordFieldId);
+    this.callback = callback;
+
+    this.initialize();
+  }
+
+  private initialize(): void {
+    const dataUrl = this.generateRequestUrl();
+    const tree = new SelectTree();
+
+    const settings = {
+      dataUrl: dataUrl,
+      showIcons: true,
+      showCheckboxes: true,
+      readOnlyMode: parseInt(this.recordField.dataset.readOnly, 10) === 1,
+      input: this.recordField,
+      exclusiveNodesIdentifiers: this.recordField.dataset.treeExclusiveKeys,
+      validation: JSON.parse(this.recordField.dataset.formengineValidationRules)[0],
+      expandUpToLevel: this.recordField.dataset.treeExpandUpToLevel,
+    };
+    const initialized = tree.initialize(this.treeWrapper, settings);
+    if (!initialized) {
+      return;
+    }
+
+    tree.dispatch.on('nodeSelectedAfter.requestUpdate', this.callback);
+
+    if (this.recordField.dataset.treeShowToolbar) {
+      require(['TYPO3/CMS/Backend/FormEngine/Element/TreeToolbar'], (TreeToolbar: any): void => {
+        const selectTreeToolbar = new TreeToolbar();
+        selectTreeToolbar.initialize(this.treeWrapper);
+      });
+    }
+  }
+
+  private generateRequestUrl(): string {
+    const params = {
+      tableName: this.recordField.dataset.tablename,
+      fieldName: this.recordField.dataset.fieldname,
+      uid: this.recordField.dataset.uid,
+      recordTypeValue: this.recordField.dataset.recordtypevalue,
+      dataStructureIdentifier: this.recordField.dataset.datastructureidentifier !== ''
+        ? JSON.parse(this.recordField.dataset.datastructureidentifier)
+        : '',
+      flexFormSheetName: this.recordField.dataset.flexformsheetname,
+      flexFormFieldName: this.recordField.dataset.flexformfieldname,
+      flexFormContainerName: this.recordField.dataset.flexformcontainername,
+      flexFormContainerIdentifier: this.recordField.dataset.flexformcontaineridentifier,
+      flexFormContainerFieldName: this.recordField.dataset.flexformcontainerfieldname,
+      flexFormSectionContainerIsNew: this.recordField.dataset.flexformsectioncontainerisnew,
+      command: this.recordField.dataset.command,
+    };
+    return TYPO3.settings.ajaxUrls.record_tree_data + '&' + $.param(params);
+  }
+}
+
+export = SelectTreeElement;
index 2e41db0..e4872a5 100644 (file)
@@ -16,7 +16,6 @@ declare namespace TYPO3 {
   export let Modal: any;
   export let OpendocsMenu: any;
   export let Permissions: any;
-  export let Popover: any;
   export let Severity: any;
   export let ShortcutMenu: any;
   export let Storage: any;
@@ -35,6 +34,16 @@ declare namespace TYPO3 {
         public validate(): void;
       }
 
+      export namespace FormEngine {
+        export namespace Element {
+          export class SelectTree {
+            public dispatch: {[key: string]: Function};
+            public constructor();
+            public initialize(selector: HTMLElement|JQuery, settings: {[key: string]: any}): boolean;
+          }
+        }
+      }
+
       export class FormEngine {
         public readonly Validation: FormEngineValidation;
         public legacyFieldChangedCb(): void;
@@ -80,6 +89,10 @@ declare module 'TYPO3/CMS/Backend/FormEngine' {
   export = new TYPO3.CMS.Backend.FormEngine();
 }
 
+declare module 'TYPO3/CMS/Backend/FormEngine/Element/SelectTree' {
+  export = TYPO3.CMS.Backend.FormEngine.Element.SelectTree;
+}
+
 declare module 'TYPO3/CMS/Backend/Wizard' {
   export = new TYPO3.CMS.Backend.Wizard();
 }
index 7941fd4..67b73dd 100644 (file)
@@ -14,6 +14,8 @@ namespace TYPO3\CMS\Backend\Form\Element;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
 /**
  * Render data as a tree.
  *
@@ -78,7 +80,7 @@ class SelectTreeElement extends AbstractFormElement
 
         // Field configuration from TCA:
         $config = $parameterArray['fieldConf']['config'];
-        $readOnly = !empty($config['readOnly']) ? 'true' : 'false';
+        $readOnly = !empty($config['readOnly']) ? 1 : 0;
         $exclusiveKeys = !empty($config['exclusiveKeys']) ? $config['exclusiveKeys'] : '';
         $exclusiveKeys = $exclusiveKeys . ',';
         $appearance = !empty($config['treeConfig']['appearance']) ? $config['treeConfig']['appearance'] : [];
@@ -91,6 +93,7 @@ class SelectTreeElement extends AbstractFormElement
         }
         $heightInPx = $height * $this->itemHeight;
         $treeWrapperId = 'tree_' . $formElementId;
+        $fieldId = 'tree_record_' . $formElementId;
 
         $fieldName = $this->data['fieldName'];
 
@@ -140,7 +143,7 @@ class SelectTreeElement extends AbstractFormElement
         $html[] =       '<div class="form-wizards-wrap">';
         $html[] =           '<div class="form-wizards-element">';
         $html[] =               '<div class="typo3-tceforms-tree">';
-        $html[] =                   '<input class="treeRecord" type="hidden"';
+        $html[] =                   '<input class="treeRecord" type="hidden" id="' . htmlspecialchars($fieldId) . '"';
         $html[] =                       ' data-formengine-validation-rules="' . htmlspecialchars($this->getValidationDataAsJsonString($config)) . '"';
         $html[] =                       ' data-relatedfieldname="' . htmlspecialchars($parameterArray['itemFormElName']) . '"';
         $html[] =                       ' data-tablename="' . htmlspecialchars($this->data['tableName']) . '"';
@@ -165,7 +168,6 @@ class SelectTreeElement extends AbstractFormElement
         $html[] =                   '/>';
         $html[] =               '</div>';
         $html[] =               '<div id="' . $treeWrapperId . '" class="svg-tree-wrapper" style="height: ' . $heightInPx . 'px;"></div>';
-        $html[] =               '<script type="text/javascript">var ' . $treeWrapperId . ' = ' . $this->getTreeOnChangeJs() . '</script>';
         $html[] =           '</div>';
         if ($readOnly === 'false' && !empty($fieldWizardHtml)) {
             $html[] =       '<div class="form-wizards-items-bottom">';
@@ -182,8 +184,14 @@ class SelectTreeElement extends AbstractFormElement
         if ($showHeader) {
             $resultArray['additionalInlineLanguageLabelFiles'][] = 'EXT:core/Resources/Private/Language/locallang_csh_corebe.xlf';
         }
-        $resultArray['requireJsModules']['selectTreeElement'] = [
-            'TYPO3/CMS/Backend/FormEngine/Element/SelectTreeElement' => 'function (SelectTreeElement) { SelectTreeElement.initialize(); }'
+        $resultArray['requireJsModules']['selectTreeElement'] = ['TYPO3/CMS/Backend/FormEngine/Element/SelectTreeElement' => '
+            function(SelectTreeElement) {
+                require([\'jquery\'], function($) {
+                    $(function() {
+                        new SelectTreeElement(' . GeneralUtility::quoteJSvalue($treeWrapperId) . ', ' . GeneralUtility::quoteJSvalue($fieldId) . ', ' . $this->getTreeOnChangeJs() . ');
+                    });
+                });
+            }'
         ];
 
         return $resultArray;
index eb5b40a..6affacd 100644 (file)
@@ -193,9 +193,9 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'],
     SelectTree.prototype.saveCheckboxes = function() {
       if (typeof this.settings.input !== 'undefined') {
         var selectedNodes = this.getSelectedNodes();
-        this.settings.input.val(selectedNodes.map(function(d) {
+        this.settings.input.value = selectedNodes.map(function(d) {
           return d.identifier;
-        }));
+        });
       }
     };
 
index 643336f..1428e08 100644 (file)
  *
  * The TYPO3 project - inspiring people to share!
  */
-
-/**
- * Initialization of the selectTree js component used e.g. for category tree rendering
- */
-define(['jquery', 'TYPO3/CMS/Backend/FormEngine/Element/SelectTree'],
-  function($, SelectTree) {
-    'use strict';
-
-    var SelectTreeElement = {};
-
-    SelectTreeElement.initialize = function() {
-      $(document).ready(function() {
-        $('.typo3-tceforms-tree .treeRecord').each(function(i, element) {
-
-          /**
-           * Hidden input field storing selected elements.
-           * Tree is initialized based on values stored in it's data attributes
-           *
-           * @type {*|jQuery|HTMLElement}
-           */
-          var $treeInput = $(element);
-          var dataParams = {
-            tableName: $treeInput.data('tablename'),
-            fieldName: $treeInput.data('fieldname'),
-            uid: $treeInput.data('uid'),
-            recordTypeValue: $treeInput.data('recordtypevalue'),
-            dataStructureIdentifier: $treeInput.data('datastructureidentifier'),
-            flexFormSheetName: $treeInput.data('flexformsheetname'),
-            flexFormFieldName: $treeInput.data('flexformfieldname'),
-            flexFormContainerName: $treeInput.data('flexformcontainername'),
-            flexFormContainerIdentifier: $treeInput.data('flexformcontaineridentifier'),
-            flexFormContainerFieldName: $treeInput.data('flexformcontainerfieldname'),
-            flexFormSectionContainerIsNew: $treeInput.data('flexformsectioncontainerisnew'),
-            command: $treeInput.data('command')
-          };
-          var $wrapper = $treeInput.parent().siblings('.svg-tree-wrapper');
-          var dataUrl = TYPO3.settings.ajaxUrls.record_tree_data + '&' + $.param(dataParams);
-          var tree = new SelectTree();
-          var initialized = tree.initialize($wrapper, {
-            dataUrl: dataUrl,
-            showIcons: true,
-            showCheckboxes: true,
-            readOnlyMode: $treeInput.data('read-only'),
-            input: $treeInput,
-            exclusiveNodesIdentifiers: $treeInput.data('tree-exclusive-keys'),
-            validation: $treeInput.data('formengine-validation-rules')[0],
-            expandUpToLevel: $treeInput.data('tree-expand-up-to-level')
-          });
-          if (!initialized) {
-            return;
-          }
-
-          tree.dispatch.on('nodeSelectedAfter.requestUpdate', window[$wrapper.attr('id')]);
-
-          if ($treeInput.data('tree-show-toolbar')) {
-            require(['TYPO3/CMS/Backend/FormEngine/Element/TreeToolbar'], function(TreeToolbar) {
-              var selectTreeToolbar = new TreeToolbar();
-              selectTreeToolbar.initialize($wrapper);
-            });
-          }
-        });
-      });
-    };
-
-    return SelectTreeElement;
-  });
+define(["require","exports","TYPO3/CMS/Backend/FormEngine/Element/SelectTree"],function(e,t,r){"use strict";return function(){function t(e,t,r){this.treeWrapper=null,this.recordField=null,this.callback=null,this.treeWrapper=document.querySelector("#"+e),this.recordField=document.querySelector("#"+t),this.callback=r,this.initialize()}return t.prototype.initialize=function(){var t=this,i=this.generateRequestUrl(),a=new r,d={dataUrl:i,showIcons:!0,showCheckboxes:!0,readOnlyMode:1===parseInt(this.recordField.dataset.readOnly,10),input:this.recordField,exclusiveNodesIdentifiers:this.recordField.dataset.treeExclusiveKeys,validation:JSON.parse(this.recordField.dataset.formengineValidationRules)[0],expandUpToLevel:this.recordField.dataset.treeExpandUpToLevel};a.initialize(this.treeWrapper,d)&&(a.dispatch.on("nodeSelectedAfter.requestUpdate",this.callback),this.recordField.dataset.treeShowToolbar&&e(["TYPO3/CMS/Backend/FormEngine/Element/TreeToolbar"],function(e){(new e).initialize(t.treeWrapper)}))},t.prototype.generateRequestUrl=function(){var e={tableName:this.recordField.dataset.tablename,fieldName:this.recordField.dataset.fieldname,uid:this.recordField.dataset.uid,recordTypeValue:this.recordField.dataset.recordtypevalue,dataStructureIdentifier:""!==this.recordField.dataset.datastructureidentifier?JSON.parse(this.recordField.dataset.datastructureidentifier):"",flexFormSheetName:this.recordField.dataset.flexformsheetname,flexFormFieldName:this.recordField.dataset.flexformfieldname,flexFormContainerName:this.recordField.dataset.flexformcontainername,flexFormContainerIdentifier:this.recordField.dataset.flexformcontaineridentifier,flexFormContainerFieldName:this.recordField.dataset.flexformcontainerfieldname,flexFormSectionContainerIsNew:this.recordField.dataset.flexformsectioncontainerisnew,command:this.recordField.dataset.command};return TYPO3.settings.ajaxUrls.record_tree_data+"&"+$.param(e)},t}()});
\ No newline at end of file