[TASK] Remove dependency to tab.js in FormEngine 47/39347/6
authorWouter Wolters <typo3@wouterwolters.nl>
Thu, 7 May 2015 22:08:04 +0000 (00:08 +0200)
committerFrank Nägler <typo3@naegler.net>
Fri, 8 May 2015 23:12:25 +0000 (01:12 +0200)
Resolves: #66849
Releases: master
Change-Id: Iad61ca580344c9794d8ad19721c11689fc5a2e16
Reviewed-on: http://review.typo3.org/39347
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Frank Nägler <typo3@naegler.net>
Tested-by: Frank Nägler <typo3@naegler.net>
12 files changed:
Build/Gruntfile.js
Build/bower.json
typo3/sysext/backend/Classes/Controller/File/EditFileController.php
typo3/sysext/backend/Classes/Form/Element/TextElement.php
typo3/sysext/backend/Classes/Form/FormEngine.php
typo3/sysext/backend/Classes/Template/DocumentTemplate.php
typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js
typo3/sysext/backend/Resources/Public/JavaScript/tab.js [deleted file]
typo3/sysext/core/Classes/Page/PageRenderer.php
typo3/sysext/core/Resources/Public/JavaScript/Contrib/taboverride.min.js [new file with mode: 0644]
typo3/sysext/t3editor/Classes/T3editor.php
typo3/sysext/t3editor/Resources/Public/JavaScript/T3editor.js [new file with mode: 0644]

