[TASK] Migrate FormEngineSuggest to TypeScript 20/56220/9
authorAndreas Fernandez <a.fernandez@scripting-base.de>
Fri, 16 Mar 2018 12:41:20 +0000 (13:41 +0100)
committerFrank Naegler <frank.naegler@typo3.org>
Wed, 31 Oct 2018 12:48:52 +0000 (13:48 +0100)
The FormEngineSuggest module is migrated to TypeScript now. In the same
step, the usage of jQuery is reduced and dead code has been removed.

Resolves: #82589
Releases: master
Change-Id: I87cf7aafdb68815c9406f5fa29661bf5af6acd85
Reviewed-on: https://review.typo3.org/56220
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
typo3/sysext/backend/Resources/Private/TypeScript/FormEngineSuggest.ts [new file with mode: 0644]
typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js
typo3/sysext/backend/Resources/Public/JavaScript/FormEngineSuggest.js

diff --git a/typo3/sysext/backend/Resources/Private/TypeScript/FormEngineSuggest.ts b/typo3/sysext/backend/Resources/Private/TypeScript/FormEngineSuggest.ts
new file mode 100644 (file)
index 0000000..35b5843
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * 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 * as $ from 'jquery';
+import 'TYPO3/CMS/Core/Contrib/jquery.autocomplete';
+import FormEngine = require('TYPO3/CMS/Backend/FormEngine');
+
+// data structure returned by SuggestWizardDefaultReceiver::queryTable()
+interface SuggestEntry {
+  table: string;
+  uid: number;
+
+  label: string;
+  // The HTML content for the suggest option
+  text: string;
+  // The record path
+  path: string;
+
+  style: string;
+  class: string;
+  // the icon
+  sprite: string;
+}
+
+interface TransformedSuggestEntry {
+  value: string;
+  data: SuggestEntry;
+}
+
+class FormEngineSuggest {
+  constructor(element: HTMLElement) {
+    $((): void => {
+      this.initialize(element);
+    });
+  }
+
+  private initialize(searchField: HTMLElement): void {
+    const containerElement: Element = searchField.closest('.t3-form-suggest-container');
+    const tableName: string = searchField.dataset.tablename;
+    const fieldName: string = searchField.dataset.fieldname;
+    const formEl: string = searchField.dataset.field;
+    const uid: number = parseInt(searchField.dataset.uid, 10);
+    const pid: number = parseInt(searchField.dataset.pid, 10);
+    const dataStructureIdentifier: string = searchField.dataset.datastructureidentifier;
+    const flexFormSheetName: string = searchField.dataset.flexformsheetname;
+    const flexFormFieldName: string = searchField.dataset.flexformfieldname;
+    const flexFormContainerName: string = searchField.dataset.flexformcontainername;
+    const flexFormContainerFieldName: string = searchField.dataset.flexformcontainerfieldname;
+    const minimumCharacters: number = parseInt(searchField.dataset.minchars, 10);
+    const url: string = TYPO3.settings.ajaxUrls.record_suggest;
+    const params = {
+      tableName,
+      fieldName,
+      uid,
+      pid,
+      dataStructureIdentifier,
+      flexFormSheetName,
+      flexFormFieldName,
+      flexFormContainerName,
+      flexFormContainerFieldName
+    };
+
+    function insertValue(element: HTMLElement): void {
+      let insertData: string = '';
+      if (searchField.dataset.fieldtype === 'select') {
+        insertData = element.dataset.uid;
+      } else {
+        insertData = element.dataset.table + '_' + element.dataset.uid;
+      }
+      FormEngine.setSelectOptionFromExternalSource(formEl, insertData, element.dataset.label, element.dataset.label);
+      FormEngine.Validation.markFieldAsChanged($(document.querySelector('input[name="' + formEl + '"]')));
+    }
+
+    $(searchField).autocomplete({
+      // ajax options
+      serviceUrl: url,
+      params: params,
+      type: 'POST',
+      paramName: 'value',
+      dataType: 'json',
+      minChars: minimumCharacters,
+      groupBy: 'typeLabel',
+      containerClass: 'autocomplete-results',
+      appendTo: containerElement,
+      forceFixPosition: false,
+      preserveInput: true,
+      showNoSuggestionNotice: true,
+      noSuggestionNotice: '<div class="autocomplete-info">No results</div>',
+      minLength: minimumCharacters,
+      preventBadQueries: false,
+      // put the AJAX results in the right format
+      transformResult: (response: Array<SuggestEntry>): {suggestions: Array<TransformedSuggestEntry>} => {
+        return {
+          suggestions: response.map((dataItem: SuggestEntry): {value: string, data: SuggestEntry} => {
+            return {value: dataItem.text, data: dataItem};
+          })
+        };
+      },
+      // Rendering of each item
+      formatResult: (suggestion: {data: SuggestEntry}): string => {
+        return $('<div>').append(
+          $('<a class="autocomplete-suggestion-link" href="#">' +
+            suggestion.data.sprite + suggestion.data.text +
+            '</a></div>').attr({
+            'data-label': suggestion.data.label,
+            'data-table': suggestion.data.table,
+            'data-uid': suggestion.data.uid
+          })).html();
+      },
+      onSearchComplete: function(): void {
+        containerElement.classList.add('open');
+      },
+      beforeRender: function(container: JQuery): void {
+        // Unset height, width and z-index again, should be fixed by the plugin at a later point
+        container.attr('style', '');
+        containerElement.classList.add('open');
+      },
+      onHide: function(): void {
+        containerElement.classList.remove('open');
+      },
+      onSelect: function(): void {
+        insertValue(<HTMLElement>(containerElement.querySelector('.autocomplete-selected a')));
+      }
+    });
+  }
+}
+
+export = FormEngineSuggest;
index f6ff5f2..a32fe47 100644 (file)
@@ -1031,7 +1031,9 @@ define(['jquery',
     }
     if ($('.t3-form-suggest').length) {
       require(['TYPO3/CMS/Backend/FormEngineSuggest'], function(Suggest) {
-        Suggest($('.t3-form-suggest'));
+        $('.t3-form-suggest').each(function(index, suggestElement) {
+          new Suggest(suggestElement);
+        });
       });
     }
     // Apply DatePicker to all date time fields
index e54c8fc..17a072d 100644 (file)
  *
  * The TYPO3 project - inspiring people to share!
  */
-
-/**
- * Module: TYPO3/CMS/Backend/FormEngineSuggest
- * Functionality to load suggest functionality
- */
-define(['jquery', 'jquery/autocomplete'], function($) {
-  var initialize = function($searchField) {
-    var $containerElement = $searchField.closest('.t3-form-suggest-container');
-    var tableName = $searchField.data('tablename'),
-      fieldName = $searchField.data('fieldname'),
-      formEl = $searchField.data('field'),
-      uid = $searchField.data('uid'),
-      pid = $searchField.data('pid'),
-      dataStructureIdentifier = $searchField.data('datastructureidentifier'),
-      flexFormSheetName = $searchField.data('flexformsheetname'),
-      flexFormFieldName = $searchField.data('flexformfieldname'),
-      flexFormContainerName = $searchField.data('flexformcontainername'),
-      flexFormContainerFieldName = $searchField.data('flexformcontainerfieldname'),
-      minimumCharacters = $searchField.data('minchars'),
-      url = TYPO3.settings.ajaxUrls['record_suggest'],
-      params = {
-        'tableName': tableName,
-        'fieldName': fieldName,
-        'uid': uid,
-        'pid': pid,
-        'dataStructureIdentifier': dataStructureIdentifier,
-        'flexFormSheetName': flexFormSheetName,
-        'flexFormFieldName': flexFormFieldName,
-        'flexFormContainerName': flexFormContainerName,
-        'flexFormContainerFieldName': flexFormContainerFieldName
-      },
-      insertValue = function(element) {
-        var insertData = '';
-        if ($searchField.data('fieldtype') === 'select') {
-          insertData = $(element).data('uid');
-        } else {
-          insertData = $(element).data('table') + '_' + $(element).data('uid');
-        }
-        var labelEl = $('<div>').html($(element).data('label'));
-        var label = labelEl.text();
-        var title = labelEl.find('span').attr('title') || label;
-        setFormValueFromBrowseWin(formEl, insertData, label, title);
-        TBE_EDITOR.fieldChanged(tableName, uid, fieldName, formEl);
-      };
-
-    $searchField.autocomplete({
-      // ajax options
-      serviceUrl: url,
-      params: params,
-      type: 'POST',
-      paramName: 'value',
-      dataType: 'json',
-      minChars: minimumCharacters,
-      groupBy: 'typeLabel',
-      containerClass: 'autocomplete-results',
-      appendTo: $containerElement,
-      forceFixPosition: false,
-      preserveInput: true,
-      showNoSuggestionNotice: true,
-      noSuggestionNotice: '<div class="autocomplete-info">No results</div>',
-      minLength: minimumCharacters,
-      preventBadQueries: false,
-      // put the AJAX results in the right format
-      transformResult: function(response) {
-        return {
-          suggestions: $.map(response, function(dataItem) {
-            return {value: dataItem.text, data: dataItem};
-          })
-        };
-      },
-      // Rendering of each item
-      formatResult: function(suggestion, value) {
-        return $('<div>').append(
-          $('<a class="autocomplete-suggestion-link" href="#">' +
-            suggestion.data.sprite + suggestion.data.text +
-            '</a></div>').attr({
-            'data-label': suggestion.data.label,
-            'data-table': suggestion.data.table,
-            'data-uid': suggestion.data.uid
-          })).html();
-      },
-      onSearchComplete: function() {
-        $containerElement.addClass('open');
-      },
-      beforeRender: function(container) {
-        // Unset height, width and z-index again, should be fixed by the plugin at a later point
-        container.attr('style', '');
-        $containerElement.addClass('open');
-      },
-      onHide: function() {
-        $containerElement.removeClass('open');
-      },
-      onSelect: function() {
-        insertValue($containerElement.find('.autocomplete-selected a')[0]);
-      }
-    });
-
-    // set up the events
-    $containerElement.on('click', '.autocomplete-suggestion-link', function(evt) {
-      evt.preventDefault();
-    });
-  };
-
-  /**
-   * Return a function that gets DOM elements that are checked if suggest is already initialized
-   * @exports TYPO3/CMS/Backend/FormEngineSuggest
-   */
-  return function(selectorElements) {
-    $(selectorElements).each(function(key, el) {
-      if (!$(el).data('t3-suggest-initialized')) {
-        initialize($(el));
-        $(el).data('t3-suggest-initialized', true);
-      }
-    });
-  };
-});
+define(["require","exports","jquery","TYPO3/CMS/Backend/FormEngine","TYPO3/CMS/Core/Contrib/jquery.autocomplete"],function(e,t,a,n){"use strict";return function(){function e(e){var t=this;a(function(){t.initialize(e)})}return e.prototype.initialize=function(e){var t=e.closest(".t3-form-suggest-container"),i=e.dataset.tablename,r=e.dataset.fieldname,o=e.dataset.field,s=parseInt(e.dataset.uid,10),d=parseInt(e.dataset.pid,10),l=e.dataset.datastructureidentifier,u=e.dataset.flexformsheetname,c=e.dataset.flexformfieldname,m=e.dataset.flexformcontainername,f=e.dataset.flexformcontainerfieldname,p=parseInt(e.dataset.minchars,10),g=TYPO3.settings.ajaxUrls.record_suggest,x={tableName:i,fieldName:r,uid:s,pid:d,dataStructureIdentifier:l,flexFormSheetName:u,flexFormFieldName:c,flexFormContainerName:m,flexFormContainerFieldName:f};a(e).autocomplete({serviceUrl:g,params:x,type:"POST",paramName:"value",dataType:"json",minChars:p,groupBy:"typeLabel",containerClass:"autocomplete-results",appendTo:t,forceFixPosition:!1,preserveInput:!0,showNoSuggestionNotice:!0,noSuggestionNotice:'<div class="autocomplete-info">No results</div>',minLength:p,preventBadQueries:!1,transformResult:function(e){return{suggestions:e.map(function(e){return{value:e.text,data:e}})}},formatResult:function(e){return a("<div>").append(a('<a class="autocomplete-suggestion-link" href="#">'+e.data.sprite+e.data.text+"</a></div>").attr({"data-label":e.data.label,"data-table":e.data.table,"data-uid":e.data.uid})).html()},onSearchComplete:function(){t.classList.add("open")},beforeRender:function(e){e.attr("style",""),t.classList.add("open")},onHide:function(){t.classList.remove("open")},onSelect:function(){var i,r;i=t.querySelector(".autocomplete-selected a"),r="",r="select"===e.dataset.fieldtype?i.dataset.uid:i.dataset.table+"_"+i.dataset.uid,n.setSelectOptionFromExternalSource(o,r,i.dataset.label,i.dataset.label),n.Validation.markFieldAsChanged(a(document.querySelector('input[name="'+o+'"]')))}})},e}()});
\ No newline at end of file