Index: t3lib/config_default.php =================================================================== --- t3lib/config_default.php (Revision 157) +++ t3lib/config_default.php (Revision 161) @@ -176,6 +176,7 @@ 'SC_alt_file_navframe::expandCollapse' => 'typo3/alt_file_navframe.php:SC_alt_file_navframe->ajaxExpandCollapse', 't3lib_TCEforms_inline::createNewRecord' => '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/classes/class.t3lib_tceforms_suggest.php:t3lib_TCEforms_suggest->processAjaxRequest', 'ShortcutMenu::getGroups' => 'typo3/classes/class.shortcutmenu.php:ShortcutMenu->getAjaxShortcutGroups', 'ShortcutMenu::saveShortcut' => 'typo3/classes/class.shortcutmenu.php:ShortcutMenu->setAjaxShortcut', 'ShortcutMenu::render' => 'typo3/classes/class.shortcutmenu.php:ShortcutMenu->renderAjax', Index: t3lib/class.t3lib_tceforms.php =================================================================== --- t3lib/class.t3lib_tceforms.php (Revision 157) +++ t3lib/class.t3lib_tceforms.php (Revision 161) @@ -183,6 +183,7 @@ require_once(PATH_t3lib.'class.t3lib_diff.php'); require_once(PATH_t3lib.'class.t3lib_tceforms_inline.php'); +require_once(PATH_t3lib.'classes/class.t3lib_tceforms_suggest.php'); @@ -364,6 +365,11 @@ if (!isset($GLOBALS['ajaxID']) || strpos($GLOBALS['ajaxID'], 't3lib_TCEforms_inline::')!==0) { $this->inline = t3lib_div::makeInstance('t3lib_TCEforms_inline'); } + // Create instance of t3lib_TCEforms_suggest only if this a non-Suggest-AJAX call: + if (!isset($GLOBALS['ajaxID']) || strpos($GLOBALS['ajaxID'], 't3lib_TCEforms_suggest::')!==0) { + $this->suggest = t3lib_div::makeInstance('t3lib_TCEforms_suggest'); + } + // Prepare user defined objects (if any) for hooks which extend this function: $this->hookObjectsMainFields = array(); @@ -398,6 +404,7 @@ $this->titleLen = $BE_USER->uc['titleLen']; // @deprecated $this->inline->init($this); + $this->suggest->init($this); } @@ -2068,6 +2075,17 @@ if (!$disabled && $show_thumbs) { $thumbsnail = implode('
',$imgs); } + + $hideSuggest = $PA['fieldConf']['config']['hideSuggestByDefault']; + if (isset($GLOBALS['BE_USER']->userTS['options.']['suggest.']['hideSuggestByDefault'])) { + $hideSuggest = (bool)$GLOBALS['BE_USER']->userTS['options.']['suggest.']['hideSuggestByDefault']; + } + + // has to be rendered here because when creating the whole form we don't have + // all neccessary information available for calling the function + if ($config['useSuggest']) { + $suggestSelector = $this->suggest->renderSuggestSelector($PA['itemFormElName'], $table, $field, $row, $config, $hideSuggest, $this); + } // Creating the element: $params = array( @@ -2078,7 +2096,10 @@ 'style' => isset($config['selectedListStyle']) ? ' style="'.htmlspecialchars($config['selectedListStyle']).'"' : ' style="'.$this->defaultMultipleSelectorStyle.'"', 'info' => $info, 'thumbnails' => $thumbsnail, - 'readOnly' => $disabled + 'readOnly' => $disabled, + 'hideSuggest' => $hideSuggest, + 'suggestBoxPosition' => $PA['fieldConf']['config']['suggestBoxPosition'], + 'suggestSelector' => $suggestSelector ); $item.= $this->dbFileIcons($PA['itemFormElName'],'db',implode(',',$tempFT),$itemArray,'',$params,$PA['onFocus'],$table,$field,$row['uid']); @@ -3318,6 +3339,18 @@ if (!$selector) { $selector = ''; } + + if ($params['suggestSelector']) { + switch ($params['suggestBoxPosition']) { + case 'right': + $params['thumbnails'] = $params['suggestSelector'].$params['thumbnails']; + break; + + default: + $selector .= $params['suggestSelector']; + break; + } + } $icons = array( @@ -3340,6 +3373,12 @@ 'backPath,'gfx/insert3.gif','width="14" height="14"').' border="0" '.t3lib_BEfunc::titleAltAttrib($this->getLL('l_browse_'.($mode=='file'?'file':'db'))).' />'. ''; } + if ($params['hideSuggest']) { + $aOnClick='new Effect.Appear("suggest-'.$table.'-'.$field.'-'.$uid.'"); new Effect.Fade("suggestlink-'.$table.'-'.$field.'-'.$uid.'");'; + $icons['R'][]=''. + 'backPath,'gfx/group_suggest.gif','width="14" height="14"').' border="0" '.t3lib_BEfunc::titleAltAttrib($this->getLL('l_suggest')).' />'. + ''; + } if (!$params['dontShowMoveIcons']) { if ($sSize>=5) { $icons['L'][]=''. @@ -4946,13 +4985,16 @@ // if IRRE fields were processed, add the JavaScript functions: if ($this->inline->inlineCount) { - $jsFile[] = ''; $jsFile[] = ''; $out .= ' inline.setPrependFormFieldNames("'.$this->inline->prependNaming.'"); inline.setNoTitleString("'.addslashes(t3lib_BEfunc::getNoRecordTitle(true)).'"); '; } + // if Suggest fields were processed, add the JS functions: + if ($this->suggest->suggestCount > 0) { + $jsFile[] = ''; + } // Toggle icons: $toggleIcon_open = 'backPath,'gfx/pil2down.gif','width="12" height="7"').' hspace="2" alt="Open" title="Open" />'; Index: t3lib/js/jsfunc.suggest.js =================================================================== --- t3lib/js/jsfunc.suggest.js (Revision 0) +++ t3lib/js/jsfunc.suggest.js (Revision 161) @@ -0,0 +1,82 @@ +/*************************************************************** +* AJAX selectors for TCEforms +* +* $Id:$ +* +* Copyright notice +* +* (c) 2007 Andreas Wolf +* All rights reserved +* +* This script is part of the TYPO3 project. The TYPO3 project is +* free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* The GNU General Public License can be found at +* http://www.gnu.org/copyleft/gpl.html. +* +* This script is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* This copyright notice MUST APPEAR in all copies of the script! +***************************************************************/ + +/** + * Class for JS handling of suggest fields in TCEforms. + * + * @author Andreas Wolf + */ +var suggest = { + /** + * Wrapper for script.aculo.us' Autocompleter functionality: Assigns a new autocompletion object to + * the input field of a given Suggest selector. + * + * @param string objectId The ID of the object to assign the completer to + * @param string table The table of the record which is currently edited + * @param string field The field which is currently edited + * @param integer uid The uid of the record which is currently edited + * @param integer pid The pid of the record which is currently edited + * @return void + */ + createSuggestField: function(objectId, table, field, uid, pid) { + new Ajax.Autocompleter( + objectId+"Suggest", + objectId+"SuggestChoices", + "ajax.php", + { + paramName: "value", + minChars: 2, + updateElement: suggest.addElementToList, + parameters: 'ajaxID=t3lib_TCEforms_suggest::searchRecord&table='+table+'&field='+field+'&formfield='+objectId+'&uid='+uid+'&pid='+pid + } + ); + }, + + /** + * Adds an element to the list of items in a group selector. + * + * @param object item The item to add to the list (usually an li element) + * @return void + */ + addElementToList: function(item) { + arr = item.id.split('-'); + ins_table = arr[0]; + ins_uid = arr[1]; + rec_table = arr[2]; + rec_uid = arr[3]; + rec_field = arr[4]; + + setFormValueFromBrowseWin('data['+rec_table+']['+rec_uid+']['+rec_field+']',ins_table+'_'+ins_uid, item.firstChild.textContent); + TBE_EDITOR.fieldChanged(rec_table,rec_uid,rec_field,'data['+rec_table+']['+rec_uid+']['+rec_field+']'); + + suggest = document.getElementById('data['+rec_table+']['+rec_uid+']['+rec_field+']Suggest'); + suggest.value = ''; + } +} + + +/*]]>*/ \ Kein Zeilenvorschub am Ende der Datei Index: t3lib/classes/class.t3lib_tceforms_suggest.php =================================================================== --- t3lib/classes/class.t3lib_tceforms_suggest.php (Revision 0) +++ t3lib/classes/class.t3lib_tceforms_suggest.php (Revision 161) @@ -0,0 +1,212 @@ + +* All rights reserved +* +* This script is part of the TYPO3 project. The TYPO3 project is +* free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* The GNU General Public License can be found at +* http://www.gnu.org/copyleft/gpl.html. +* A copy is found in the textfile GPL.txt and important notices to the license +* from the author is found in LICENSE.txt distributed with these scripts. +* +* +* This script is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* This copyright notice MUST APPEAR in all copies of the script! +***************************************************************/ +/** + * AJAX functions for use in TCEforms + * + * $Id:$ + * + * @author Andreas Wolf + */ + +class t3lib_TCEforms_suggest { + public $suggestCount = 0; // count the number of ajax selectors used + + + /** + * Initialize an instance of t3lib_TCEforms_suggest + * + * @param t3lib_TCEforms $tceForms Reference to an TCEforms instance + * @return void + */ + public function init(&$tceForms) { + $this->TCEformsObj =& $tceForms; + $this->backPath =& $tceForms->backPath; + } + + /** + * Renders an ajax-enabled text field. Also adds required JS + * + * @param string $fieldname The fieldname in the form + * @param string $table The table we render this selector for + * @param string $field The field we render this selector for + * @param array $row The row which is currently edited + * @param array $config The TSconfig of the field + * @param boolean $hideSuggest Whether or not to hide the selector by default + * @return string The HTML code for the selector + */ + public function renderSuggestSelector($fieldname, $table, $field, array $row, array $config, $hideSuggest) { + $this->suggestCount++; + + if ($hideSuggest) { + $hide = ' style="display:none;"'; + } + + // TODO: move CSS to stylesheet + $selector = '
'.$this->getLL('find_record').' +
+ '; + + $this->TCEformsObj->additionalJS_post[] = ' + suggest.createSuggestField("'.$fieldname.'", "'.$table.'", "'.$field.'", "'.$row['uid'].'", '.$row['pid'].'); + '; + + return $selector; + } + + /** + * Ajax handler for the "suggest" feature in TCEforms + * + * @param string $search The string to search for in the database + * @param string $table The table which is currently edited + * @param string $field The field which is currently edited + * @param integer $uid The uid of the record which is currently edited (may be NEWxxxxxx) + * @param integer $pid The pid of the record which is currently edited (always numeric + * @param string $formfield The field which is edited + * @return void + */ + public function processAjaxRequest($params, &$ajaxObj) { + global $TCA, $LANG; + + // instantiate the global language object here because in AJAX calls it's not available, + // but we need it. + // @see: typo3/template.php + require_once(PATH_typo3.'sysext/lang/lang.php'); + $LANG = t3lib_div::makeInstance('language'); + $LANG->init($BE_USER->uc['lang']); + + + // get parameters from $_GET/$_POST + $search = t3lib_div::_GP('value'); + $table = t3lib_div::_GP('table'); + $field = t3lib_div::_GP('field'); + $uid = t3lib_div::_GP('uid'); + $pageId = t3lib_div::_GP('pid'); + $formfield = t3lib_div::_GP('formfield'); + + + t3lib_div::loadTCA($table); + + if (is_numeric($uid)) { + // already existing element, so get the TSconfig of the page itself... + if ($table == 'pages') { + $pageId = $uid; + // ... or the page containing the element + } else { + $row = t3lib_BEfunc::getRecord($table, $uid); + $pageId = $row['pid']; + } + } // New element, so use given id of parent page (i.e., don't modify it here) + + $TSconfig = t3lib_BEfunc::getPagesTSconfig($pageId); + + $queryTables = t3lib_div::trimExplode(',', $TCA[$table]['columns'][$field]['config']['allowed']); + + $resultRows = array(); + foreach ($queryTables as $queryTable) { + t3lib_div::loadTCA($queryTable); + + // if the table does not exist, skip it + if (count($TCA[$queryTable]) == 0) continue; + + // merge the configurations of different "levels" to get the working configuration for this table and + // field (i.e., go from the most general to the most special configuration) + $config = is_array($TSconfig['TCEMAIN.']['default.']['suggest.']) ? + $TSconfig['TCEMAIN.']['default.']['suggest.'] : array(); + $config = t3lib_div::array_merge_recursive_overrule($config, + (is_array($TSconfig['TCEMAIN.'][$queryTable.'.']['suggest.']) ? + $TSconfig['TCEMAIN.'][$queryTable.'.']['suggest.'] : array())); + // use $table instead of $queryTable here because we overlay a config for the input-field here, not for + // the queried table + $config = t3lib_div::array_merge_recursive_overrule($config, + (is_array($TSconfig['TCEFORM.'][$table.'.'][$field.'.']['suggest.']) ? + $TSconfig['TCEFORM.'][$table.'.'][$field.'.']['suggest.'] : array())); + $config = t3lib_div::array_merge_recursive_overrule($config, + (is_array($TSconfig['TCEFORM.'][$table.'.'][$field.'.']['suggest.'][$queryTable.'.']) ? + $TSconfig['TCEFORM.'][$table.'.'][$field.'.']['suggest.'][$queryTable.'.'] : array())); + + $class = t3lib_div::makeInstanceClassName($config['suggestClass']); + if (!class_exists($class)) { + $class = 'suggestDefaultSelector'; + } + $obj = new $class($queryTable, $config); + + $params = array('value' => $search); + $rows = $obj->queryTable($params, $this); + + + if (!$rows) { + continue; + } + $resultRows = t3lib_div::array_merge($resultRows, $rows); + unset($rows); + } + + $listItems = array(); + if (count($resultRows) > 0) { + // traverse all found records, ... + foreach ($resultRows as $key => $row) { + $rowsSort[$key] = $row['text']; + } + // ... sort them... + asort($rowsSort); + $rowsSort = array_keys($rowsSort); + + // ... and put together the selector + $returnRows = array(); + for ($i = 0; $i < 10 && $i < count($resultRows); $i++) { + $row = $resultRows[$rowsSort[$i]]; + $returnRows[] = ''.$row['text'].''; + } + } + if (count($returnRows) > 0) { + $list = implode('', $returnRows); + } else { + $list = ''; + } + + // encode the content in utf-8, otherwise it won't be shown correctly in the backend + $ajaxObj->addContent(0, $LANG->csConvObj->utf8_encode('
    '.$list.'
