Feature #10639: Integration of the Mass File Uploader (based on SWFUpload and Ext JS)
authorBenni Mack <benni.mack@typo3.org>
Mon, 18 May 2009 08:59:25 +0000 (08:59 +0000)
committerBenni Mack <benni.mack@typo3.org>
Mon, 18 May 2009 08:59:25 +0000 (08:59 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@5432 709f56b5-9817-0410-a4d7-c38de5d9e867

16 files changed:
ChangeLog
NEWS.txt
t3lib/class.t3lib_beuserauth.php
t3lib/class.t3lib_div.php
t3lib/class.t3lib_userauth.php
typo3/alt_clickmenu.php
typo3/alt_file_navframe.php
typo3/backend.php
typo3/css/backend-style.css
typo3/file_list.php
typo3/js/common.js
typo3/stylesheet.css
typo3/sysext/setup/locallang_csh_mod.xml
typo3/sysext/setup/mod/index.php
typo3/sysext/setup/mod/locallang.xml
typo3/sysext/t3skin/stylesheets/stylesheet_post.css

index a80ed93..63819ca 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,6 @@
 2009-05-18  Benjamin Mack  <benni@typo3.org>
 
+       * Feature #10639: Integration of the Mass File Uploader (based on SWFUpload and Ext JS)
        * Fixed bug #11111 / Follow-up to #10892: Root item cannot be collapsed in pagetree (Thanks to Andreas Wolf)
        * Fixed bug #11112 / Follow-up to #10892: Collapsing nodes in pagetree produces multiple items with same id (Thanks to Andreas Wolf)
 
index a578f33..a344c40 100644 (file)
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -62,6 +62,12 @@ Backend
          In the view showing a single table with many elements, a pagination helps to
          get through them.
 
+       * Uploading files is now available with an optional Flash Uploader which shows a 
+         nice widget with information on the upload progress. It makes it possible to select
+         multiple files at once. Enable the Flash Uploader by checking the appropriate checkbox 
+         in the User Setup, reload the Backend and make sure that your browser has the 
+         latest version of Flash (Flash v9+) installed.
+
        * It is possible now to temporarily lock down the backend for system maintenance. Editors
          will see an overlay with an message notifying them that the backend is locked. When the
          lock is removed, editors can continue without having to re-login.
index 5c83db1..f8af98e 100644 (file)
@@ -132,6 +132,7 @@ class t3lib_beUserAuth extends t3lib_userAuthGroup {
                'edit_showFieldHelp' => 'icon',
                'edit_RTE' => '1',
                'edit_docModuleUpload' => '1',
+               'enableFlashUploader' => '1',
                'disableCMlayers' => 0,
                'navFrameWidth' => '',  // Default is 245 pixels
                'navFrameResizable' => 0,
@@ -364,6 +365,40 @@ class t3lib_beUserAuth extends t3lib_userAuthGroup {
        function veriCode()     {
                return substr(md5($this->id.$GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']),0,10);
        }
+
+
+       /**
+        * The session_id is used to find user in the database. 
+        * Two tables are joined: The session-table with user_id of the session and the usertable with its primary key
+        * if the client is flash (e.g. from a flash application inside TYPO3 that does a server request)
+        * then don't evaluate with the hashLockClause, as the client/browser is included in this hash
+        * and thus, the flash request would be rejected
+        *
+        * @return DB result object or false on error
+        * @access private 
+        */
+       protected function fetchUserSessionFromDB() {
+               if ($GLOBALS['CLIENT']['BROWSER'] == 'flash') {
+                       // if on the flash client, the veri code is valid, then the user session is fetched
+                       // from the DB without the hashLock clause
+                       if (t3lib_div::_GP('vC') == $this->veriCode()) {
+                               $dbres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
+                                               '*',
+                                               $this->session_table.','.$this->user_table,
+                                               $this->session_table.'.ses_id = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->id, $this->session_table).'
+                                                       AND '.$this->session_table.'.ses_name = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->name, $this->session_table).'
+                                                       AND '.$this->session_table.'.ses_userid = '.$this->user_table.'.'.$this->userid_column.'
+                                                       '.$this->ipLockClause().'
+                                                       '.$this->user_where_clause()
+                               );
+                       } else {
+                               $dbres = false;
+                       }
+               } else {
+                       $dbres = parent::fetchUserSessionFromDB();
+               }
+               return $dbres;
+       }
 }
 
 
index a1f6a6d..e198c77 100644 (file)
@@ -3846,6 +3846,8 @@ final class t3lib_div {
                        $bInfo['BROWSER']= 'msie';
                } elseif (strpos($useragent, 'Mozilla') !== false) {
                        $bInfo['BROWSER']='net';
+               } elseif (strpos($useragent, 'Flash') !== false) {
+                       $bInfo['BROWSER'] = 'flash';
                }
                if ($bInfo['BROWSER'])  {
                                // Browser version
index adf55e1..3bc2c1d 100644 (file)
@@ -222,6 +222,10 @@ class t3lib_userAuth {
                $this->hash_length = t3lib_div::intInRange($this->hash_length,6,32);
                $this->svConfig = $TYPO3_CONF_VARS['SVCONF']['auth'];
 
+                       // if we have a flash client, take the ID from the GP
+               if (!$id && $GLOBALS['CLIENT']['BROWSER'] == 'flash') {
+                       $id = t3lib_div::_GP($this->name);
+               }
 
                        // If fallback to get mode....
                if (!$id && $this->getFallBack && $this->get_name)      {
@@ -683,20 +687,10 @@ class t3lib_userAuth {
 
                if ($this->writeDevLog)         t3lib_div::devLog('Fetch session ses_id = '.$this->id, 't3lib_userAuth');
 
-                       // The session_id is used to find user in the database. Two tables are joined: The session-table with user_id of the session and the usertable with its primary key
-               $dbres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
-                                               '*',
-                                               $this->session_table.','.$this->user_table,
-                                               $this->session_table.'.ses_id = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->id, $this->session_table).'
-                                                       AND '.$this->session_table.'.ses_name = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->name, $this->session_table).'
-                                                       AND '.$this->session_table.'.ses_userid = '.$this->user_table.'.'.$this->userid_column.'
-                                                       '.$this->ipLockClause().'
-                                                       '.$this->hashLockClause().'
-                                                       '.$this->user_where_clause()
-                                       );
-
+                       // fetch the user session from the DB
+               $dbres = $this->fetchUserSessionFromDB();
 
-               if ($user = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($dbres))      {
+               if ($dbres && $user = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($dbres)) {
                                // A user was found
                        if (is_string($this->auth_timeout_field))       {
                                $timeout = intval($user[$this->auth_timeout_field]);            // Get timeout-time from usertable
@@ -798,6 +792,27 @@ class t3lib_userAuth {
         *************************/
 
        /**
+        * The session_id is used to find user in the database. 
+        * Two tables are joined: The session-table with user_id of the session and the usertable with its primary key
+        * @return DB result object or false on error
+        * @access private 
+        */
+       protected function fetchUserSessionFromDB() {
+               $dbres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
+                                       '*',
+                                       $this->session_table.','.$this->user_table,
+                                       $this->session_table.'.ses_id = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->id, $this->session_table).'
+                                               AND '.$this->session_table.'.ses_name = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->name, $this->session_table).'
+                                               AND '.$this->session_table.'.ses_userid = '.$this->user_table.'.'.$this->userid_column.'
+                                               '.$this->ipLockClause().'
+                                               '.$this->hashLockClause().'
+                                               '.$this->user_where_clause()
+               );
+               return $dbres;
+       }
+
+
+       /**
         * This returns the where-clause needed to select the user with respect flags like deleted, hidden, starttime, endtime
         *
         * @return      string
index 5502783..62bd7f1 100644 (file)
@@ -846,7 +846,10 @@ class clickMenu {
                                // rename
                        if (!in_array('rename',$this->disabledItems))   $menuItems['rename']=$this->FILE_launch($path,'file_rename.php','rename','rename.gif');
                                // upload
-                       if (!in_array('upload',$this->disabledItems) && is_dir($path)) $menuItems['upload']=$this->FILE_launch($path,'file_upload.php','upload','upload.gif',TRUE);
+                       if (!in_array('upload',$this->disabledItems) && is_dir($path)) {
+                               $menuItems['upload'] = $this->FILE_upload($path);
+                       }
+
                                // new
                        if (!in_array('new',$this->disabledItems) && is_dir($path)) $menuItems['new']=$this->FILE_launch($path,'file_newfolder.php','new','new_file.gif');
                                // info
@@ -924,6 +927,32 @@ class clickMenu {
        }
 
        /**
+        * function for adding an upload entry to the $menuItems array
+        *
+        * @param       string          Path to the file/directory (target)
+        * @return      array           Item array, element in $menuItems
+        * @internal
+        */
+       function FILE_upload($path) {
+               $script = 'file_upload.php';
+               $type = 'upload';
+               $image = 'upload.gif';
+               if ($GLOBALS['BE_USER']->uc['enableFlashUploader']) {
+                       $loc='top.content'.(!$this->alwaysContentFrame?'.list_frame':'');
+
+                       $editOnClick = 'if (top.TYPO3.FileUploadWindow.isFlashAvailable()) { initFlashUploader("' . rawurlencode($path) . '"); } else if(' . $loc . '){' . $loc . ".location.href=top.TS.PATH_typo3+'".$script.'?target=' . rawurlencode($path) . "';}";
+
+                       return $this->linkItem(
+                               $this->label($type),
+                               $this->excludeIcon('<img'.t3lib_iconWorks::skinImg($this->PH_backPath,'gfx/'.$image,'width="12" height="12"').' alt="" />'),
+                               $editOnClick.'return hideCM();'
+                               );
+               } else {
+                       return $this->FILE_launch($path, $script, $type, $image, true);
+               }
+       }
+
+       /**
         * Returns element for copy or cut of files.
         *
         * @param       string          Path to the file/directory (target)
index 4a33d8f..4b37769 100644 (file)
@@ -134,6 +134,54 @@ class SC_alt_file_navframe {
 
                ($this->currentSubScript?'top.currentSubScript=unescape("'.rawurlencode($this->currentSubScript).'");':'').'
 
+               function initFlashUploader(path) {
+                       path = decodeURIComponent(path);
+                       var flashUploadOptions = {
+                               uploadURL: top.TS.PATH_typo3 + "ajax.php",
+                               uploadFileSizeLimit: "' . t3lib_div::getMaxUploadFileSize() . '",
+                               uploadFileTypes: {
+                                       allow:  "' . $GLOBALS['TYPO3_CONF_VARS']['BE']['fileExtensions']['webspace']['allow'] . '",
+                                       deny: "' . $GLOBALS['TYPO3_CONF_VARS']['BE']['fileExtensions']['webspace']['deny'] . '"
+                               },
+                               uploadFilePostName: "upload_1",
+                               uploadPostParams: {
+                                       "file[upload][1][target]": path,
+                                       "file[upload][1][data]": 1,
+                                       "file[upload][1][charset]": "utf-8",
+                                       "ajaxID": "TYPO3_tcefile::process"
+                               }
+                       };
+
+                               // get the flashUploaderWindow instance from the parent frame
+                       var flashUploader = top.TYPO3.FileUploadWindow.getInstance(flashUploadOptions);
+                               // add an additional function inside the container to show the checkbox option
+                       var infoComponent = new top.Ext.Panel({
+                               autoEl: { tag: "div" },
+                               height: "auto",
+                               bodyBorder: false,
+                               border: false,
+                               hideBorders: true,
+                               cls: "t3-upload-window-infopanel",
+                               id: "t3-upload-window-infopanel-addition",
+                               html: \'<label for="overrideExistingFilesCheckbox"><input id="overrideExistingFilesCheckbox" type="checkbox" onclick="setFlashPostOptionOverwriteExistingFiles(this);" />\' + top.String.format(top.TYPO3.LLL.fileUpload.infoComponentOverrideFiles) + \'</label>\'
+                       });
+                       flashUploader.add(infoComponent);
+
+                               // do a reload of this frame once all uploads are done
+                       flashUploader.on("totalcomplete", function() {
+                               jumpTo(path, "", "", "");
+                       });
+
+                               // this is the callback function that delivers the additional post parameter to the flash application
+                       top.setFlashPostOptionOverwriteExistingFiles = function(checkbox) {
+                               var uploader = top.TYPO3.getInstance("FileUploadWindow");
+                               if (uploader.isVisible()) {
+                                       uploader.swf.addPostParam("overwriteExistingFiles", (checkbox.checked == true ? 1 : 0));
+                               }
+                       };
+               }
+
+
                // setting prefs for foldertree
                Tree.ajaxID = "SC_alt_file_navframe::expandCollapse";
 
@@ -143,8 +191,8 @@ class SC_alt_file_navframe {
                        if (theUrl.indexOf("?") != -1) {
                                theUrl += "&id=" + id
                        } else {
-                               theUrl += "?id=" + id                   
-                       }       
+                               theUrl += "?id=" + id
+                       }
                        top.fsMod.currentBank = bank;
 
                        if (top.condensedMode) {
index 153c7fa..b51993b 100644 (file)
@@ -96,6 +96,10 @@ class TYPO3backend {
                        'contrib/scriptaculous/scriptaculous.js?load=builder,effects,controls,dragdrop',
                        'contrib/extjs/adapter/ext/ext-base.js',
                        'contrib/extjs/ext-all.js',
+                       'contrib/swfupload/swfupload.js',
+                       'contrib/swfupload/plugins/swfupload.swfobject.js',
+                       'contrib/swfupload/plugins/swfupload.cookies.js',
+                       'contrib/swfupload/plugins/swfupload.queue.js',
                        'md5.js',
                        'js/backend.js',
                        'js/common.js',
@@ -103,6 +107,7 @@ class TYPO3backend {
                        'js/toolbarmanager.js',
                        'js/modulemenu.js',
                        'js/iecompatibility.js',
+                       'js/flashupload.js',
                        '../t3lib/jsfunc.evalfield.js'
                );
 
@@ -403,12 +408,48 @@ class TYPO3backend {
                this.PATH_typo3_enc = "'.rawurlencode($pathTYPO3).'";
                this.username = "'.htmlspecialchars($GLOBALS['BE_USER']->user['username']).'";
                this.uniqueID = "'.t3lib_div::shortMD5(uniqid('')).'";
+               this.veriCode = "' . $GLOBALS['BE_USER']->veriCode() . '";
                this.navFrameWidth = 0;
                this.securityLevel = "'.$this->loginSecurityLevel.'";
+               this.denyFileTypes = "' . PHP_EXTENSIONS_DEFAULT . '";
        }
        var TS = new typoSetup();
 
        /**
+        * Language Labels
+        */
+       TYPO3.LLL = {
+               fileUpload: {
+                       windowTitle: "File Upload Progress",
+                       buttonSelectFiles: "Select Files",
+                       buttonCancelAll: "Cancel All Uploads",
+                       infoComponentMaxFileSize: "You can upload files with a maximum size of {0}.",
+                       infoComponentFileUploadLimit: "You can upload a total of {0}.",
+                       infoComponentFileTypeLimit: "You can upload the following file types {0}.",
+                       infoComponentOverrideFiles: "' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xml:overwriteExistingFiles', 1) . '",
+                       processRunning: "Another process is already uploading",
+                       uploadWait: "Waiting to start upload of {0}",
+                       uploadStarting: "Starting upload of {0}",
+                       uploadProgress: "{0}% of {1} uploaded",
+                       uploadSuccess: "{0} was successfully uploaded!",
+                       errorQueueLimitExceeded: "Too many files selected",
+                       errorQueueFileSizeLimit: "{0} is too big",
+                       errorQueueZeroByteFile:  "{0} is empty",
+                       errorQueueInvalidFiletype: "Filetype not allowed for {0}",
+                       errorUploadHttp: "Too many files selected",
+                       errorUploadMissingUrl: "Internal error: No Upload URL set",
+                       errorUploadIO: "Internal error: Problems while reading/writing the file",
+                       errorUploadSecurityError: "Internal error: {0}",
+                       errorUploadLimit: "Upload limit exceeded",
+                       errorUploadFailed: "Upload failed",
+                       errorUploadFileIDNotFound: "Internal error: File ID not found",
+                       errorUploadFileValidation: "Internal error while validating the file",
+                       errorUploadFileCancelled: "Upload of {0} canceled",
+                       errorUploadStopped: "Upload of {0} stopped"
+               }
+        };
+
+       /**
         * Functions for session-expiry detection:
         */
        function busy() {       //
index 9812b40..4c7e080 100644 (file)
@@ -309,9 +309,32 @@ Description : styles for the TYPO3 backend
        padding: 1px;
 }
 
+/* ----- File Upload Window ----- */
 
+.swfupload {
+       display: block;
+       position: absolute;
+       width: 80px;
+       height: 22px;
+       z-index: 2000;
+}
 
+#t3-upload-window-infopanel div div {
+       padding: 10px;
+}
+.t3-upload-window-infopanel div div {
+       padding: 0 10px 10px;
+}
 
+.t3-upload-window-infopanel input {
+       vertical-align: text-bottom;
+       margin-right: 3px;
+}
+
+.t3-upload-window-progressbar .x-progress-text div {
+       text-align: left;
+       text-indent: 6px;
+}
 
 
 
index c0fccda..1856a96 100644 (file)
@@ -54,6 +54,7 @@ require ('mod/file/list/conf.php');
 require ('init.php');
 require ('template.php');
 $LANG->includeLLFile('EXT:lang/locallang_mod_file_list.xml');
+$LANG->includeLLFile('EXT:lang/locallang_misc.xml');
 require_once (PATH_t3lib.'class.t3lib_basicfilefunc.php');
 require_once (PATH_t3lib.'class.t3lib_extfilefunc.php');
 require_once (PATH_t3lib.'class.t3lib_recordlist.php');
@@ -168,6 +169,7 @@ class SC_file_list {
                $this->doc = t3lib_div::makeInstance('template');
                $this->doc->backPath = $BACK_PATH;
                $this->doc->setModuleTemplate('templates/file_list.html');
+               $this->doc->loadPrototype();
 
                        // Validating the input "id" (the path, directory!) and checking it against the mounts of the user.
                $this->id = $this->basicFF->is_directory($this->id);
@@ -175,7 +177,67 @@ class SC_file_list {
 
                        // There there was access to this file path, continue, make the list
                if ($access)    {
-
+                               // include the initialization for the flash uploader
+                       if ($GLOBALS['BE_USER']->uc['enableFlashUploader']) {
+
+                               $this->doc->JScodeArray['flashUploader'] = '
+                                       if (top.TYPO3.FileUploadWindow.isFlashAvailable()) {
+                                               document.observe("dom:loaded", function() {
+                                                               // monitor the button
+                                                       $("button-upload").observe("click", initFlashUploader);
+
+                                                       function initFlashUploader(event) {
+                                                                       // set the page specific options for the flashUploader
+                                                               var flashUploadOptions = {
+                                                                       uploadURL:           top.TS.PATH_typo3 + "ajax.php",
+                                                                       uploadFileSizeLimit: "' . t3lib_div::getMaxUploadFileSize() . '",
+                                                                       uploadFileTypes: {
+                                                                               allow:  "' . $GLOBALS['TYPO3_CONF_VARS']['BE']['fileExtensions']['webspace']['allow'] . '",
+                                                                               deny: "' . $GLOBALS['TYPO3_CONF_VARS']['BE']['fileExtensions']['webspace']['deny'] . '"
+                                                                       },
+                                                                       uploadFilePostName:  "upload_1",
+                                                                       uploadPostParams: {
+                                                                               "file[upload][1][target]": "' . $this->id . '",
+                                                                               "file[upload][1][data]": 1,
+                                                                               "file[upload][1][charset]": "utf-8",
+                                                                               "ajaxID": "TYPO3_tcefile::process"
+                                                                       }
+                                                               };
+
+                                                                       // get the flashUploaderWindow instance from the parent frame
+                                                               var flashUploader = top.TYPO3.FileUploadWindow.getInstance(flashUploadOptions);
+                                                               // add an additional function inside the container to show the checkbox option
+                                                               var infoComponent = new top.Ext.Panel({
+                                                                       autoEl: { tag: "div" },
+                                                                       height: "auto",
+                                                                       bodyBorder: false,
+                                                                       border: false,
+                                                                       hideBorders: true,
+                                                                       cls: "t3-upload-window-infopanel",
+                                                                       id: "t3-upload-window-infopanel-addition",
+                                                                       html: \'<label for="overrideExistingFilesCheckbox"><input id="overrideExistingFilesCheckbox" type="checkbox" onclick="setFlashPostOptionOverwriteExistingFiles(this);" />\' + top.String.format(top.TYPO3.LLL.fileUpload.infoComponentOverrideFiles) + \'</label>\'
+                                                               });
+                                                               flashUploader.add(infoComponent);
+
+                                                                       // do a reload of this frame once all uploads are done
+                                                               flashUploader.on("totalcomplete", function() {
+                                                                       window.location.reload();
+                                                               });
+
+                                                                       // this is the callback function that delivers the additional post parameter to the flash application
+                                                               top.setFlashPostOptionOverwriteExistingFiles = function(checkbox) {
+                                                                       var uploader = top.TYPO3.getInstance("FileUploadWindow");
+                                                                       if (uploader.isVisible()) {
+                                                                               uploader.swf.addPostParam("overwriteExistingFiles", (checkbox.checked == true ? 1 : 0));
+                                                                       }
+                                                               };
+
+                                                               event.stop();
+                                                       };
+                                               });
+                                       }
+                               ';
+                       }
                                // Create filelisting object
                        $this->filelist = t3lib_div::makeInstance('fileList');
                        $this->filelist->backPath = $BACK_PATH;
@@ -347,7 +409,7 @@ class SC_file_list {
 
                        // upload button
                $theIcon = '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/upload.gif','width="18" height="16"').' title="'.$GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:cm.upload',1)).'" alt="'.$GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:cm.upload',1)).'" />';
-               $buttons['upload'] = '<a href="' . $BACK_PATH . 'file_upload.php?target=' . rawurlencode($this->id) . '&amp;returnUrl=' . rawurlencode($this->filelist->listURL()) . '">' . $theIcon . '</a>';
+               $buttons['upload'] = '<a href="' . $BACK_PATH . 'file_upload.php?target=' . rawurlencode($this->id) . '&amp;returnUrl=' . rawurlencode($this->filelist->listURL()) . '" id="button-upload">' . $theIcon . '</a>';
 
                $theIcon = '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/new_file.gif','width="18" height="16"').' title="'.$GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:cm.new',1)).'" alt="'.$GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:cm.new',1)).'" />';
                $buttons['new'] = '<a href="' . $BACK_PATH . 'file_newfolder.php?target=' . rawurlencode($this->id) . '&amp;returnUrl=' . rawurlencode($this->filelist->listURL()) . '">' . $theIcon . '</a>';
index 05f4c60..694d245 100644 (file)
@@ -75,3 +75,29 @@ T3AJAX.showError = function(xhr, json) {
                }
        }
 }
+
+// common storage and global object, could later hold more information about the current user etc.
+var TYPO3 = {
+       // store instances that only should be running once
+       _instances: {},
+       getInstance: function(className) {
+               return TYPO3._instances[className] || false;
+       },
+       addInstance: function(className, instance) {
+               TYPO3._instances[className] = instance;
+               return instance;
+       },
+       
+       helpers: {
+               // creates an array by splitting a string into parts, taking a delimiter 
+               split: function(str, delim) {
+                       var res = new Array();
+                       while (str.indexOf(delim) > 0) {
+                               res.push(str.substr(0, str.indexOf(delim)));
+                               str = str.substr(str.indexOf(delim) + delim.length);
+                       }
+                       res.push(allow);
+                       return res;
+               }
+       }
+};
index f555f81..ac70395 100644 (file)
@@ -2784,6 +2784,18 @@ pre.ts-hl .ts-linenum {
 }
 
 
+/*** Icons ***/
+
+/* extJS icons */
+.t3icon-ext-upload {
+       background: url('gfx/upload.gif') 3px 4px no-repeat !important;
+}
+.t3icon-ext-cancel {
+       background: url('gfx/icon_fatalerror.gif') 2px 3px no-repeat !important;
+}
+.t3iconstyle-center {
+       background-position: center center;
+}
 
 
 /* Visual debugging: */
index aa33997..0937502 100755 (executable)
@@ -70,6 +70,8 @@ The default module is &quot;About Modules&quot;.</label>
                        <label index="option_edit_docModuleUpload.description">This option will enable an &quot;Upload&quot; box for each field in TYPO3 records where you can attach a file or image. Most likely you don't want to disable this since it is usually just a nice thing to have.</label>
                        <label index="option_edit_docModuleUpload.details">If you disable the Upload box there is still the TYPO3 Element Browser left for attaching files and images.</label>
                        <label index="_option_edit_docModuleUpload.image">EXT:setup/cshimages/setup12.png</label>
+                       <label index="option_enableFlashUploader.alttitle">Enable Flash Uploader</label>
+                       <label index="option_enableFlashUploader.description">This option will enable a flash-based uploader that allows you to select multiple files at once when uploading files. If you enable this option, make sure that your browser has the latest Flash plugin (Flash 9 or higher) installed in order to make this feature work.</label>
                        <label index="option_edit_showFieldHelp.alttitle">Context Sensitive Help mode</label>
                        <label index="option_edit_showFieldHelp.description">Defines the mode of Context Sensitive Help (CSH) in TYPO3. The default is that small help icons are shown everywhere a help item is available. You can click the icon and help will appear in a window for you.</label>
                        <label index="option_edit_showFieldHelp.details">Alternatively you can select that descriptions are shown inline. This is useful for people who are still learning how TYPO3 works and want to browse the backend with descriptions shown directly.
index 25c3f79..1539a60 100755 (executable)
@@ -161,6 +161,7 @@ class SC_mod_user_setup_index {
                        $BE_USER->uc['edit_wideDocument'] = $d['edit_wideDocument'];
                        if ($GLOBALS['TYPO3_CONF_VARS']['BE']['RTEenabled'])    { $BE_USER->uc['edit_RTE'] = $d['edit_RTE']; }
                        $BE_USER->uc['edit_docModuleUpload'] = $d['edit_docModuleUpload'];
+                       $BE_USER->uc['enableFlashUploader'] = $d['enableFlashUploader'];
                        $BE_USER->uc['edit_showFieldHelp'] = $d['edit_showFieldHelp'];
                        $BE_USER->uc['disableCMlayers'] = $d['disableCMlayers'];
 
@@ -556,6 +557,10 @@ class SC_mod_user_setup_index {
                                        'type' => 'check',
                                        'form' => '<input id="field_edit_docModuleUpload" type="checkbox" name="data[edit_docModuleUpload]"'.($BE_USER->uc['edit_docModuleUpload']?' checked="checked"':'').' />'
                                ),
+                               'enableFlashUploader' => array(
+                                       'type' => 'check',
+                                       'form' => '<input id="field_enableFlashUploader" type="checkbox" name="data[enableFlashUploader]"' . ($BE_USER->uc['enableFlashUploader'] ? ' checked="checked"' : '') . ' />'
+                               ),
                                'disableCMlayers' => array(
                                        'type' => 'check',
                                        'form' => '<input id="field_disableCMlayers" type="checkbox" name="data[disableCMlayers]"'.($BE_USER->uc['disableCMlayers']?' checked="checked"':'').' />'
index 7a20d7d..641092d 100755 (executable)
@@ -78,6 +78,7 @@
                        <label index="edit_wideDocument">Wide document background</label>
                        <label index="edit_RTE">Enable Rich Text Editor (if available)</label>
                        <label index="edit_docModuleUpload">File upload directly in Doc-module</label>
+                       <label index="enableFlashUploader">Enable Flash Uploader (requires Flash 9+)</label>
                        <label index="edit_functions">Edit</label>
                        <label index="disableCMlayers">Disable Popup Context Menus</label>
                        <label index="setToStandard">Reset all Values to default</label>
index 285f0c5..cc80ef1 100644 (file)
@@ -148,3 +148,11 @@ h4 {
 }
 
 /* END PAGE HEADERS: */
+
+/* Icons */
+.t3icon-ext-upload {
+       background: url('../icons/gfx/upload.gif') 1px 2px no-repeat !important;
+}
+.t3icon-ext-cancel {
+       background: url('../icons/gfx/icon_fatalerror.gif') 1px 2px no-repeat !important;
+}