* Added feature #5500: Load Inline Elements On Demand (thanks to Harald Glaser &...
authorSusanne Moog <typo3@susannemoog.de>
Tue, 13 Apr 2010 14:30:38 +0000 (14:30 +0000)
committerSusanne Moog <typo3@susannemoog.de>
Tue, 13 Apr 2010 14:30:38 +0000 (14:30 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@7340 709f56b5-9817-0410-a4d7-c38de5d9e867

ChangeLog
t3lib/class.t3lib_tceforms_inline.php
t3lib/config_default.php
t3lib/jsfunc.inline.js

index 111a9e8..ec3bc70 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+2010-04-13  Susanne Moog <typo3@susanne-moog.de>
+       * Added feature #5500: Load Inline Elements On Demand (thanks to Harald Glaser & Vladimir Podkovanov)
+
 2010-04-13  Dmitry Dulepov <dmitry.dulepov@gmail.com>
 
        * Fixed bug #14027: Tweak: Add "tiff" to imagefile_ext array
index c549977..49b59d2 100644 (file)
@@ -390,17 +390,33 @@ class t3lib_TCEforms_inline {
                        // Put the current level also to the dynNestedStack of TCEforms:
                $this->fObj->pushToDynNestedStack('inline', $objectId);
 
-               $header = $this->renderForeignRecordHeader($parentUid, $foreign_table, $rec, $config, $isVirtualRecord);
                if (!$isVirtualRecord) {
-                       $combination = $this->renderCombinationTable($rec, $appendFormFieldNames, $config);
-                       $fields = $this->renderMainFields($foreign_table, $rec);
-                       $fields = $this->wrapFormsSection($fields);
                                // Get configuration:
                        $collapseAll = (isset($config['appearance']['collapseAll']) && $config['appearance']['collapseAll']);
+                       $ajaxLoad = (isset($config['appearance']['ajaxLoad']) && !$config['appearance']['ajaxLoad']) ? false : true;
 
                        if ($isNewRecord) {
                                        // show this record expanded or collapsed
                                $isExpanded = (!$collapseAll ? 1 : 0);
+                       } else {
+                               $isExpanded = ($config['renderFieldsOnly'] || (!$collapseAll && $this->getExpandedCollapsedState($foreign_table, $rec['uid'])));
+                       }
+                               // Render full content ONLY IF this is a AJAX-request, a new record, the record is not collapsed or AJAX-loading is explicitly turned off
+                       if ($isNewRecord || $isExpanded || !$ajaxLoad) {
+                               $combination = $this->renderCombinationTable($rec, $appendFormFieldNames, $config);
+                               $fields = $this->renderMainFields($foreign_table, $rec);
+                               $fields = $this->wrapFormsSection($fields);
+                                       // Replace returnUrl in Wizard-Code, if this is an AJAX call
+                               $ajaxArguments = t3lib_div::_GP('ajax');
+                               if (isset($ajaxArguments[2]) && trim($ajaxArguments[2]) != '') {
+                                       $fields = str_replace('P[returnUrl]=%2F' . rawurlencode(TYPO3_mainDir) . '%2Fajax.php', 'P[returnUrl]=' . rawurlencode($ajaxArguments[2]), $fields);
+                               }
+                       } else {
+                               $combination = '';
+                                       // This string is the marker for the JS-function to check if the full content has already been loaded
+                               $fields = '<!--notloaded-->';
+                       }
+                       if ($isNewRecord) {
                                        // get the top parent table
                                $top = $this->getStructureLevel(0);
                                $ucFieldName = 'uc[inlineView]['.$top['table'].']['.$top['uid'].']'.$appendFormFieldNames;
@@ -408,26 +424,27 @@ class t3lib_TCEforms_inline {
                                $fields .= '<input type="hidden" name="'.$this->prependFormFieldNames.$appendFormFieldNames.'[pid]" value="'.$rec['pid'].'"/>';
                                $fields .= '<input type="hidden" name="'.$ucFieldName.'" value="'.$isExpanded.'" />';
                        } else {
-                                       // show this record expanded or collapsed
-                               $isExpanded = (!$collapseAll && $this->getExpandedCollapsedState($foreign_table, $rec['uid']));
                                        // set additional field for processing for saving
                                $fields .= '<input type="hidden" name="'.$this->prependCmdFieldNames.$appendFormFieldNames.'[delete]" value="1" disabled="disabled" />';
                        }
-
                                // if this record should be shown collapsed
                        if (!$isExpanded) {
                                $appearanceStyleFields = ' style="display: none;"';
                        }
                }
-
+                               
+               if ($config['renderFieldsOnly']) {
+                       $out = $fields . $combination;
+               } else {
                        // set the record container with data for output
-               $out = '<div id="' . $objectId . '_header">' . $header . '</div>';
-               $out .= '<div id="' . $objectId . '_fields"' . $appearanceStyleFields . '>' . $fields.$combination . '</div>';
-                       // wrap the header, fields and combination part of a child record with a div container
-               $classMSIE = ($this->fObj->clientInfo['BROWSER']=='msie' && $this->fObj->clientInfo['VERSION'] < 8 ? 'MSIE' : '');
-               $class = 'inlineDiv' . $classMSIE . ($isNewRecord ? ' inlineIsNewRecord' : '');
-               $out = '<div id="' . $objectId . '_div" class="'.$class.'">' . $out . '</div>';
-
+                       $out = '<div id="' . $objectId . '_fields"' . $appearanceStyleFields . '>' . $fields . $combination . '</div>';
+                       $header = $this->renderForeignRecordHeader($parentUid, $foreign_table, $rec, $config, $isVirtualRecord);
+                       $out = '<div id="' . $objectId . '_header">' . $header . '</div>' . $out;
+                               // wrap the header, fields and combination part of a child record with a div container
+                       $classMSIE = ($this->fObj->clientInfo['BROWSER']=='msie' && $this->fObj->clientInfo['VERSION'] < 8 ? 'MSIE' : '');
+                       $class = 'inlineDiv' . $classMSIE . ($isNewRecord ? ' inlineIsNewRecord' : '');
+                       $out = '<div id="' . $objectId . '_div" class="'.$class.'">' . $out . '</div>';
+               }
                        // Remove the current level also from the dynNestedStack of TCEforms:
                $this->fObj->popFromDynNestedStack();
 
@@ -474,7 +491,8 @@ class t3lib_TCEforms_inline {
                        // Init:
                $objectId = $this->inlineNames['object'] . self::Structure_Separator . $foreign_table . self::Structure_Separator . $rec['uid'];
                $expandSingle = $config['appearance']['expandSingle'] ? 1 : 0;
-               $onClick = "return inline.expandCollapseRecord('" . htmlspecialchars($objectId) . "', $expandSingle)";
+                       // we need the returnUrl of the main script when loading the fields via AJAX-call (to correct wizard code, so include it as 3rd parameter)
+               $onClick = "return inline.expandCollapseRecord('" . htmlspecialchars($objectId) . "', $expandSingle, '" . rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI')) . "')";
 
                        // Pre-Processing:
                $isOnSymmetricSide = t3lib_loadDBGroup::isOnSymmetricSide($parentUid, $config, $rec);
@@ -961,6 +979,7 @@ class t3lib_TCEforms_inline {
         * @return      void
         */
        public function processAjaxRequest($params, $ajaxObj) {
+               
                $ajaxArguments = t3lib_div::_GP('ajax');
                $ajaxIdParts = explode('::', $GLOBALS['ajaxID'], 2);
 
@@ -969,6 +988,7 @@ class t3lib_TCEforms_inline {
                        switch ($ajaxMethod) {
                                case 'createNewRecord':
                                case 'synchronizeLocalizeRecords':
+                               case 'getRecordDetails':
                                        $this->isAjaxCall = true;
                                                // Construct runtime environment for Inline Relational Record Editing:
                                        $this->processAjaxRequestConstruct($ajaxArguments);
@@ -1239,6 +1259,67 @@ class t3lib_TCEforms_inline {
                return $jsonArray;
        }
 
+       /**
+        * Handle AJAX calls to dynamically load the form fields of a given record.
+        * (basically a copy of "createNewRecord")
+        * Normally this method is never called from inside TYPO3. Always from outside by AJAX.
+        *
+        * @param       string          $domObjectId: The calling object in hierarchy, that requested a new record.
+        * @return      array           An array to be used for JSON
+        */
+       function getRecordDetails($domObjectId) {
+                       // the current table - for this table we should add/import records
+               $current = $this->inlineStructure['unstable'];
+                       // the parent table - this table embeds the current table
+               $parent = $this->getStructureLevel(-1);
+                       // get TCA 'config' of the parent table
+               if (!$this->checkConfiguration($parent['config'])) {
+                       return $this->getErrorMessageForAJAX('Wrong configuration in table ' . $parent['table']);
+               }
+               $config = $parent['config'];
+                       // set flag in config so that only the fields are rendered
+               $config['renderFieldsOnly'] = true;
+
+               $collapseAll = (isset($config['appearance']['collapseAll']) && $config['appearance']['collapseAll']);
+               $expandSingle = (isset($config['appearance']['expandSingle']) && $config['appearance']['expandSingle']);
+
+                       // Put the current level also to the dynNestedStack of TCEforms:
+               $this->fObj->pushToDynNestedStack('inline', $this->inlineNames['object']);
+
+               $record = $this->getRecord($this->inlineFirstPid, $current['table'], $current['uid']);
+
+                       // the HTML-object-id's prefix of the dynamically created record
+               $objectPrefix = $this->inlineNames['object'] . self::Structure_Separator . $current['table'];
+               $objectId = $objectPrefix . self::Structure_Separator . $record['uid'];
+
+               $item = $this->renderForeignRecord($parent['uid'], $record, $config);
+               if($item === false) {
+                       return $this->getErrorMessageForAJAX('Access denied');
+               }
+
+                       // Encode TCEforms AJAX response with utf-8:
+               $item = $GLOBALS['LANG']->csConvObj->utf8_encode($item, $GLOBALS['LANG']->charSet);
+
+               $jsonArray = array(
+                       'data'  => $item,
+                       'scriptCall' => array(
+                               'inline.domAddRecordDetails(\'' . $domObjectId . '\',\'' . $objectPrefix . '\',' . ($expandSingle ? '1' : '0') . ',json.data);',
+                       )
+               );
+
+               $this->getCommonScriptCalls($jsonArray, $config);
+                       // Collapse all other records if requested:
+               if (!$collapseAll && $expandSingle) {
+                       $jsonArray['scriptCall'][] = 'inline.collapseAllRecords(\'' . $objectId . '\',\'' . $objectPrefix . '\',\'' . $record['uid'] . '\');';
+               }
+
+                       // Remove the current level also from the dynNestedStack of TCEforms:
+               $this->fObj->popFromDynNestedStack();
+
+                       // Return the JSON array:
+               return $jsonArray;
+       }
+       
 
        /**
         * Generates a JSON array which executes the changes and thus updates the forms view.
index 9a78485..f8c0806 100644 (file)
@@ -262,6 +262,7 @@ $TYPO3_CONF_VARS = array(
                        'SC_alt_file_navframe::expandCollapse'              => 'typo3/alt_file_navframe.php:SC_alt_file_navframe->ajaxExpandCollapse',
                        'TYPO3_tcefile::process'                            => 'typo3/classes/class.typo3_tcefile.php:TYPO3_tcefile->processAjaxRequest',
                        't3lib_TCEforms_inline::createNewRecord'                    => 't3lib/class.t3lib_tceforms_inline.php:t3lib_TCEforms_inline->processAjaxRequest',
+                       't3lib_TCEforms_inline::getRecordDetails'                   => 't3lib/class.t3lib_tceforms_inline.php:t3lib_TCEforms_inline->processAjaxRequest',
                        't3lib_TCEforms_inline::synchronizeLocalizeRecords'     => 't3lib/class.t3lib_tceforms_inline.php:t3lib_TCEforms_inline->processAjaxRequest',
                        't3lib_TCEforms_inline::setExpandedCollapsedState'      => 't3lib/class.t3lib_tceforms_inline.php:t3lib_TCEforms_inline->processAjaxRequest',
                        't3lib_TCEforms_suggest::searchRecord'              => 't3lib/tceforms/class.t3lib_tceforms_suggest.php:t3lib_TCEforms_suggest->processAjaxRequest',
index ba42bbe..440717f 100644 (file)
@@ -45,10 +45,19 @@ var inline = {
        setPrependFormFieldNames: function(value) {     this.prependFormFieldNames = value; },
        setNoTitleString: function(value) { this.noTitleString = value; },
 
-       expandCollapseRecord: function(objectId, expandSingle) {
+       expandCollapseRecord: function(objectId, expandSingle, returnURL) {
                var currentUid = this.parseObjectId('none', objectId, 1);
                var objectPrefix = this.parseObjectId('full', objectId, 0, 1);
 
+                       // if content is not loaded yet, get it now from server
+               if ($(objectId+'_fields') && $(objectId+'_fields').innerHTML.substr(0,16) == '<!--notloaded-->') {
+                               // add loading-indicator
+                       if ($(objectId+'_label')) {
+                               $(objectId+'_label').insert({before:'<span id="irre-loading-indicator" class="loading-indicator">&nbsp;</span>'});
+                       }
+                       return this.getRecordDetails(objectId, returnURL);      
+               }               
+               
                var currentState = '';
                var collapse = new Array();
                var expand = new Array();
@@ -104,6 +113,11 @@ var inline = {
                        ucFormObj[0].value = value;
                }
        },
+       
+       getRecordDetails: function(objectId, returnURL) {
+               inline.makeAjaxCall('getRecordDetails', [inline.getNumberOfRTE(), objectId, returnURL], true);
+               return false;
+       },
 
        createNewRecord: function(objectId, recordUid) {
                if (this.isBelowMax(objectId)) {
@@ -351,6 +365,17 @@ var inline = {
                                new Insertion.After(insertObject, htmlData);
                }
        },
+       domAddRecordDetails: function(objectId, objectPrefix, expandSingle, htmlData) {
+               var objectDiv = $(objectId + '_fields');
+               if (!objectDiv || objectDiv.innerHTML.substr(0,16) != '<!--notloaded-->')
+                       return;
+               objectDiv.update(htmlData);
+                       // remove loading-indicator
+               if ($('irre-loading-indicator')) 
+                       $('irre-loading-indicator').remove();
+                       // now that the content is loaded, set the expandState
+               this.expandCollapseRecord(objectId, expandSingle);
+       },
 
                // Get script and link elements from head tag:
        getDomHeadChildren: function(head) {