', $LANG->charSet)); + } + + /** + * Returns language label from locallang_core.php + * + * @param string The label key + * @return string The value of the label, fetched for the current backend language. + */ + private function getLL($str) { + return $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.'.$str); + } +} + + +if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['classes/t3lib/class.t3lib_tceforms_suggest.php']) { + include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['classes/t3lib/class.t3lib_tceforms_suggest.php']); +} \ Kein Zeilenvorschub am Ende der Datei Index: typo3/classes/class.suggestDefaultSelector.php =================================================================== --- typo3/classes/class.suggestDefaultSelector.php (Revision 0) +++ typo3/classes/class.suggestDefaultSelector.php (Revision 161) @@ -0,0 +1,449 @@ + +* All rights reserved +* +* This script is part of the TYPO3 project. The TYPO3 project is +* free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* The GNU General Public License can be found at +* http://www.gnu.org/copyleft/gpl.html. +* A copy is found in the textfile GPL.txt and important notices to the license +* from the author is found in LICENSE.txt distributed with these scripts. +* +* +* This script is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* This copyright notice MUST APPEAR in all copies of the script! +***************************************************************/ + +/** + * Demo implementation of a handler class for the ajax record selector. + * + * Normally other implementations should be inherited from this one. queryTable() should not be overwritten under normal + * circumstances. + * + * @author Andreas Wolf + * + */ +class suggestDefaultSelector { + /** + * The name of the table to query + * + * @var string + */ + protected $table = ''; + + /** + * The name of the foreign table to query (records from this table will be used for displaying instead of the ones + * from table) + * + * @var string + */ + protected $mmForeignTable = ''; + + /** + * Holds the configuration for the table we query + * + * @var array + */ + protected $tableConfig = array(); + + /** + * Counter to limit the recursions when querying the table; also needed to choose the range of records to select + * + * @var integer + */ + protected $recursionCounter = 0; + + /** + * The select-clause to use when selecting the records (is manipulated and used by different functions, so it has to + * be a global var) + * + * @var string + */ + protected $selectClause = ''; + + /** + * Configuration for this selector from TSconfig + * + * @var array + */ + protected $config = array(); + + /** + * The CSS class(es) to use for rendering the selector + * + * @var string + */ + protected $cssClasses = ''; + + + + /** + * The constructor of this class + * + * @param string $table + * @param array $config The configuration (TSconfig) to use for this selector + * @return void + */ + public function __construct($table, $config) { + global $TCA; + + $this->table = $table; + + $this->config = $config; + + // Get the configuration for this table + $this->tableConfig = $TCA[$table]; + + if ($config['cssClasses'] != '') { + $this->cssClasses = $config['cssClasses']; + } + + + $depth = intval($config['pidDepth']); + + $pageIds = t3lib_div::trimExplode(',', $config['pid']); + foreach ($pageIds as $pageId) { + if ($pageId > 0) { + $pagesTemp .= $pageId.','; + $pageArr = $this->getAllSubpagesOfPage($pageId, $depth); + + foreach ($pageArr as $pages) { + $pagesTemp .= $pages.','; + } + } + } + $this->pages = array_unique(t3lib_div::trimExplode(',', $pagesTemp, true)); + + + + if ($params['table'] == 'pages') { + $this->addWhere = ' AND '.$this->tceforms->readPerms(); + } + // if table is versionized, only get the records from the Live Workspace - the overlay of WS-records is + // done below + if ($TCA[$params['table']]['ctrl']['versioningWS'] == true) { + $this->addWhere .= ' AND t3ver_wsid=0'; + } + } + + /** + * Queries a table for records and completely processes them + * + * Returns a two-dimensional array of almost finished records; the only need to be put into a
  • -structure + * + * If you subclass this class, you will most likely only want to overwrite the functions called from here, but not + * this function itself + * + * @param array $params + * @param object $ref + * @return array The fetched and processed rows + */ + public function queryTable(&$params, &$ref) { + global $TYPO3_DB; + + $this->params = &$params; + + $this->start = $this->recursionCounter * 50; + + $this->prepareSelectStatement(); + + $rows = array(); + + $result = $this->selectRecords(); + if (!$result) return false; + + while ($row = $TYPO3_DB->sql_fetch_assoc($result)) { + // check if we already have collected 10 records + if (count($rows) > 10) break; + + $this->manipulateRecord($row); + + $this->makeWorkspaceOverlay($row); + + // check if the user has access to the record + if (!$this->checkRecordAccess($row, $row['uid'])) { + continue; + } + + $iconPath = $this->getIcon($row); + + $uid = ($row['t3ver_oid'] > 0) ? $row['t3ver_oid'] : $row['uid']; + + $path = $this->getRecordPath($row, $uid); + + if (strlen($path) > 30) { + $croppedPath = $GLOBALS['LANG']->csConvObj->crop($GLOBALS['LANG']->charSet,$path,10).'...'.$GLOBALS['LANG']->csConvObj->crop($GLOBALS['LANG']->charSet,$path,-20); + } else { + $croppedPath = $path; + } + + + + $label = $this->getLabel($row); + + $entry = array( + 'text' => ''.$label.'('.$uid.')
    '.$croppedPath.'', + 'table' => ($this->mmForeignTable ? $this->mmForeignTable : $this->table), + 'path' => $path, + 'uid' => $uid, + 'icon' => $iconPath, + 'style' => 'background-image:url('.$iconPath.');', + 'class' => $this->cssClasses, + ); + + $entry = $this->renderRecord($row, $entry); + + + $rows[$table.'_'.$uid] = $entry; + } + + // if there are less than ten records, call this function again to get more records + if (count($rows) < 10 && $TYPO3_DB->sql_num_rows($result) >= 50 && $recursionCounter < 10) { + $tmp = self::queryTable($this->params['value'], ++$recursionCounter); + $rows = array_merge($tmp, $rows); + } + + return $rows; + } + + /** + * Prepare the statement for selecting the records which will be returned to the selector. May also return some + * other records (e.g. from a mm-table) which will be used later on to select the real records + * + * @return void + */ + protected function prepareSelectStatement() { + global $TYPO3_DB; + + $searchWholePhrase = $this->config['searchWholePhrase']; + + if (isset($this->pages)) { + $this->selectClause = $this->tableConfig['ctrl']['label'].' LIKE \''.($searchWholePhrase ? '%' : '').$TYPO3_DB->escapeStrForLike($this->params['value'], $this->table).'%\' AND deleted=0'; + } + + $this->selectClause .= $this->getPageIdClause($this->pages) ? ' AND ('.$this->getPageIdClause($this->pages).')' : ''; + + // add the global clauses to the where-statement + $this->selectClause .= $this->addWhere; + } + + /** + * Selects all subpages of one page, optionally only upto a certain level + * + * @param integer $uid + * @param integer $depth + */ + protected function getAllSubpagesOfPage($uid, $depth = 99) { + global $TYPO3_DB; + + $pageIds = array($uid); + $level = 0; + + $pages = array(); + $pages[$level] = $uid; + + // check for + while (($depth - $level) >= 0 && $pageIds != '') { + ++$level; + + $rows = $TYPO3_DB->exec_SELECTgetRows('uid', 'pages', '('.$this->getPageIdClause($pageIds).')', '', '', '', 'uid'); + if (count($rows) > 0) { + $pageIds = array_keys($rows); + $pageIdsString = implode(',', $pageIds); + + $pages[$level] = $pageIdsString; + } else { + break; + } + } + + return $pages; + } + + /** + * Manipulate a record before using it to render the selector; may be used to replace a MM-relation etc. + * + * @param array $row + */ + protected function manipulateRecord(&$row) { + } + + /** + * Select the recrods from the table (uses the statement prepared in $this->selectClause) + * + * @return resource The resource which holds the records + */ + protected function selectRecords() { + global $TYPO3_DB; + + $result = $TYPO3_DB->exec_SELECTquery('*', $this->table, $this->selectClause, '', '', $this->start.', 50'); + + if (!$result) { + $result = false; + } + + return $result; + } + + protected function checkRecordAccess($row, $uid) { + global $BE_USER; + + $retValue = true; + if (($this->mmForeignTable ? $this->mmForeignTable : $this->table) == 'pages') { + $row = t3lib_BEfunc::readPageAccess($uid, $BE_USER->getPagePermsClause(1)); + if (!$row) + $retValue = false; + } else { + $parent = t3lib_BEfunc::readPageAccess($row['pid'], $BE_USER->getPagePermsClause(1)); + if (!is_array($parent)) + $retValue = false; + } + + return $retValue; + } + + /** + * Overlay the given record with its workspace-version, if any + * + * @return void + */ + protected function makeWorkspaceOverlay(&$row) { + global $BE_USER; + + // check for workspace-versions + if ($BE_USER->workspace != 0 && $this->tableConfig['ctrl']['versioningWS'] == true) { + t3lib_BEfunc::workspaceOL(($this->mmForeignTable ? $this->mmForeignTable : $this->table), $row); + } + } + + /** + * Return the icon for a record - just a wrapper for two functions from t3lib_iconWorks + * + * @param array $row The record to get the icon for + * @return string The path to the icon + */ + protected function getIcon($row) { + $icon = t3lib_iconWorks::getIcon(($this->mmForeignTable ? $this->mmForeignTable : $this->table), $row); + $icon = t3lib_iconWorks::skinImg('', $icon, '', 1); + + return $icon; + } + + /** + * Returns the path for a record. Is the whole path for all records except pages - for these the last part is cut + * off, because it contains the pagetitle itself, which would be double information + * + * The path is returned uncut, cutting has to be done by calling function. + * + * @param array $row The row + * @param integer $uid The records uid + * @return string The record-path + */ + protected function getRecordPath(&$row, $uid) { + global $BE_USER; + + if ($this->config['titleSegmentLimit']) { + $titleLimit = $this->config['titleSegmentLimit']; + } else { + $titleLimit = 0; + } + + if (($this->mmForeignTable ? $this->mmForeignTable : $this->table) == 'pages') { + $path = t3lib_BEfunc::getRecordPath($uid, '', $titleLimit); + + // for pages we only want the first (n-1) parts of the path, because the n-th part is the page itself + $path = substr($path, 0, strrpos($path, '/', -2)).'/'; + } else { + $path = t3lib_BEfunc::getRecordPath($row['pid'], '', $titleLimit); + } + + return $path; + } + + /** + * Returns a label for a given record; usually only a wrapper for t3lib_BEfunc::getRecordTitle + * + * @param array $row + * @return The label for the record + */ + protected function getLabel($row) { + $label = t3lib_BEfunc::getRecordTitle(($this->mmForeignTable ? $this->mmForeignTable : $this->table), $row); + if ($label !== '') { + $label = t3lib_div::fixed_lgd_cs($label, 20); + } else { + $label = ''.$this->getLL('l_no_title').''; + } + + return $label; + } + + /** + * Calls a user function for rendering the page. + * + * This user function should manipulate $entry, especially $entry['text'] + * + * @param array $row The row + * @param array $entry The entry to render + * @return array The rendered entry (will be put into a
  • later on + */ + protected function renderRecord($row, $entry) { + // call renderlet if available (normal pages etc. usually don't have one) + $func = $this->config['renderFunc']; + if ($func != '') { + $params = array('table' => $this->table, 'uid' => $row['uid'], 'row' => $row, 'entry' => &$entry); + t3lib_div::callUserFunction($func, $params, $this, ''); + } + + return $entry; + } + + /** + * Returns language label from locallang_core.php + * Labels must be prefixed with either "l_" or "m_". + * The prefix "l_" maps to the prefix "labels." inside locallang_core.php + * The prefix "m_" maps to the prefix "mess." inside locallang_core.php + * + * @param string The label key + * @return string The value of the label, fetched for the current backend language. + */ + function getLL($str) { + $content = ''; + + switch(substr($str,0,2)) { + case 'l_': + $content = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.'.substr($str,2)); + break; + case 'm_': + $content = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:mess.'.substr($str,2)); + break; + } + return $content; + } + + /** + * Returns a string as to use a replacement for IN (...) in an SQL where-clause. Needed for compatibility with + * MSSQL + * + * @param array $pageIds The pages to use for the clause + * @return string + */ + private function getPageIdClause($pageIds) { + $pageArr = array(); + foreach ($pageIds as $pageId) { + $pageArr[] = 'pid='.$pageId; + } + + return implode(' OR ', $pageArr); + } +} Index: typo3/gfx/group_suggest.gif =================================================================== Kann nicht anzeigen: Dateityp ist als binär angegeben. svn:mime-type = application/octet-stream Eigenschaftsänderungen: typo3/gfx/group_suggest.gif ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Index: typo3/stylesheet.css =================================================================== --- typo3/stylesheet.css (Revision 157) +++ typo3/stylesheet.css (Revision 161) @@ -646,6 +646,46 @@ +DIV.suggest_choices { + position:absolute; + width:300px; + background-color:white; + border:1px solid #888; + margin:0px; + padding:0px; +} +DIV.suggest_choices UL { + list-style-type:none; + margin:0px; + padding:0px; +} +DIV.suggest_choices LI.selected { background-color: #ffb !important;} +DIV.suggest_choices LI { + list-style-type:none; + display:block; + margin:0; + padding:2px; + padding-left:24px; + height:32px; + cursor:pointer; + background-color:#EFEFF4; + background-repeat:no-repeat; + background-position:4px center; +} +DIV.suggest_choices LI.pages { + background-color:#FCC; +} +DIV.suggest_choices SPAN.label { + font-weight:bold; +} +DIV.suggest_choices SPAN.uid { + font-size:0.9em; + margin-left:0.3em; +} +DIV.suggest_choices SPAN.path { + font-size:0.9em; + margin-top:0.3em; +}