index e6337c0..6a2b74a 100644 (file)
@@ -54,6 +54,7 @@ module.exports = function(grunt) {
                                        '<%= paths.core %>Public/JavaScript/Contrib/bootstrap-datetimepicker.js': '/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js',
                                        '<%= paths.core %>Public/JavaScript/Contrib/autosize.js': '/autosize/dest/autosize.min.js',
                                        '<%= paths.core %>Public/JavaScript/Contrib/placeholders.jquery.min.js': '/Placeholders.js/dist/placeholders.jquery.min.js',
+                                       '<%= paths.core %>Public/JavaScript/Contrib/taboverride.min.js': '/taboverride/build/output/taboverride.min.js',
 
                                        /**
                                         * copy needed files of scriptaculous
index 09e188b..b7fbad5 100644 (file)
@@ -37,6 +37,7 @@
     "autosize": "2.0.0",
     "cropper": "0.9.1",
     "imagesloaded": "3.1.8",
-    "Placeholders.js": "4.0.1"
+    "Placeholders.js": "4.0.1",
+    "taboverride": "4.0.2"
   }
 }
index b8f0d83..8dbe53e 100644 (file)
@@ -161,7 +161,7 @@ class EditFileController {
                        // Edit textarea:
                        $code .= '
                                <div id="c-edit">
-                                       <textarea rows="30" name="file[editfile][0][data]" wrap="off" ' . $this->doc->formWidth(48, TRUE, 'width:98%;height:80%') . ' class="text-monospace enable-tab">' . GeneralUtility::formatForTextarea($fileContent) . '</textarea>
+                                       <textarea rows="30" name="file[editfile][0][data]" wrap="off" ' . $this->doc->formWidth(48, TRUE, 'width:98%;height:80%') . ' class="text-monospace t3js-enable-tab">' . GeneralUtility::formatForTextarea($fileContent) . '</textarea>
                                        <input type="hidden" name="file[editfile][0][target]" value="' . $this->fileObject->getUid() . '" />
                                        <input type="hidden" name="redirect" value="' . htmlspecialchars($hValue) . '" />
                                        ' . \TYPO3\CMS\Backend\Form\FormEngine::getHiddenTokenField('tceAction') . '
index 328b54a..d7e36ef 100644 (file)
@@ -201,7 +201,7 @@ class TextElement extends AbstractFormElement {
                                        $classes[] = 'text-monospace';
                                }
                                if ($specialConfiguration['enable-tab']) {
-                                       $classes[] = 'enable-tab';
+                                       $classes[] = 't3js-enable-tab';
                                }
 
                                // calculate styles
index bb65edb..6f39419 100644 (file)
@@ -1076,8 +1076,6 @@ class FormEngine {
                if ($this->extJSCODE) {
                        $jsonArray['scriptCall'][] = $this->extJSCODE;
                }
-               // activate "enable tabs" for textareas
-               $jsonArray['scriptCall'][] = 'changeTextareaElements();';
                return $jsonArray;
        }
 
index 32d64e9..d2af784 100644 (file)
@@ -810,11 +810,7 @@ function jumpToUrl(URL) {
 
                $languageCode = $this->pageRenderer->getLanguage() === 'default' ? 'en' : $this->pageRenderer->getLanguage();
                $this->pageRenderer->setHtmlTag('<html lang="' . $languageCode . '">');
-               // This loads the tabulator-in-textarea feature. It automatically modifies
-               // every textarea which is found.
-               if (!$GLOBALS['BE_USER']->uc['disableTabInTextarea']) {
-                       $this->pageRenderer->addJsFile($this->backPath . 'sysext/backend/Resources/Public/JavaScript/tab.js');
-               }
+
                // Include the JS for the Context Sensitive Help
                // @todo: right now this is a hard dependency on csh manual, as the whole help system should be moved to
                // the extension. The core provides a API for adding help, and rendering help, but the rendering
index de80ace..298776a 100644 (file)
@@ -701,6 +701,18 @@ define('TYPO3/CMS/Backend/FormEngine', ['jquery'], function ($) {
        };
 
        /**
+        * convert all textareas to enable tab
+        */
+       FormEngine.convertTextareasEnableTab = function() {
+               var $elements = $('.t3js-enable-tab');
+               if ($elements.length) {
+                       require(['taboverride'], function(taboverride) {
+                               taboverride.set($elements);
+                       });
+               }
+       };
+
+       /**
         * this is the main function that is called on page load, but also after elements are asynchroniously
         * called e.g. after IRRE elements are loaded again, or a new flexform section is added.
         * use this function in your extension like this "TYPO3.FormEngine.initialize()"
@@ -719,6 +731,7 @@ define('TYPO3/CMS/Backend/FormEngine', ['jquery'], function ($) {
                        DateTimePicker.initialize();
                });
                FormEngine.convertTextareasResizable();
+               FormEngine.convertTextareasEnableTab();
                $(document).on('click', '.t3js-editform-close', function(e) {
                        e.preventDefault();
                        FormEngine.preventExitIfNotSaved();
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/tab.js b/typo3/sysext/backend/Resources/Public/JavaScript/tab.js
deleted file mode 100644 (file)
index 145fab9..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * This code has been copied from Project_CMS
- * Copyright (c) 2005 by Phillip Berndt (www.pberndt.com)
- *
- * Extended Textarea for IE and Firefox browsers
- * Features:
- *  - Possibility to place tabs in <textarea> elements using a simply <TAB> key
- *  - Auto-indenting of new lines
- *
- * License: GNU General Public License
- */
-
-function checkBrowser() {
-       browserName = navigator.appName;
-       browserVer = parseInt(navigator.appVersion);
-
-       ok = false;
-       if (browserName == "Microsoft Internet Explorer" && browserVer >= 4) {
-               ok = true;
-       } else if (browserName == "Netscape" && browserVer >= 3) {
-               ok = true;
-       }
-
-       return ok;
-}
-
-       // Automatically change all textarea elements
-function changeTextareaElements() {
-       if (!checkBrowser()) {
-                       // Stop unless we're using IE or Netscape (includes Mozilla family)
-               return false;
-       }
-
-       document.textAreas = document.getElementsByTagName("textarea");
-
-       for (i = 0; i < document.textAreas.length; i++) {
-                       // Only change if the class parameter contains "enable-tab"
-               if (document.textAreas[i].className && document.textAreas[i].className.search(/(^| )enable-tab( |$)/) != -1) {
-                       document.textAreas[i].textAreaID = i;
-                       makeAdvancedTextArea(document.textAreas[i]);
-               }
-       }
-}
-
-       // Wait until the document is completely loaded.
-       // Set a timeout instead of using the onLoad() event because it could be used by something else already.
-window.setTimeout("changeTextareaElements();", 200);
-
-       // Turn textarea elements into "better" ones. Actually this is just adding some lines of JavaScript...
-function makeAdvancedTextArea(textArea) {
-       if (textArea.tagName.toLowerCase() != "textarea") {
-               return false;
-       }
-
-               // On attempt to leave the element:
-               // Do not leave if this.dontLeave is true
-       textArea.onblur = function(e) {
-               if (!this.dontLeave) {
-                       return;
-               }
-               this.dontLeave = null;
-               window.setTimeout("document.textAreas[" + this.textAreaID + "].restoreFocus()", 1);
-               return false;
-       }
-
-               // Set the focus back to the element and move the cursor to the correct position.
-       textArea.restoreFocus = function() {
-               this.focus();
-
-               if (this.caretPos) {
-                       this.caretPos.collapse(false);
-                       this.caretPos.select();
-               }
-       }
-
-               // Determine the current cursor position
-       textArea.getCursorPos = function() {
-               if (this.selectionStart) {
-                       currPos = this.selectionStart;
-               } else if (this.caretPos) {     // This is very tricky in IE :-(
-                       oldText = this.caretPos.text;
-                       finder = "--getcurrpos" + Math.round(Math.random() * 10000) + "--";
-                       this.caretPos.text += finder;
-                       currPos = this.value.indexOf(finder);
-
-                       this.caretPos.moveStart('character', -finder.length);
-                       this.caretPos.text = "";
-
-                       this.caretPos.scrollIntoView(true);
-               } else {
-                       return;
-               }
-
-               return currPos;
-       }
-
-               // On tab, insert a tabulator. Otherwise, check if a slash (/) was pressed.
-       textArea.onkeydown = function(e) {
-               if (this.selectionStart == null &! this.createTextRange) {
-                       return;
-               }
-               if (!e) {
-                       e = window.event;
-               }
-
-                       // Tabulator
-               if (e.keyCode == 9) {
-                       this.dontLeave = true;
-                       this.textInsert(String.fromCharCode(9));
-               }
-
-                       // Newline
-               if (e.keyCode == 13) {
-                               // Get the cursor position
-                       currPos = this.getCursorPos();
-
-                               // Search the last line
-                       lastLine = "";
-                       for (i = currPos - 1; i >= 0; i--) {
-                               if(this.value.substring(i, i + 1) == '\n') {
-                                       break;
-                               }
-                       }
-                       lastLine = this.value.substring(i + 1, currPos);
-
-                               // Search for whitespaces in the current line
-                       whiteSpace = "";
-                       for (i = 0; i < lastLine.length; i++) {
-                               if (lastLine.substring(i, i + 1) == '\t') {
-                                       whiteSpace += "\t";
-                               } else if (lastLine.substring(i, i + 1) == ' ') {
-                                       whiteSpace += " ";
-                               } else {
-                                       break;
-                               }
-                       }
-
-                               // Another ugly IE hack
-                       if (navigator.appVersion.match(/MSIE/)) {
-                               whiteSpace = "\\n" + whiteSpace;
-                       }
-
-                               // Insert whitespaces
-                       window.setTimeout("document.textAreas["+this.textAreaID+"].textInsert(\""+whiteSpace+"\");", 1);
-               }
-       }
-
-               // Save the current cursor position in IE
-       textArea.onkeyup = textArea.onclick = textArea.onselect = function(e) {
-               if (this.createTextRange) {
-                       this.caretPos = document.selection.createRange().duplicate();
-               }
-       }
-
-               // Insert text at the current cursor position
-       textArea.textInsert = function(insertText) {
-               if (this.selectionStart != null) {
-                       var savedScrollTop = this.scrollTop;
-                       var begin = this.selectionStart;
-                       var end = this.selectionEnd;
-                       if (end > begin + 1) {
-                               this.value = this.value.substr(0, begin) + insertText + this.value.substr(end);
-                       } else {
-                               this.value = this.value.substr(0, begin) + insertText + this.value.substr(begin);
-                       }
-
-                       this.selectionStart = begin + insertText.length;
-                       this.selectionEnd = begin + insertText.length;
-                       this.scrollTop = savedScrollTop;
-               } else if (this.caretPos) {
-                       this.caretPos.text = insertText;
-                       this.caretPos.scrollIntoView(true);
-               } else {
-                       text.value += insertText;
-               }
-
-               this.focus();
-       }
-}
\ No newline at end of file
index d6f4b40..1194462 100644 (file)
@@ -1606,7 +1606,8 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface {
                                'imagesloaded' => $this->backPath . 'sysext/core/Resources/Public/JavaScript/Contrib/imagesloaded.pkgd.min',
                                'bootstrap' => $this->backPath . 'sysext/core/Resources/Public/JavaScript/Contrib/bootstrap/bootstrap',
                                'twbs/bootstrap-datetimepicker' => $this->backPath . 'sysext/core/Resources/Public/JavaScript/Contrib/bootstrap-datetimepicker',
-                               'autosize' => $this->backPath . 'sysext/core/Resources/Public/JavaScript/Contrib/autosize'
+                               'autosize' => $this->backPath . 'sysext/core/Resources/Public/JavaScript/Contrib/autosize',
+                               'taboverride' => $this->backPath . 'sysext/core/Resources/Public/JavaScript/Contrib/taboverride.min',
                        );
                        // get all extensions that are loaded
                        $loadedExtensions = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getLoadedExtensionListArray();
diff --git a/typo3/sysext/core/Resources/Public/JavaScript/Contrib/taboverride.min.js b/typo3/sysext/core/Resources/Public/JavaScript/Contrib/taboverride.min.js
new file mode 100644 (file)
index 0000000..315163b
--- /dev/null
@@ -0,0 +1,4 @@
+/*! taboverride v4.0.2 | https://github.com/wjbryant/taboverride
+Copyright (c) 2014 Bill Bryant | http://opensource.org/licenses/mit */
+!function(a){"use strict";var b;"object"==typeof exports?a(exports):"function"==typeof define&&define.amd?define(["exports"],a):(b=window.tabOverride={},a(b))}(function(a){"use strict";function b(a,b){var c,d,e,f=["alt","ctrl","meta","shift"],g=a.length,h=!0;for(c=0;g>c;c+=1)if(!b[a[c]]){h=!1;break}if(h)for(c=0;c<f.length;c+=1){if(e=f[c]+"Key",b[e])if(g){for(h=!1,d=0;g>d;d+=1)if(e===a[d]){h=!0;break}}else h=!1;if(!h)break}return h}function c(a,c){return a===q&&b(s,c)}function d(a,c){return a===r&&b(t,c)}function e(a,b){return function(c,d){var e,f="";if(arguments.length){if("number"==typeof c&&(a(c),b.length=0,d&&d.length))for(e=0;e<d.length;e+=1)b.push(d[e]+"Key");return this}for(e=0;e<b.length;e+=1)f+=b[e].slice(0,-3)+"+";return f+a()}}function f(a){a=a||event;var b,e,f,g,h,i,j,k,l,s,t,w,x,y,z,A,B,C,D=a.currentTarget||a.srcElement,E=a.keyCode,F="character";if((!D.nodeName||"textarea"===D.nodeName.toLowerCase())&&(E===q||E===r||13===E&&u)){if(v=!1,f=D.value,k=D.scrollTop,"number"==typeof D.selectionStart)l=D.selectionStart,s=D.selectionEnd,t=f.slice(l,s);else{if(!o.selection)return;g=o.selection.createRange(),t=g.text,h=g.duplicate(),h.moveToElementText(D),h.setEndPoint("EndToEnd",g),s=h.text.length,l=s-t.length,n>1?(i=f.slice(0,l).split(m).length-1,j=t.split(m).length-1):i=j=0}if(E===q||E===r)if(b=p,e=b.length,y=0,z=0,A=0,l!==s&&-1!==t.indexOf("\n"))if(w=0===l||"\n"===f.charAt(l-1)?l:f.lastIndexOf("\n",l-1)+1,s===f.length||"\n"===f.charAt(s)?x=s:"\n"===f.charAt(s-1)?x=s-1:(x=f.indexOf("\n",s),-1===x&&(x=f.length)),c(E,a))y=1,D.value=f.slice(0,w)+b+f.slice(w,x).replace(/\n/g,function(){return y+=1,"\n"+b})+f.slice(x),g?(g.collapse(),g.moveEnd(F,s+y*e-j-i),g.moveStart(F,l+e-i),g.select()):(D.selectionStart=l+e,D.selectionEnd=s+y*e,D.scrollTop=k);else{if(!d(E,a))return;0===f.slice(w).indexOf(b)&&(w===l?t=t.slice(e):A=e,z=e),D.value=f.slice(0,w)+f.slice(w+A,l)+t.replace(new RegExp("\n"+b,"g"),function(){return y+=1,"\n"})+f.slice(s),g?(g.collapse(),g.moveEnd(F,s-z-y*e-j-i),g.moveStart(F,l-A-i),g.select()):(D.selectionStart=l-A,D.selectionEnd=s-z-y*e)}else if(c(E,a))g?(g.text=b,g.select()):(D.value=f.slice(0,l)+b+f.slice(s),D.selectionEnd=D.selectionStart=l+e,D.scrollTop=k);else{if(!d(E,a))return;0===f.slice(l-e).indexOf(b)&&(D.value=f.slice(0,l-e)+f.slice(l),g?(g.move(F,l-e-i),g.select()):(D.selectionEnd=D.selectionStart=l-e,D.scrollTop=k))}else if(u){if(0===l||"\n"===f.charAt(l-1))return void(v=!0);if(w=f.lastIndexOf("\n",l-1)+1,x=f.indexOf("\n",l),-1===x&&(x=f.length),B=f.slice(w,x).match(/^[ \t]*/)[0],C=B.length,w+C>l)return void(v=!0);g?(g.text="\n"+B,g.select()):(D.value=f.slice(0,l)+"\n"+B+f.slice(s),D.selectionEnd=D.selectionStart=l+n+C,D.scrollTop=k)}return a.preventDefault?void a.preventDefault():(a.returnValue=!1,!1)}}function g(a){a=a||event;var b=a.keyCode;if(c(b,a)||d(b,a)||13===b&&u&&!v){if(!a.preventDefault)return a.returnValue=!1,!1;a.preventDefault()}}function h(a,b){var c,d=x[a]||[],e=d.length;for(c=0;e>c;c+=1)d[c].apply(null,b)}function i(a){function b(b){for(c=0;f>c;c+=1)b(a[c].type,a[c].handler)}var c,d,e,f=a.length;return o.addEventListener?(d=function(a){b(function(b,c){a.removeEventListener(b,c,!1)})},e=function(a){d(a),b(function(b,c){a.addEventListener(b,c,!1)})}):o.attachEvent&&(d=function(a){b(function(b,c){a.detachEvent("on"+b,c)})},e=function(a){d(a),b(function(b,c){a.attachEvent("on"+b,c)})}),{add:e,remove:d}}function j(a){h("addListeners",[a]),l.add(a)}function k(a){h("removeListeners",[a]),l.remove(a)}var l,m,n,o=window.document,p="        ",q=9,r=9,s=[],t=["shiftKey"],u=!0,v=!1,w=o.createElement("textarea"),x={};l=i([{type:"keydown",handler:f},{type:"keypress",handler:g}]),w.value="\n",m=w.value,n=m.length,w=null,a.utils={executeExtensions:h,isValidModifierKeyCombo:b,createListeners:i,addListeners:j,removeListeners:k},a.handlers={keydown:f,keypress:g},a.addExtension=function(a,b){return a&&"string"==typeof a&&"function"==typeof b&&(x[a]||(x[a]=[]),x[a].push(b)),this},a.set=function(a,b){var c,d,e,f,g,i,l;if(a)for(c=arguments.length<2||b,d=a,e=d.length,"number"!=typeof e&&(d=[d],e=1),c?(f=j,g="true"):(f=k,g=""),i=0;e>i;i+=1)l=d[i],l&&l.nodeName&&"textarea"===l.nodeName.toLowerCase()&&(h("set",[l,c]),l.setAttribute("data-taboverride-enabled",g),f(l));return this},a.tabSize=function(a){var b;if(arguments.length){if(a&&"number"==typeof a&&a>0)for(p="",b=0;a>b;b+=1)p+=" ";else p="   ";return this}return"   "===p?0:p.length},a.autoIndent=function(a){return arguments.length?(u=a?!0:!1,this):u},a.tabKey=e(function(a){return arguments.length?void(q=a):q},s),a.untabKey=e(function(a){return arguments.length?void(r=a):r},t)});
+//# sourceMappingURL=taboverride.min.js.map
\ No newline at end of file
index df0d677..dc83873 100644 (file)
@@ -177,6 +177,7 @@ class T3editor implements \TYPO3\CMS\Core\SingletonInterface {
                        // Include editor-js-lib
                        $doc->loadJavascriptLib($path_codemirror . 'codemirror.js');
                        $doc->loadJavascriptLib($path_t3e . 'res/jslib/t3editor.js');
+                       $pageRenderer->loadRequireJsModule('TYPO3/CMS/T3editor/T3editor');
 
                        $content .= \TYPO3\CMS\Core\Utility\GeneralUtility::wrapJS(
                                'T3editor = T3editor || {};' .
diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/T3editor.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/T3editor.js
new file mode 100644 (file)
index 0000000..adc0356
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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!
+ */
+
+define('TYPO3/CMS/T3editor/T3editor', ['jquery'], function ($) {
+
+       var T3editor = {};
+
+       /**
+        * Convert all textareas to enable tab
+        */
+       T3editor.convertTextareasEnableTab = function() {
+               var $elements = $('.enable-tab');
+               if ($elements.length) {
+                       require(['taboverride'], function(taboverride) {
+                               taboverride.set($elements);
+                       });
+               }
+       };
+
+       /**
+        * Initialize and return the T3editor object
+        */
+       return function() {
+               $(document).ready(function() {
+                       T3editor.convertTextareasEnableTab();
+               });
+
+               return T3editor;
+       }();
+});