/**
     * Return the Javascript code for configuring the RTE
     *
     * @param	integer		$RTEcounter: The index number of the current RTE editing area within the form.
     * @param	string		$table: The table that includes this RTE (optional, necessary for IRRE).
     * @param	string		$uid: The uid of that table that includes this RTE (optional, necessary for IRRE).
     * @param	string		$field: The field of that record that includes this RTE (optional).
     *
     * @return	string		the Javascript code for configuring the RTE
     */
    function registerRTEinJS($RTEcounter, $table = '', $uid = '', $field = '', $textAreaId = '')
    {
        $configureRTEInJavascriptString = (!$this->is_FE() ? '' : '
			' . '/*<![CDATA[*/') . '
			if (typeof(configureEditorInstance) == "undefined") {
				configureEditorInstance = new Object();
			}
			configureEditorInstance["' . $textAreaId . '"] = function() {
				if (typeof(RTEarea) == "undefined" || typeof(HTMLArea) == "undefined") {
					window.setTimeout("configureEditorInstance[\'' . $textAreaId . '\']();", 40);
				} else {
			editornumber = "' . $textAreaId . '";
			RTEarea[editornumber] = new Object();
			RTEarea[editornumber].RTEtsConfigParams = "&RTEtsConfigParams=' . rawurlencode($this->RTEtsConfigParams()) . '";
			RTEarea[editornumber].number = editornumber;
			RTEarea[editornumber].deleted = false;
			RTEarea[editornumber].textAreaId = "' . $textAreaId . '";
			RTEarea[editornumber].id = "RTEarea" + editornumber;
			RTEarea[editornumber].RTEWidthOverride = "' . trim($this->thisConfig['RTEWidthOverride']) . '";
			RTEarea[editornumber].RTEHeightOverride = "' . trim($this->thisConfig['RTEHeightOverride']) . '";
			RTEarea[editornumber].fullScreen = ' . ($this->fullScreen ? 'true' : 'false') . ';
			RTEarea[editornumber].showStatusBar = ' . (trim($this->thisConfig['showStatusBar']) ? 'true' : 'false') . ';
			RTEarea[editornumber].enableWordClean = ' . (trim($this->thisConfig['enableWordClean']) ? 'true' : 'false') . ';
			RTEarea[editornumber].htmlRemoveComments = ' . (trim($this->thisConfig['removeComments']) ? 'true' : 'false') . ';
			RTEarea[editornumber].disableEnterParagraphs = ' . (trim($this->thisConfig['disableEnterParagraphs']) ? 'true' : 'false') . ';
			RTEarea[editornumber].disableObjectResizing = ' . (trim($this->thisConfig['disableObjectResizing']) ? 'true' : 'false') . ';
			RTEarea[editornumber].removeTrailingBR = ' . (trim($this->thisConfig['removeTrailingBR']) ? 'true' : 'false') . ';
			RTEarea[editornumber].useCSS = ' . (trim($this->thisConfig['useCSS']) ? 'true' : 'false') . ';
			RTEarea[editornumber].keepButtonGroupTogether = ' . (trim($this->thisConfig['keepButtonGroupTogether']) ? 'true' : 'false') . ';
			RTEarea[editornumber].disablePCexamples = ' . (trim($this->thisConfig['disablePCexamples']) ? 'true' : 'false') . ';
			RTEarea[editornumber].showTagFreeClasses = ' . (trim($this->thisConfig['showTagFreeClasses']) ? 'true' : 'false') . ';
			RTEarea[editornumber].useHTTPS = ' . (trim(stristr($this->siteURL, 'https')) || $this->thisConfig['forceHTTPS'] ? 'true' : 'false') . ';
			RTEarea[editornumber].tceformsNested = ' . (is_object($this->TCEform) && method_exists($this->TCEform, 'getDynNestedStack') ? $this->TCEform->getDynNestedStack(true) : '[]') . ';
			RTEarea[editornumber].dialogueWindows = new Object();
			RTEarea[editornumber].dialogueWindows.defaultPositionFromTop = ' . (isset($this->thisConfig['dialogueWindows.']['defaultPositionFromTop']) ? intval($this->thisConfig['dialogueWindows.']['defaultPositionFromTop']) : '100') . ';
			RTEarea[editornumber].dialogueWindows.defaultPositionFromLeft = ' . (isset($this->thisConfig['dialogueWindows.']['defaultPositionFromLeft']) ? intval($this->thisConfig['dialogueWindows.']['defaultPositionFromLeft']) : '100') . ';
			RTEarea[editornumber].dialogueWindows.doNotResize = ' . (trim($this->thisConfig['dialogueWindows.']['doNotResize']) ? 'true' : 'false') . ';
			RTEarea[editornumber].dialogueWindows.doNotCenter = ' . (trim($this->thisConfig['dialogueWindows.']['doNotCenter']) ? 'true' : 'false') . ';';
        // The following properties apply only to the backend
        if (!$this->is_FE()) {
            $configureRTEInJavascriptString .= '
			RTEarea[editornumber].sys_language_content = "' . $this->contentLanguageUid . '";
			RTEarea[editornumber].typo3ContentLanguage = "' . $this->contentTypo3Language . '";
			RTEarea[editornumber].typo3ContentCharset = "' . $this->contentCharset . '";
			RTEarea[editornumber].userUid = "' . $this->userUid . '";';
        }
        // Setting the plugin flags
        $configureRTEInJavascriptString .= '
			RTEarea[editornumber].plugin = new Object();
			RTEarea[editornumber].pathToPluginDirectory = new Object();';
        foreach ($this->pluginEnabledArray as $pluginId) {
            $configureRTEInJavascriptString .= '
			RTEarea[editornumber].plugin.' . $pluginId . ' = true;';
            if (is_object($this->registeredPlugins[$pluginId])) {
                $pathToPluginDirectory = $this->registeredPlugins[$pluginId]->getPathToPluginDirectory();
                if ($pathToPluginDirectory) {
                    $configureRTEInJavascriptString .= '
			RTEarea[editornumber].pathToPluginDirectory.' . $pluginId . ' = "' . $pathToPluginDirectory . '";';
                }
            }
        }
        // Setting the buttons configuration
        $configureRTEInJavascriptString .= '
			RTEarea[editornumber].buttons = new Object();';
        if (is_array($this->thisConfig['buttons.'])) {
            foreach ($this->thisConfig['buttons.'] as $buttonIndex => $conf) {
                $button = substr($buttonIndex, 0, -1);
                if (in_array($button, $this->toolbar)) {
                    $configureRTEInJavascriptString .= '
			RTEarea[editornumber].buttons.' . $button . ' = ' . $this->buildNestedJSArray($conf) . ';';
                }
            }
        }
        // Setting the list of tags to be removed if specified in the RTE config
        if (trim($this->thisConfig['removeTags'])) {
            $configureRTEInJavascriptString .= '
			RTEarea[editornumber].htmlRemoveTags = /^(' . implode('|', t3lib_div::trimExplode(',', $this->thisConfig['removeTags'], 1)) . ')$/i;';
        }
        // Setting the list of tags to be removed with their contents if specified in the RTE config
        if (trim($this->thisConfig['removeTagsAndContents'])) {
            $configureRTEInJavascriptString .= '
			RTEarea[editornumber].htmlRemoveTagsAndContents = /^(' . implode('|', t3lib_div::trimExplode(',', $this->thisConfig['removeTagsAndContents'], 1)) . ')$/i;';
        }
        // Process default style configuration
        $configureRTEInJavascriptString .= '
			RTEarea[editornumber].defaultPageStyle = "' . $this->writeTemporaryFile('', 'defaultPageStyle', 'css', $this->buildStyleSheet()) . '";';
        // Setting the pageStyle
        $filename = trim($this->thisConfig['contentCSS']) ? trim($this->thisConfig['contentCSS']) : 'EXT:' . $this->ID . '/res/contentcss/default.css';
        $configureRTEInJavascriptString .= '
			RTEarea[editornumber].pageStyle = "' . t3lib_div::createVersionNumberedFilename($this->getFullFileName($filename)) . '";';
        // Process classes configuration
        $classesConfigurationRequired = false;
        foreach ($this->registeredPlugins as $pluginId => $plugin) {
            if ($this->isPluginEnabled($pluginId)) {
                $classesConfigurationRequired = $classesConfigurationRequired || $plugin->requiresClassesConfiguration();
            }
        }
        if ($classesConfigurationRequired) {
            $configureRTEInJavascriptString .= $this->buildJSClassesConfig($RTEcounter);
        }
        // Add Javascript configuration for registered plugins
        foreach ($this->registeredPlugins as $pluginId => $plugin) {
            if ($this->isPluginEnabled($pluginId)) {
                $configureRTEInJavascriptString .= $plugin->buildJavascriptConfiguration('editornumber');
            }
        }
        // Avoid premature reference to HTMLArea when being initially loaded by IRRE Ajax call
        $configureRTEInJavascriptString .= '
			RTEarea[editornumber].toolbar = ' . $this->getJSToolbarArray() . ';
			RTEarea[editornumber].convertButtonId = ' . json_encode(array_flip($this->convertToolbarForHtmlAreaArray)) . ';
			RTEarea.initEditor(editornumber);
				}
			};
			configureEditorInstance["' . $textAreaId . '"]();' . (!$this->is_FE() ? '' : '
			/*]]>*/');
        return $configureRTEInJavascriptString;
    }
 /**
  * Generation of TCEform elements of the type "inline"
  * This will render inline-relational-record sets. Relations.
  *
  * @param	string		$table: The table name of the record
  * @param	string		$field: The field name which this element is supposed to edit
  * @param	array		$row: The record data array where the value(s) for the field can be found
  * @param	array		$PA: An array with additional configuration options.
  * @return	string		The HTML code for the TCEform field
  */
 function getSingleField_typeInline($table, $field, $row, &$PA)
 {
     // check the TCA configuration - if false is returned, something was wrong
     if ($this->checkConfiguration($PA['fieldConf']['config']) === false) {
         return false;
     }
     // count the number of processed inline elements
     $this->inlineCount++;
     // Init:
     $config = $PA['fieldConf']['config'];
     $foreign_table = $config['foreign_table'];
     t3lib_div::loadTCA($foreign_table);
     if (t3lib_BEfunc::isTableLocalizable($table)) {
         $language = intval($row[$GLOBALS['TCA'][$table]['ctrl']['languageField']]);
     }
     $minitems = t3lib_div::intInRange($config['minitems'], 0);
     $maxitems = t3lib_div::intInRange($config['maxitems'], 0);
     if (!$maxitems) {
         $maxitems = 100000;
     }
     // Register the required number of elements:
     $this->fObj->requiredElements[$PA['itemFormElName']] = array($minitems, $maxitems, 'imgName' => $table . '_' . $row['uid'] . '_' . $field);
     // remember the page id (pid of record) where inline editing started first
     // we need that pid for ajax calls, so that they would know where the action takes place on the page structure
     if (!isset($this->inlineFirstPid)) {
         // if this record is not new, try to fetch the inlineView states
         // @TODO: Add checking/cleaning for unused tables, records, etc. to save space in uc-field
         if (t3lib_div::testInt($row['uid'])) {
             $inlineView = unserialize($GLOBALS['BE_USER']->uc['inlineView']);
             $this->inlineView = $inlineView[$table][$row['uid']];
         }
         // If the parent is a page, use the uid(!) of the (new?) page as pid for the child records:
         if ($table == 'pages') {
             $this->inlineFirstPid = $row['uid'];
             // If pid is negative, fetch the previous record and take its pid:
         } elseif ($row['pid'] < 0) {
             $prevRec = t3lib_BEfunc::getRecord($table, abs($row['pid']));
             $this->inlineFirstPid = $prevRec['pid'];
             // Take the pid as it is:
         } else {
             $this->inlineFirstPid = $row['pid'];
         }
     }
     // add the current inline job to the structure stack
     $this->pushStructure($table, $row['uid'], $field, $config);
     // e.g. data[<table>][<uid>][<field>]
     $nameForm = $this->inlineNames['form'];
     // e.g. data-<pid>-<table1>-<uid1>-<field1>-<table2>-<uid2>-<field2>
     $nameObject = $this->inlineNames['object'];
     // get the records related to this inline record
     $relatedRecords = $this->getRelatedRecords($table, $field, $row, $PA, $config);
     // set the first and last record to the config array
     $relatedRecordsUids = array_keys($relatedRecords['records']);
     $config['inline']['first'] = reset($relatedRecordsUids);
     $config['inline']['last'] = end($relatedRecordsUids);
     // Tell the browser what we have (using JSON later):
     $top = $this->getStructureLevel(0);
     $this->inlineData['config'][$nameObject] = array('table' => $foreign_table, 'md5' => md5($nameObject));
     $this->inlineData['config'][$nameObject . self::Structure_Separator . $foreign_table] = array('min' => $minitems, 'max' => $maxitems, 'sortable' => $config['appearance']['useSortable'], 'top' => array('table' => $top['table'], 'uid' => $top['uid']));
     // Set a hint for nested IRRE and tab elements:
     $this->inlineData['nested'][$nameObject] = $this->fObj->getDynNestedStack(false, $this->isAjaxCall);
     // if relations are required to be unique, get the uids that have already been used on the foreign side of the relation
     if ($config['foreign_unique']) {
         // If uniqueness *and* selector are set, they should point to the same field - so, get the configuration of one:
         $selConfig = $this->getPossibleRecordsSelectorConfig($config, $config['foreign_unique']);
         // Get the used unique ids:
         $uniqueIds = $this->getUniqueIds($relatedRecords['records'], $config, $selConfig['type'] == 'groupdb');
         $possibleRecords = $this->getPossibleRecords($table, $field, $row, $config, 'foreign_unique');
         $uniqueMax = $config['appearance']['useCombination'] || $possibleRecords === false ? -1 : count($possibleRecords);
         $this->inlineData['unique'][$nameObject . self::Structure_Separator . $foreign_table] = array('max' => $uniqueMax, 'used' => $uniqueIds, 'type' => $selConfig['type'], 'table' => $config['foreign_table'], 'elTable' => $selConfig['table'], 'field' => $config['foreign_unique'], 'selector' => $selConfig['selector'], 'possible' => $this->getPossibleRecordsFlat($possibleRecords));
     }
     // if it's required to select from possible child records (reusable children), add a selector box
     if ($config['foreign_selector']) {
         // if not already set by the foreign_unique, set the possibleRecords here and the uniqueIds to an empty array
         if (!$config['foreign_unique']) {
             $possibleRecords = $this->getPossibleRecords($table, $field, $row, $config);
             $uniqueIds = array();
         }
         $selectorBox = $this->renderPossibleRecordsSelector($possibleRecords, $config, $uniqueIds);
         $item .= $selectorBox;
     }
     // wrap all inline fields of a record with a <div> (like a container)
     $item .= '<div id="' . $nameObject . '">';
     // define how to show the "Create new record" link - if there are more than maxitems, hide it
     if ($relatedRecords['count'] >= $maxitems || $uniqueMax > 0 && $relatedRecords['count'] >= $uniqueMax) {
         $config['inline']['inlineNewButtonStyle'] = 'display: none;';
     }
     // Render the level links (create new record, localize all, synchronize):
     if ($config['appearance']['levelLinksPosition'] != 'none') {
         $levelLinks = $this->getLevelInteractionLink('newRecord', $nameObject . self::Structure_Separator . $foreign_table, $config);
         if ($language > 0) {
             // Add the "Localize all records" link before all child records:
             if (isset($config['appearance']['showAllLocalizationLink']) && $config['appearance']['showAllLocalizationLink']) {
                 $levelLinks .= $this->getLevelInteractionLink('localize', $nameObject . self::Structure_Separator . $foreign_table, $config);
             }
             // Add the "Synchronize with default language" link before all child records:
             if (isset($config['appearance']['showSynchronizationLink']) && $config['appearance']['showSynchronizationLink']) {
                 $levelLinks .= $this->getLevelInteractionLink('synchronize', $nameObject . self::Structure_Separator . $foreign_table, $config);
             }
         }
     }
     // Add the level links before all child records:
     if (in_array($config['appearance']['levelLinksPosition'], array('both', 'top'))) {
         $item .= $levelLinks;
     }
     $item .= '<div id="' . $nameObject . '_records">';
     $relationList = array();
     if (count($relatedRecords['records'])) {
         foreach ($relatedRecords['records'] as $rec) {
             $item .= $this->renderForeignRecord($row['uid'], $rec, $config);
             if (!isset($rec['__virtual']) || !$rec['__virtual']) {
                 $relationList[] = $rec['uid'];
             }
         }
     }
     $item .= '</div>';
     // Add the level links after all child records:
     if (in_array($config['appearance']['levelLinksPosition'], array('both', 'bottom'))) {
         $item .= $levelLinks;
     }
     // add Drag&Drop functions for sorting to TCEforms::$additionalJS_post
     if (count($relationList) > 1 && $config['appearance']['useSortable']) {
         $this->addJavaScriptSortable($nameObject . '_records');
     }
     // publish the uids of the child records in the given order to the browser
     $item .= '<input type="hidden" name="' . $nameForm . '" value="' . implode(',', $relationList) . '" class="inlineRecord" />';
     // close the wrap for all inline fields (container)
     $item .= '</div>';
     // on finishing this section, remove the last item from the structure stack
     $this->popStructure();
     // if this was the first call to the inline type, restore the values
     if (!$this->getStructureDepth()) {
         unset($this->inlineFirstPid);
     }
     return $item;
 }