/** * JavaScript bottom code * * @param string $formname The identification of the form on the page. * @return string A section with JavaScript - if $update is FALSE, embedded in <script></script> */ protected function JSbottom($formname = 'forms[0]') { $languageService = $this->getLanguageService(); $jsFile = array(); // @todo: this is messy here - "additional hidden fields" should be handled elsewhere $html = implode(LF, $this->hiddenFieldAccum); $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/md5.js'); // load the main module for FormEngine with all important JS functions $this->requireJsModules['TYPO3/CMS/Backend/FormEngine'] = 'function(FormEngine) { FormEngine.setBrowserUrl(' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('wizard_element_browser')) . '); }'; $this->requireJsModules['TYPO3/CMS/Backend/FormEngineValidation'] = 'function(FormEngineValidation) { FormEngineValidation.setUsMode(' . ($GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? '1' : '0') . '); FormEngineValidation.registerReady(); }'; $pageRenderer = $this->getPageRenderer(); foreach ($this->requireJsModules as $moduleName => $callbacks) { if (!is_array($callbacks)) { $callbacks = array($callbacks); } foreach ($callbacks as $callback) { $pageRenderer->loadRequireJsModule($moduleName, $callback); } } $pageRenderer->loadJquery(); $pageRenderer->loadExtJS(); // Load tree stuff here $pageRenderer->addJsFile('sysext/backend/Resources/Public/JavaScript/tree.js'); $pageRenderer->addInlineLanguageLabelFile(ExtensionManagementUtility::extPath('lang') . 'locallang_csh_corebe.xlf', 'tcatree'); $pageRenderer->addJsFile('sysext/backend/Resources/Public/JavaScript/notifications.js'); if (ExtensionManagementUtility::isLoaded('rtehtmlarea')) { // This js addition is hackish ... it will always load this file even if not RTE // is added here. But this simplifies RTE initialization a lot and is thus kept for now. $pageRenderer->addJsFile('sysext/rtehtmlarea/Resources/Public/JavaScript/HTMLArea/NameSpace/NameSpace.js'); } $beUserAuth = $this->getBackendUserAuthentication(); // Make textareas resizable and flexible ("autogrow" in height) $textareaSettings = array('autosize' => (bool) $beUserAuth->uc['resizeTextareas_Flexible']); $pageRenderer->addInlineSettingArray('Textarea', $textareaSettings); $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/jsfunc.tbe_editor.js'); $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ValueSlider'); // Needed for FormEngine manipulation (date picker) $dateFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? array('MM-DD-YYYY', 'HH:mm MM-DD-YYYY') : array('DD-MM-YYYY', 'HH:mm DD-MM-YYYY'); $pageRenderer->addInlineSetting('DateTimePicker', 'DateFormat', $dateFormat); // support placeholders for IE9 and lower $clientInfo = GeneralUtility::clientInfo(); if ($clientInfo['BROWSER'] == 'msie' && $clientInfo['VERSION'] <= 9) { $this->loadJavascriptLib('sysext/core/Resources/Public/JavaScript/Contrib/placeholders.jquery.min.js'); } $pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileListLocalisation'); $pageRenderer->addInlineLanguagelabelFile(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('lang') . 'locallang_core.xlf', 'file_upload'); // Load codemirror for T3Editor if (ExtensionManagementUtility::isLoaded('t3editor')) { $this->loadJavascriptLib('sysext/t3editor/Resources/Public/JavaScript/Contrib/codemirror/js/codemirror.js'); } // We want to load jQuery-ui inside our js. Enable this using requirejs. $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js'); $out = ' inline.setNoTitleString("' . addslashes(BackendUtility::getNoRecordTitle(true)) . '"); '; $out .= ' TBE_EDITOR.formname = "' . $formname . '"; TBE_EDITOR.formnameUENC = "' . rawurlencode($formname) . '"; TBE_EDITOR.backPath = ""; TBE_EDITOR.isPalettedoc = null; TBE_EDITOR.doSaveFieldName = "' . ($this->doSaveFieldName ? addslashes($this->doSaveFieldName) : '') . '"; TBE_EDITOR.labels.fieldsChanged = ' . GeneralUtility::quoteJSvalue($languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.fieldsChanged')) . '; TBE_EDITOR.labels.fieldsMissing = ' . GeneralUtility::quoteJSvalue($languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.fieldsMissing')) . '; TBE_EDITOR.labels.maxItemsAllowed = ' . GeneralUtility::quoteJSvalue($languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.maxItemsAllowed')) . '; TBE_EDITOR.labels.refresh_login = '******'LLL:EXT:lang/locallang_core.xlf:mess.refresh_login')) . '; TBE_EDITOR.labels.refreshRequired = {}; TBE_EDITOR.labels.refreshRequired.title = ' . GeneralUtility::quoteJSvalue($languageService->sL('LLL:EXT:lang/locallang_core.xlf:mess.refreshRequired.title')) . '; TBE_EDITOR.labels.refreshRequired.content = ' . GeneralUtility::quoteJSvalue($languageService->sL('LLL:EXT:lang/locallang_core.xlf:mess.refreshRequired.content')) . '; TBE_EDITOR.labels.remainingCharacters = ' . GeneralUtility::quoteJSvalue($languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.remainingCharacters')) . '; TBE_EDITOR.customEvalFunctions = {}; '; // Add JS required for inline fields if (!empty($this->inlineData)) { $out .= ' inline.addToDataArray(' . json_encode($this->inlineData) . '); '; } // $this->additionalJS_submit: if ($this->additionalJS_submit) { $additionalJS_submit = implode('', $this->additionalJS_submit); $additionalJS_submit = str_replace(array(CR, LF), '', $additionalJS_submit); $out .= ' TBE_EDITOR.addActionChecks("submit", "' . addslashes($additionalJS_submit) . '"); '; } $out .= LF . implode(LF, $this->additionalJS_post) . LF . $this->extJSCODE; $spacer = LF . TAB; $out = $html . $spacer . implode($spacer, $jsFile) . GeneralUtility::wrapJS($out); return $out; }
/** * Renders the HTML header for a foreign record, such as the title, toggle-function, drag'n'drop, etc. * Later on the command-icons are inserted here. * * @param string $parentUid The uid of the parent (embedding) record (uid or NEW...) * @param string $foreign_table The foreign_table we create a header for * @param array $rec The current record of that foreign_table * @param array $config content of $PA['fieldConf']['config'] * @param boolean $isVirtualRecord * @return string The HTML code of the header * @todo Define visibility */ public function renderForeignRecordHeader($parentUid, $foreign_table, $rec, $config, $isVirtualRecord = FALSE) { // Init: $objectId = $this->inlineNames['object'] . self::Structure_Separator . $foreign_table . self::Structure_Separator . $rec['uid']; // 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) // Pre-Processing: $isOnSymmetricSide = RelationHandler::isOnSymmetricSide($parentUid, $config, $rec); $hasForeignLabel = !$isOnSymmetricSide && $config['foreign_label'] ? TRUE : FALSE; $hasSymmetricLabel = $isOnSymmetricSide && $config['symmetric_label'] ? TRUE : FALSE; // Get the record title/label for a record: // Try using a self-defined user function only for formatted labels if (isset($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc'])) { $params = array('table' => $foreign_table, 'row' => $rec, 'title' => '', 'isOnSymmetricSide' => $isOnSymmetricSide, 'options' => isset($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc_options']) ? $GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc_options'] : array(), 'parent' => array('uid' => $parentUid, 'config' => $config)); // callUserFunction requires a third parameter, but we don't want to give $this as reference! $null = NULL; GeneralUtility::callUserFunction($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc'], $params, $null); $recTitle = $params['title']; // Try using a normal self-defined user function } elseif (isset($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc'])) { $params = array('table' => $foreign_table, 'row' => $rec, 'title' => '', 'isOnSymmetricSide' => $isOnSymmetricSide, 'parent' => array('uid' => $parentUid, 'config' => $config)); // callUserFunction requires a third parameter, but we don't want to give $this as reference! $null = NULL; GeneralUtility::callUserFunction($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc'], $params, $null); $recTitle = $params['title']; } elseif ($hasForeignLabel || $hasSymmetricLabel) { $titleCol = $hasForeignLabel ? $config['foreign_label'] : $config['symmetric_label']; $foreignConfig = $this->getPossibleRecordsSelectorConfig($config, $titleCol); // Render title for everything else than group/db: if ($foreignConfig['type'] != 'groupdb') { $recTitle = BackendUtility::getProcessedValueExtra($foreign_table, $titleCol, $rec[$titleCol], 0, 0, FALSE); } else { // $recTitle could be something like: "tx_table_123|...", $valueParts = GeneralUtility::trimExplode('|', $rec[$titleCol]); $itemParts = GeneralUtility::revExplode('_', $valueParts[0], 2); $recTemp = BackendUtility::getRecordWSOL($itemParts[0], $itemParts[1]); $recTitle = BackendUtility::getRecordTitle($itemParts[0], $recTemp, FALSE); } $recTitle = BackendUtility::getRecordTitlePrep($recTitle); if (trim($recTitle) === '') { $recTitle = BackendUtility::getNoRecordTitle(TRUE); } } else { $recTitle = BackendUtility::getRecordTitle($foreign_table, $rec, TRUE); } $altText = BackendUtility::getRecordIconAltText($rec, $foreign_table); $iconImg = IconUtility::getSpriteIconForRecord($foreign_table, $rec, array('title' => htmlspecialchars($altText), 'id' => $objectId . '_icon')); $label = '<span id="' . $objectId . '_label">' . $recTitle . '</span>'; $ctrl = $this->renderForeignRecordHeaderControl($parentUid, $foreign_table, $rec, $config, $isVirtualRecord); $thumbnail = FALSE; // Renders a thumbnail for the header if (!empty($config['appearance']['headerThumbnail']['field'])) { $fieldValue = $rec[$config['appearance']['headerThumbnail']['field']]; $firstElement = array_shift(GeneralUtility::trimExplode(',', $fieldValue)); $fileUid = array_pop(BackendUtility::splitTable_Uid($firstElement)); if (!empty($fileUid)) { $fileObject = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->getFileObject($fileUid); if ($fileObject && $fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject); $thumbnail = $flashMessage->render(); } elseif ($fileObject) { $imageSetup = $config['appearance']['headerThumbnail']; unset($imageSetup['field']); $imageSetup = array_merge(array('width' => '45', 'height' => '45c'), $imageSetup); $processedImage = $fileObject->process(\TYPO3\CMS\Core\Resource\ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $imageSetup); // Only use a thumbnail if the processing was successful. if (!$processedImage->usesOriginalFile()) { $imageUrl = $processedImage->getPublicUrl(TRUE); $thumbnail = '<img class="t3-form-field-header-inline-thumbnail-image" src="' . $imageUrl . '" alt="' . htmlspecialchars($altText) . '" title="' . htmlspecialchars($altText) . '">'; } } } } if (!empty($config['appearance']['headerThumbnail']['field']) && $thumbnail) { $headerClasses = ' t3-form-field-header-inline-has-thumbnail'; $mediaContainer = '<div class="t3-form-field-header-inline-thumbnail" id="' . $objectId . '_thumbnailcontainer">' . $thumbnail . '</div>'; } else { $headerClasses = ' t3-form-field-header-inline-has-icon'; $mediaContainer = '<div class="t3-form-field-header-inline-icon" id="' . $objectId . '_iconcontainer">' . $iconImg . '</div>'; } $header = '<div class="t3-form-field-header-inline-wrap' . $headerClasses . '">' . '<div class="t3-form-field-header-inline-ctrl">' . $ctrl . '</div>' . '<div class="t3-form-field-header-inline-body">' . $mediaContainer . '<div class="t3-form-field-header-inline-summary">' . $label . '</div>' . '</div>' . '</div>'; return $header; }
/** * JavaScript code used for input-field evaluation. * * Example use: * * $msg .= 'Distribution time (hh:mm dd-mm-yy):<br /><input type="text" name="send_mail_datetime_hr"' * . ' onchange="typo3form.fieldGet(\'send_mail_datetime\', \'datetime\', \'\', 0,0);"' * . $this->getTBE()->formWidth(20) . ' /><input type="hidden" value="' . $GLOBALS['EXEC_TIME'] * . '" name="send_mail_datetime" /><br />'; * $this->extJSCODE .= 'typo3form.fieldSet("send_mail_datetime", "datetime", "", 0,0);'; * * ... and then include the result of this function after the form * * @param string $formname The identification of the form on the page. * @param boolean $update Just extend/update existing settings, e.g. for AJAX call * @return string A section with JavaScript - if $update is FALSE, embedded in <script></script> * @todo Define visibility */ public function JSbottom($formname = 'forms[0]', $update = FALSE) { $jsFile = array(); $elements = array(); $out = ''; // Required: foreach ($this->requiredFields as $itemImgName => $itemName) { $match = array(); if (preg_match('/^(.+)\\[((\\w|\\d|_)+)\\]$/', $itemName, $match)) { $record = $match[1]; $field = $match[2]; $elements[$record][$field]['required'] = 1; $elements[$record][$field]['requiredImg'] = $itemImgName; if (isset($this->requiredAdditional[$itemName]) && is_array($this->requiredAdditional[$itemName])) { $elements[$record][$field]['additional'] = $this->requiredAdditional[$itemName]; } } } // Range: foreach ($this->requiredElements as $itemName => $range) { if (preg_match('/^(.+)\\[((\\w|\\d|_)+)\\]$/', $itemName, $match)) { $record = $match[1]; $field = $match[2]; $elements[$record][$field]['range'] = array($range[0], $range[1]); $elements[$record][$field]['rangeImg'] = $range['imgName']; } } $this->TBE_EDITOR_fieldChanged_func = 'TBE_EDITOR.fieldChanged_fName(fName,formObj[fName+"_list"]);'; if (!$update) { if ($this->loadMD5_JS) { $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/md5.js'); } $pageRenderer = $this->getPageRenderer(); // load the main module for FormEngine with all important JS functions $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/FormEngine'); $pageRenderer->loadPrototype(); $pageRenderer->loadJquery(); $pageRenderer->loadExtJS(); // Make textareas resizable and flexible $beUserAuth = $this->getBackendUserAuthentication(); if (!($beUserAuth->uc['resizeTextareas'] == '0' && $beUserAuth->uc['resizeTextareas_Flexible'] == '0')) { $pageRenderer->addCssFile($this->backPath . 'js/extjs/ux/resize.css'); $this->loadJavascriptLib('js/extjs/ux/ext.resizable.js'); } $resizableSettings = array('textareaMaxHeight' => $beUserAuth->uc['resizeTextareas_MaxHeight'] > 0 ? $beUserAuth->uc['resizeTextareas_MaxHeight'] : '600', 'textareaFlexible' => !$beUserAuth->uc['resizeTextareas_Flexible'] == '0', 'textareaResize' => !$beUserAuth->uc['resizeTextareas'] == '0'); $pageRenderer->addInlineSettingArray('', $resizableSettings); $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/jsfunc.evalfield.js'); $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/jsfunc.tbe_editor.js'); // support placeholders for IE9 and lower if ($this->clientInfo['BROWSER'] == 'msie' && $this->clientInfo['VERSION'] <= 9) { $this->loadJavascriptLib('contrib/placeholdersjs/placeholders.jquery.min.js'); } // Needed for tceform manipulation (date picker) $typo3Settings = array('datePickerUSmode' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? 1 : 0, 'dateFormat' => array('j-n-Y', 'G:i j-n-Y'), 'dateFormatUS' => array('n-j-Y', 'G:i n-j-Y')); $pageRenderer->addInlineSettingArray('', $typo3Settings); $this->loadJavascriptLib('js/extjs/ux/Ext.ux.DateTimePicker.js'); $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/tceforms.js'); // If IRRE fields were processed, add the JavaScript functions: if ($this->inline->inlineCount) { $pageRenderer->loadScriptaculous(); // We want to load jQuery-ui inside our js. Enable this using requirejs. $pageRenderer->loadRequireJs(); $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js'); $out .= ' inline.setPrependFormFieldNames("' . $this->inline->prependNaming . '"); inline.setNoTitleString("' . addslashes(BackendUtility::getNoRecordTitle(TRUE)) . '"); '; // Always include JS functions for Suggest fields as we don't know what will come $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/jsfunc.tceforms_suggest.js'); $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/jsfunc.tceforms_selectboxfilter.js'); } else { // If Suggest fields were processed, add the JS functions if ($this->suggest->suggestCount > 0) { $pageRenderer->loadScriptaculous(); $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/jsfunc.tceforms_suggest.js'); } if ($this->multiSelectFilterCount > 0) { $pageRenderer->loadScriptaculous(); $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/jsfunc.tceforms_selectboxfilter.js'); } } // Toggle icons: $toggleIcon_open = IconUtility::getSpriteIcon('actions-move-down', array('title' => 'Open')); $toggleIcon_close = IconUtility::getSpriteIcon('actions-move-right', array('title' => 'Close')); $out .= ' function getOuterHTML(idTagPrefix) { // Function getting the outerHTML of an element with id var str=($(idTagPrefix).inspect()+$(idTagPrefix).innerHTML+"</"+$(idTagPrefix).tagName.toLowerCase()+">"); return str; } function flexFormToggle(id) { // Toggling flexform elements on/off: Element.toggle(""+id+"-content"); if (Element.visible(id+"-content")) { $(id+"-toggle").update(\'' . $toggleIcon_open . '\'); $(id+"-toggleClosed").value = 0; } else { $(id+"-toggle").update(\'' . $toggleIcon_close . '\'); $(id+"-toggleClosed").value = 1; } var previewContent = ""; var children = $(id+"-content").getElementsByTagName("input"); for (var i = 0, length = children.length; i < length; i++) { if (children[i].type=="text" && children[i].value) previewContent+= (previewContent?" / ":"")+children[i].value; } if (previewContent.length>80) { previewContent = previewContent.substring(0,67)+"..."; } $(id+"-preview").update(previewContent); } function flexFormToggleSubs(id) { // Toggling sub flexform elements on/off: var descendants = $(id).immediateDescendants(); var isOpen=0; var isClosed=0; // Traverse and find how many are open or closed: for (var i = 0, length = descendants.length; i < length; i++) { if (descendants[i].id) { if (Element.visible(descendants[i].id+"-content")) {isOpen++;} else {isClosed++;} } } // Traverse and toggle for (var i = 0, length = descendants.length; i < length; i++) { if (descendants[i].id) { if (isOpen!=0 && isClosed!=0) { if (Element.visible(descendants[i].id+"-content")) {flexFormToggle(descendants[i].id);} } else { flexFormToggle(descendants[i].id); } } } } function flexFormSortable(id) { // Create sortables for flexform sections Position.includeScrollOffsets = true; Sortable.create(id, {tag:\'div\',constraint: false, onChange:function(){ setActionStatus(id); } }); } function setActionStatus(id) { // Updates the "action"-status for a section. This is used to move and delete elements. var descendants = $(id).immediateDescendants(); // Traverse and find how many are open or closed: for (var i = 0, length = descendants.length; i < length; i++) { if (descendants[i].id) { $(descendants[i].id+"-action").value = descendants[i].visible() ? i : "DELETE"; } } } TBE_EDITOR.images.req.src = "' . IconUtility::skinImg($this->backPath, 'gfx/required_h.gif', '', 1) . '"; TBE_EDITOR.images.cm.src = "' . IconUtility::skinImg($this->backPath, 'gfx/content_client.gif', '', 1) . '"; TBE_EDITOR.images.sel.src = "' . IconUtility::skinImg($this->backPath, 'gfx/content_selected.gif', '', 1) . '"; TBE_EDITOR.images.clear.src = "' . $this->backPath . 'clear.gif"; TBE_EDITOR.auth_timeout_field = ' . (int) $beUserAuth->auth_timeout_field . '; TBE_EDITOR.formname = "' . $formname . '"; TBE_EDITOR.formnameUENC = "' . rawurlencode($formname) . '"; TBE_EDITOR.backPath = "' . addslashes($this->backPath) . '"; TBE_EDITOR.prependFormFieldNames = "' . $this->prependFormFieldNames . '"; TBE_EDITOR.prependFormFieldNamesUENC = "' . rawurlencode($this->prependFormFieldNames) . '"; TBE_EDITOR.prependFormFieldNamesCnt = ' . substr_count($this->prependFormFieldNames, '[') . '; TBE_EDITOR.isPalettedoc = ' . ($this->isPalettedoc ? addslashes($this->isPalettedoc) : 'null') . '; TBE_EDITOR.doSaveFieldName = "' . ($this->doSaveFieldName ? addslashes($this->doSaveFieldName) : '') . '"; TBE_EDITOR.labels.fieldsChanged = ' . GeneralUtility::quoteJSvalue($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.fieldsChanged')) . '; TBE_EDITOR.labels.fieldsMissing = ' . GeneralUtility::quoteJSvalue($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.fieldsMissing')) . '; TBE_EDITOR.labels.refresh_login = '******'m_refresh_login')) . '; TBE_EDITOR.labels.onChangeAlert = ' . GeneralUtility::quoteJSvalue($this->getLL('m_onChangeAlert')) . '; evalFunc.USmode = ' . ($GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? '1' : '0') . '; TBE_EDITOR.backend_interface = "' . $beUserAuth->uc['interfaceSetup'] . '"; TBE_EDITOR.customEvalFunctions = {}; '; } // Add JS required for inline fields if (count($this->inline->inlineData)) { $out .= ' inline.addToDataArray(' . json_encode($this->inline->inlineData) . '); '; } // Registered nested elements for tabs or inline levels: if (count($this->requiredNested)) { $out .= ' TBE_EDITOR.addNested(' . json_encode($this->requiredNested) . '); '; } // Elements which are required or have a range definition: if (count($elements)) { $out .= ' TBE_EDITOR.addElements(' . json_encode($elements) . '); TBE_EDITOR.initRequired(); '; } // $this->additionalJS_submit: if ($this->additionalJS_submit) { $additionalJS_submit = implode('', $this->additionalJS_submit); $additionalJS_submit = str_replace(array(CR, LF), '', $additionalJS_submit); $out .= ' TBE_EDITOR.addActionChecks("submit", "' . addslashes($additionalJS_submit) . '"); '; } $out .= LF . implode(LF, $this->additionalJS_post) . LF . $this->extJSCODE; $out .= ' TBE_EDITOR.loginRefreshed(); '; // Regular direct output: if (!$update) { $spacer = LF . TAB; $out = $spacer . implode($spacer, $jsFile) . GeneralUtility::wrapJS($out); } return $out; }
/** * Renders the HTML header for a foreign record, such as the title, toggle-function, drag'n'drop, etc. * Later on the command-icons are inserted here. * * @param string $parentUid The uid of the parent (embedding) record (uid or NEW...) * @param string $foreign_table The foreign_table we create a header for * @param array $data Current data * @param array $config content of $PA['fieldConf']['config'] * @param bool $isVirtualRecord * @return string The HTML code of the header */ protected function renderForeignRecordHeader($parentUid, $foreign_table, $data, $config, $isVirtualRecord = false) { $rec = $data['databaseRow']; // Init: $domObjectId = $this->inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($this->data['inlineFirstPid']); $objectId = $domObjectId . '-' . $foreign_table . '-' . $rec['uid']; // 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) // Pre-Processing: $isOnSymmetricSide = RelationHandler::isOnSymmetricSide($parentUid, $config, $rec); $hasForeignLabel = (bool) (!$isOnSymmetricSide && $config['foreign_label']); $hasSymmetricLabel = (bool) $isOnSymmetricSide && $config['symmetric_label']; // Get the record title/label for a record: // Try using a self-defined user function only for formatted labels if (isset($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc'])) { $params = array('table' => $foreign_table, 'row' => $rec, 'title' => '', 'isOnSymmetricSide' => $isOnSymmetricSide, 'options' => isset($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc_options']) ? $GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc_options'] : array(), 'parent' => array('uid' => $parentUid, 'config' => $config)); // callUserFunction requires a third parameter, but we don't want to give $this as reference! $null = null; GeneralUtility::callUserFunction($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc'], $params, $null); $recTitle = $params['title']; // Try using a normal self-defined user function } elseif (isset($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc'])) { $recTitle = $data['recordTitle']; } elseif ($hasForeignLabel || $hasSymmetricLabel) { $titleCol = $hasForeignLabel ? $config['foreign_label'] : $config['symmetric_label']; // Render title for everything else than group/db: if (isset($this->data['processedTca']['columns'][$titleCol]['config']['type']) && $this->data['processedTca']['columns'][$titleCol]['config']['type'] === 'group' && isset($this->data['processedTca']['columns'][$titleCol]['config']['internal_type']) && $this->data['processedTca']['columns'][$titleCol]['config']['internal_type'] === 'db') { $recTitle = BackendUtility::getProcessedValueExtra($foreign_table, $titleCol, $rec[$titleCol], 0, 0, false); } else { // $recTitle could be something like: "tx_table_123|...", $valueParts = GeneralUtility::trimExplode('|', $rec[$titleCol]); $itemParts = GeneralUtility::revExplode('_', $valueParts[0], 2); $recTemp = BackendUtility::getRecordWSOL($itemParts[0], $itemParts[1]); $recTitle = BackendUtility::getRecordTitle($itemParts[0], $recTemp, false); } $recTitle = BackendUtility::getRecordTitlePrep($recTitle); if (trim($recTitle) === '') { $recTitle = BackendUtility::getNoRecordTitle(true); } } else { $recTitle = BackendUtility::getRecordTitle($foreign_table, FormEngineUtility::databaseRowCompatibility($rec), true); } $altText = BackendUtility::getRecordIconAltText($rec, $foreign_table); $iconImg = '<span title="' . $altText . '" id="' . htmlspecialchars($objectId) . '_icon' . '">' . $this->iconFactory->getIconForRecord($foreign_table, $rec, Icon::SIZE_SMALL)->render() . '</span>'; $label = '<span id="' . $objectId . '_label">' . $recTitle . '</span>'; $ctrl = $this->renderForeignRecordHeaderControl($parentUid, $foreign_table, $data, $config, $isVirtualRecord); $thumbnail = false; // Renders a thumbnail for the header if (!empty($config['appearance']['headerThumbnail']['field'])) { $fieldValue = $rec[$config['appearance']['headerThumbnail']['field']]; $firstElement = array_shift(GeneralUtility::trimExplode('|', array_shift(GeneralUtility::trimExplode(',', $fieldValue)))); $fileUid = array_pop(BackendUtility::splitTable_Uid($firstElement)); if (!empty($fileUid)) { $fileObject = ResourceFactory::getInstance()->getFileObject($fileUid); if ($fileObject && $fileObject->isMissing()) { $flashMessage = \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject); $thumbnail = $flashMessage->render(); } elseif ($fileObject) { $imageSetup = $config['appearance']['headerThumbnail']; unset($imageSetup['field']); if (!empty($rec['crop'])) { $imageSetup['crop'] = $rec['crop']; } $imageSetup = array_merge(array('width' => '45', 'height' => '45c'), $imageSetup); $processedImage = $fileObject->process(ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $imageSetup); // Only use a thumbnail if the processing process was successful by checking if image width is set if ($processedImage->getProperty('width')) { $imageUrl = $processedImage->getPublicUrl(true); $thumbnail = '<img src="' . $imageUrl . '" ' . 'width="' . $processedImage->getProperty('width') . '" ' . 'height="' . $processedImage->getProperty('height') . '" ' . 'alt="' . htmlspecialchars($altText) . '" ' . 'title="' . htmlspecialchars($altText) . '">'; } } } } if (!empty($config['appearance']['headerThumbnail']['field']) && $thumbnail) { $mediaContainer = '<div class="form-irre-header-cell form-irre-header-thumbnail" id="' . $objectId . '_thumbnailcontainer">' . $thumbnail . '</div>'; } else { $mediaContainer = '<div class="form-irre-header-cell form-irre-header-icon" id="' . $objectId . '_iconcontainer">' . $iconImg . '</div>'; } $header = $mediaContainer . ' <div class="form-irre-header-cell form-irre-header-body">' . $label . '</div> <div class="form-irre-header-cell form-irre-header-control t3js-formengine-irre-control">' . $ctrl . '</div>'; return $header; }
/** * Render different label for media elements * * @param array $params configuration * @return void */ public function getUserLabelMedia(array &$params) { $ll = 'LLL:EXT:news/Resources/Private/Language/locallang_db.xlf:'; $typeInfo = $additionalHtmlContent = ''; $type = $GLOBALS['LANG']->sL($ll . 'tx_news_domain_model_media.type.I.' . $params['row']['type']); // Add additional info based on type switch ((int) $params['row']['type']) { // Image case Media::MEDIA_TYPE_IMAGE: $typeInfo .= $this->getTitleFromFields('title,alt,caption,image', $params['row']); if (!empty($params['row']['image'])) { $params['row']['image'] = $this->splitFileName($params['row']['image']); try { $additionalHtmlContent = '<br />' . BackendUtilityCore::thumbCode($params['row'], 'tx_news_domain_model_media', 'image', $GLOBALS['BACK_PATH'], '', NULL, 0, '', '', FALSE); } catch (\TYPO3\CMS\Core\Resource\Exception\FolderDoesNotExistException $exception) { $additionalHtmlContent = '<br />' . htmlspecialchars($params['row']['image']); } } break; // Audio & Video // Audio & Video case Media::MEDIA_TYPE_MULTIMEDIA: $typeInfo .= $this->getTitleFromFields('caption,multimedia', $params['row']); break; // HTML // HTML case Media::MEDIA_TYPE_HTML: // Don't show html value as this could get a XSS $typeInfo .= $params['row']['caption']; break; default: $typeInfo .= $params['row']['caption']; } $title = !empty($typeInfo) ? $type . ': ' . $typeInfo : $type; $title = htmlspecialchars($title) . $additionalHtmlContent; // Hook to modify the label, especially useful when using custom media relations if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['mediaLabel'])) { $params = array('params' => $params, 'title' => $title); foreach ($GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['mediaLabel'] as $reference) { $title = GeneralUtility::callUserFunction($reference, $params, $this); } } // Preview if ($params['row']['showinpreview']) { $label = htmlspecialchars($GLOBALS['LANG']->sL($ll . 'tx_news_domain_model_media.show')); $icon = '../' . ExtensionManagementUtility::siteRelPath('news') . 'Resources/Public/Icons/preview.gif'; $title .= ' <img title="' . $label . '" src="' . $icon . '" />'; } // Show the [No title] if empty if (empty($title)) { $title = BackendUtilityCore::getNoRecordTitle(TRUE); } $params['title'] = $title; }
/** * JavaScript bottom code * * @param string $formname The identification of the form on the page. * @param bool $update Just extend/update existing settings, e.g. for AJAX call * @return string A section with JavaScript - if $update is FALSE, embedded in <script></script> */ public function JSbottom($formname = 'forms[0]', $update = FALSE) { $languageService = $this->getLanguageService(); $jsFile = array(); $out = ''; $this->TBE_EDITOR_fieldChanged_func = 'TBE_EDITOR.fieldChanged_fName(fName,formObj[fName+"_list"]);'; if (!$update) { if ($this->loadMD5_JS) { $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/md5.js'); } $pageRenderer = $this->getPageRenderer(); // load the main module for FormEngine with all important JS functions $this->requireJsModules['TYPO3/CMS/Backend/FormEngine'] = 'function(FormEngine) { FormEngine.setBrowserUrl(' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('browser')) . '); }'; foreach ($this->requireJsModules as $moduleName => $callbacks) { if (!is_array($callbacks)) { $callbacks = array($callbacks); } foreach ($callbacks as $callback) { $pageRenderer->loadRequireJsModule($moduleName, $callback); } } $pageRenderer->loadPrototype(); $pageRenderer->loadJquery(); $pageRenderer->loadExtJS(); $beUserAuth = $this->getBackendUserAuthentication(); // Make textareas resizable and flexible ("autogrow" in height) $textareaSettings = array('autosize' => (bool) $beUserAuth->uc['resizeTextareas_Flexible']); $pageRenderer->addInlineSettingArray('Textarea', $textareaSettings); $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/jsfunc.evalfield.js'); $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/jsfunc.tbe_editor.js'); $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ValueSlider'); // Needed for FormEngine manipulation (date picker) $dateFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? array('MM-DD-YYYY', 'HH:mm MM-DD-YYYY') : array('DD-MM-YYYY', 'HH:mm DD-MM-YYYY'); $pageRenderer->addInlineSetting('DateTimePicker', 'DateFormat', $dateFormat); // support placeholders for IE9 and lower $clientInfo = GeneralUtility::clientInfo(); if ($clientInfo['BROWSER'] == 'msie' && $clientInfo['VERSION'] <= 9) { $this->loadJavascriptLib('sysext/core/Resources/Public/JavaScript/Contrib/placeholders.jquery.min.js'); } // @todo: remove scriptaclous once suggest & flex form foo is moved to RequireJS, see #55575 $pageRenderer->loadScriptaculous(); $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/jsfunc.tceforms_suggest.js'); $pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileListLocalisation'); $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/DragUploader'); $pageRenderer->addInlineLanguagelabelFile(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('lang') . 'locallang_core.xlf', 'file_upload'); // We want to load jQuery-ui inside our js. Enable this using requirejs. $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js'); $out .= ' inline.setNoTitleString("' . addslashes(BackendUtility::getNoRecordTitle(TRUE)) . '"); '; $out .= ' TBE_EDITOR.formname = "' . $formname . '"; TBE_EDITOR.formnameUENC = "' . rawurlencode($formname) . '"; TBE_EDITOR.backPath = ""; TBE_EDITOR.isPalettedoc = null; TBE_EDITOR.doSaveFieldName = "' . ($this->doSaveFieldName ? addslashes($this->doSaveFieldName) : '') . '"; TBE_EDITOR.labels.fieldsChanged = ' . GeneralUtility::quoteJSvalue($languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.fieldsChanged')) . '; TBE_EDITOR.labels.fieldsMissing = ' . GeneralUtility::quoteJSvalue($languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.fieldsMissing')) . '; TBE_EDITOR.labels.maxItemsAllowed = ' . GeneralUtility::quoteJSvalue($languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.maxItemsAllowed')) . '; TBE_EDITOR.labels.refresh_login = '******'LLL:EXT:lang/locallang_core.xlf:mess.refresh_login')) . '; TBE_EDITOR.labels.onChangeAlert = ' . GeneralUtility::quoteJSvalue($languageService->sL('LLL:EXT:lang/locallang_core.xlf:mess.onChangeAlert')) . '; TBE_EDITOR.labels.remainingCharacters = ' . GeneralUtility::quoteJSvalue($languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.remainingCharacters')) . '; evalFunc.USmode = ' . ($GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? '1' : '0') . '; TBE_EDITOR.customEvalFunctions = {}; '; } // Add JS required for inline fields if (!empty($this->inlineData)) { $out .= ' inline.addToDataArray(' . json_encode($this->inlineData) . '); '; } // $this->additionalJS_submit: if ($this->additionalJS_submit) { $additionalJS_submit = implode('', $this->additionalJS_submit); $additionalJS_submit = str_replace(array(CR, LF), '', $additionalJS_submit); $out .= ' TBE_EDITOR.addActionChecks("submit", "' . addslashes($additionalJS_submit) . '"); '; } $out .= LF . implode(LF, $this->additionalJS_post) . LF . $this->extJSCODE; // Regular direct output: if (!$update) { $spacer = LF . TAB; $out = $spacer . implode($spacer, $jsFile) . GeneralUtility::wrapJS($out); } return $out; }
/** * Renders the HTML header for a foreign record, such as the title, toggle-function, drag'n'drop, etc. * Later on the command-icons are inserted here. * * @param string $parentUid The uid of the parent (embedding) record (uid or NEW...) * @param string $foreign_table The foreign_table we create a header for * @param array $rec The current record of that foreign_table * @param array $config content of $PA['fieldConf']['config'] * @param boolean $isVirtualRecord * @return string The HTML code of the header * @todo Define visibility */ public function renderForeignRecordHeader($parentUid, $foreign_table, $rec, $config, $isVirtualRecord = FALSE) { // Init: $objectId = $this->inlineNames['object'] . self::Structure_Separator . $foreign_table . self::Structure_Separator . $rec['uid']; // 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) // Pre-Processing: $isOnSymmetricSide = \TYPO3\CMS\Core\Database\RelationHandler::isOnSymmetricSide($parentUid, $config, $rec); $hasForeignLabel = !$isOnSymmetricSide && $config['foreign_label'] ? TRUE : FALSE; $hasSymmetricLabel = $isOnSymmetricSide && $config['symmetric_label'] ? TRUE : FALSE; // Get the record title/label for a record: // render using a self-defined user function if ($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc']) { $params = array('table' => $foreign_table, 'row' => $rec, 'title' => '', 'isOnSymmetricSide' => $isOnSymmetricSide, 'parent' => array('uid' => $parentUid, 'config' => $config)); // callUserFunction requires a third parameter, but we don't want to give $this as reference! $null = NULL; \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc'], $params, $null); $recTitle = $params['title']; } elseif ($hasForeignLabel || $hasSymmetricLabel) { $titleCol = $hasForeignLabel ? $config['foreign_label'] : $config['symmetric_label']; $foreignConfig = $this->getPossibleRecordsSelectorConfig($config, $titleCol); // Render title for everything else than group/db: if ($foreignConfig['type'] != 'groupdb') { $recTitle = \TYPO3\CMS\Backend\Utility\BackendUtility::getProcessedValueExtra($foreign_table, $titleCol, $rec[$titleCol], 0, 0, FALSE); } else { // $recTitle could be something like: "tx_table_123|...", $valueParts = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode('|', $rec[$titleCol]); $itemParts = \TYPO3\CMS\Core\Utility\GeneralUtility::revExplode('_', $valueParts[0], 2); $recTemp = \t3lib_befunc::getRecordWSOL($itemParts[0], $itemParts[1]); $recTitle = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle($itemParts[0], $recTemp, FALSE); } $recTitle = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitlePrep($recTitle); if (!strcmp(trim($recTitle), '')) { $recTitle = \TYPO3\CMS\Backend\Utility\BackendUtility::getNoRecordTitle(TRUE); } } else { $recTitle = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle($foreign_table, $rec, TRUE); } // Renders a thumbnail for the header if (!empty($config['appearance']['headerThumbnail']['field'])) { $fieldValue = $rec[$config['appearance']['headerThumbnail']['field']]; $firstElement = array_shift(\TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $fieldValue)); $fileUid = array_pop(\TYPO3\CMS\Backend\Utility\BackendUtility::splitTable_Uid($firstElement)); if (!empty($fileUid)) { $fileObject = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->getFileObject($fileUid); if ($fileObject) { $imageSetup = $config['appearance']['headerThumbnail']; unset($imageSetup['field']); $imageSetup = array_merge(array('width' => 64, 'height' => 64), $imageSetup); $imageUrl = $fileObject->process(\TYPO3\CMS\Core\Resource\ProcessedFile::CONTEXT_IMAGEPREVIEW, $imageSetup)->getPublicUrl(TRUE); $thumbnail = '<img src="' . $imageUrl . '" alt="' . htmlspecialchars($recTitle) . '">'; } else { $thumbnail = FALSE; } } } $altText = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordIconAltText($rec, $foreign_table); $iconImg = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord($foreign_table, $rec, array('title' => htmlspecialchars($altText), 'id' => $objectId . '_icon')); $label = '<span id="' . $objectId . '_label">' . $recTitle . '</span>'; $ctrl = $this->renderForeignRecordHeaderControl($parentUid, $foreign_table, $rec, $config, $isVirtualRecord); $header = '<table>' . '<tr>' . (!empty($config['appearance']['headerThumbnail']['field']) && $thumbnail ? '<td class="t3-form-field-header-inline-thumbnail" id="' . $objectId . '_thumbnailcontainer">' . $thumbnail . '</td>' : '<td class="t3-form-field-header-inline-icon" id="' . $objectId . '_iconcontainer">' . $iconImg . '</td>') . '<td class="t3-form-field-header-inline-summary">' . $label . '</td>' . '<td clasS="t3-form-field-header-inline-ctrl">' . $ctrl . '</td>' . '</tr>' . '</table>'; return $header; }