Index: t3lib/tceforms/class.t3lib_tceforms_suggest_defaultreceiver.php =================================================================== --- t3lib/tceforms/class.t3lib_tceforms_suggest_defaultreceiver.php (Revision 0) +++ t3lib/tceforms/class.t3lib_tceforms_suggest_defaultreceiver.php (Revision 0) @@ -0,0 +1,379 @@ + +* 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! +***************************************************************/ + +/** + * Default implementation of a handler class for an ajax record selector. + * + * Normally other implementations should be inherited from this one. + * queryTable() should not be overwritten under normal + * circumstances. + * + * @author Andreas Wolf + * @author Benjamin Mack + * + */ +class t3lib_tceforms_suggest_defaultreceiver { + /** + * 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 = ''; + + /** + * 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 = ''; + + /** + * Additional WHERE clause to be appended to the SQL + * + * @var string + */ + protected $addWhere = ''; + + /** + * Configuration for this selector from TSconfig + * + * @var array + */ + protected $config = array(); + + /** + * The list of pages that are allowed to perform the search for records on + * + * @var array of PIDs + */ + protected $allowedPages = array(); + + + + /** + * The constructor of this class + * + * @param string $table + * @param array $config The configuration (TCA overlayed with TSconfig) to use for this selector + * @return void + */ + public function __construct($table, $config) { + $this->table = $table; + $this->config = $config; + + // get a list of all the pages that should be looked on + if (isset($config['pidList'])) { + $allowedPages = $pageIds = t3lib_div::trimExplode(',', $config['pidList']); + $depth = intval($config['pidDepth']); + foreach ($pageIds as $pageId) { + if ($pageId > 0) { + $allowedPages += $this->getAllSubpagesOfPage($pageId, $depth); + } + } + $this->allowedPages = array_unique($allowedPages); + } + + + if ($this->table == 'pages') { + $this->addWhere = ' AND ' . $GLOBALS['BE_USER']->getPagePermsClause(1); + } + + // if table is versionized, only get the records from the Live Workspace + // the overlay itself of WS-records is done below + if ($GLOBALS['TCA'][$this->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 the parent object + * @return array The fetched and processed rows + */ + public function queryTable(&$params, &$ref) { + $rows = array(); + + $this->params = &$params; + $this->start = $this->recursionCounter * 50; + + $this->prepareSelectStatement(); + $result = $this->selectRecords(); + if ($result) { + while ($row = $GLOBALS['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']); + + $croppedPath = $path = $this->getRecordPath($row, $uid); + if (strlen($croppedPath) > 30) { + $croppedPath = $GLOBALS['LANG']->csConvObj->crop($GLOBALS['LANG']->charSet, $path, 10) . '...' . $GLOBALS['LANG']->csConvObj->crop($GLOBALS['LANG']->charSet, $path, -20); + } + + $label = $this->getLabel($row); + $entry = array( + 'text' => '' . $label . '(' . $uid . ')
    ' . $croppedPath . '', + 'table' => ($this->mmForeignTable ? $this->mmForeignTable : $this->table), + 'label' => $label, + 'path' => $path, + 'uid' => $uid, + 'icon' => $iconPath, + 'style' => 'background-image:url(' . $iconPath . ');', + 'class' => (isset($this->config['cssClass']) ? $this->config['cssClass'] : ''), + ); + + $rows[$table . '_' . $uid] = $this->renderRecord($row, $entry); + } + + // if there are less than ten records, call this function again to get more records + if (count($rows) < 10 && $GLOBALS['TYPO3_DB']->sql_num_rows($result) >= 50 && $recursionCounter < 10) { + $tmp = self::queryTable($this->params['value'], ++$recursionCounter); + $rows = array_merge($tmp, $rows); + } + return $rows; + } else { + return false; + } + } + + /** + * 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() { + $searchWholePhrase = $this->config['searchWholePhrase']; + + $searchString = $this->params['value']; + $searchUid = intval($searchString); + if (strlen($searchString)) { + $this->selectClause = $GLOBALS['TCA'][$this->table]['ctrl']['label'] . ' LIKE \'' . ($searchWholePhrase ? '%' : '') . $GLOBALS['TYPO3_DB']->escapeStrForLike($searchString, $this->table).'%\''; + if ($searchUid > 0 && $searchUid == $searchString) { + $this->selectClause = '(' . $this->selectClause . ' OR uid = ' . $searchUid . ')'; + } + } + $this->selectClause .= ' AND deleted = 0'; + + if (count($this->allowedPages)) { + $pidList = $GLOBALS['TYPO3_DB']->cleanIntArray($this->allowedPages); + if (count($pidList)) { + $this->selectClause .= ' AND pid IN (' . implode(', ', $pidList) . ') '; + } + } + + // add an additional search condition comment + if (isset($this->config['searchCondition']) && strlen($this->config['searchCondition']) > 0) { + $this->selectClause .= ' AND ' . $this->config['searchCondition']; + } + + // 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) { + $pageIds = array($uid); + $level = 0; + + $pages = array(); + $pages[$level] = $uid; + + // fetch all + while (($depth - $level) > 0 && $pageIds != '') { + ++$level; + + $pidList = $GLOBALS['TYPO3_DB']->cleanIntArray($pageIds); + $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid', 'pages', 'pid IN (' . implode(', ', $pidList) . ')', '', '', '', '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 SQL resource which holds the records or FALSE if there was an error + */ + protected function selectRecords() { + $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $this->table, $this->selectClause, '', '', $this->start . ', 50'); + return ($result ? $result : false); + } + + /** + * Selects whether the logged in Backend User is allowed to read a specific record + */ + protected function checkRecordAccess($row, $uid) { + $retValue = true; + if (($this->mmForeignTable ? $this->mmForeignTable : $this->table) == 'pages') { + if (!t3lib_BEfunc::readPageAccess($uid, $GLOBALS['BE_USER']->getPagePermsClause(1))) { + $retValue = false; + } + } else { + if (!is_array(t3lib_BEfunc::readPageAccess($row['pid'], $GLOBALS['BE_USER']->getPagePermsClause(1)))) { + $retValue = false; + } + } + return $retValue; + } + + /** + * Overlay the given record with its workspace-version, if any + * + * @param array the record to get the workspace version for + * @return void (passed by reference) + */ + protected function makeWorkspaceOverlay(&$row) { + // check for workspace-versions + if ($GLOBALS['BE_USER']->workspace != 0 && $GLOBALS['TCA'][$this->table]['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); + return t3lib_iconWorks::skinImg('', $icon, '', 1); + } + + /** + * 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) { + $titleLimit = max($this->config['maxPathTitleLength'], 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) { + return t3lib_BEfunc::getRecordTitle(($this->mmForeignTable ? $this->mmForeignTable : $this->table), $row, true); + } + + /** + * 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) + if ($this->config['renderFunc'] != '') { + $params = array( + 'table' => $this->table, + 'uid' => $row['uid'], + 'row' => $row, + 'entry' => &$entry + ); + t3lib_div::callUserFunction($this->config['renderFunc'], $params, $this, ''); + } + + return $entry; + } +} Eigenschaftsänderungen: t3lib/tceforms/class.t3lib_tceforms_suggest_defaultreceiver.php ___________________________________________________________________ HinzugefĂĽgt: svn:mergeinfo Index: t3lib/tceforms/class.t3lib_tceforms_suggest.php =================================================================== --- t3lib/tceforms/class.t3lib_tceforms_suggest.php (Revision 0) +++ t3lib/tceforms/class.t3lib_tceforms_suggest.php (Revision 0) @@ -0,0 +1,218 @@ + +* 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 + * @author Benjamin Mack + */ + +class t3lib_TCEforms_suggest { + // count the number of ajax selectors used + public $suggestCount = 0; + public $cssClass = 'typo3-TCEforms-suggest'; + + + /** + * 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 $hideByDefault 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, $hideByDefault) { + $this->suggestCount++; + + $position = $config['fieldTSConfig']['suggest.']['position']; + if (!$position) { + $position = 'right'; + } + + $containerCssClass = $this->cssClass . ' ' . $this->cssClass . '-position-' . $position; + $suggestId = 'suggest-' . $table . '-' . $field . '-' . $row['uid']; + + $selector = ' +
    + + +
    '; + + // replace "-" with ucwords for the JS object name + $jsObj = str_replace(' ', '', ucwords(str_replace('-', ' ', t3lib_div::strtolower($suggestId)))); + $this->TCEformsObj->additionalJS_post[] = ' + var ' . $jsObj . ' = new TCEForms.Suggest("' . $fieldname . '", "' . $table . '", "' . $field . '", "' . $row['uid'] . '", ' . $row['pid'] . ', ' . (intval($config['fieldTSConfig']['suggest.']['minimumCharacters']) > 0 ? intval($config['fieldTSConfig']['suggest.']['minimumCharacters']) : 2) . '); + ' . $jsObj . '.defaultValue = "' . t3lib_div::slashJS($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:labels.findRecord')) . '"; + '; + + return $selector; + } + + /** + * Ajax handler for the "suggest" feature in TCEforms + * compiles together the different results from + * + * @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) { + + // 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 the $uid is already existing element, so get the TSconfig of the page itself... + // otherwise it's a new element, so use given id of parent page (i.e., don't modify it here) + if (is_numeric($uid)) { + if ($table == 'pages') { + $pageId = $uid; + // ... or the page containing the element + } else { + $row = t3lib_BEfunc::getRecord($table, $uid); + $pageId = $row['pid']; + } + } + + $TSconfig = t3lib_BEfunc::getPagesTSconfig($pageId); + $wizardConfig = $GLOBALS['TCA'][$table]['columns'][$field]['config']['wizards']['suggest']['config']; + $queryTables = t3lib_div::trimExplode(',', $GLOBALS['TCA'][$table]['columns'][$field]['config']['allowed']); + $resultRows = array(); + + // fetch the records for each query table. A query table is a table which reacords are allowed to + // be added to the TCEForm selector, originally fetched from the "allowed" config option in the TCA + foreach ($queryTables as $queryTable) { + t3lib_div::loadTCA($queryTable); + + // if the table does not exist, skip it + if (!is_array($GLOBALS['TCA'][$queryTable]) || !count($GLOBALS['TCA'][$queryTable])) { + continue; + } + + $config = (array)$wizardConfig['default']; + if (is_array($wizardConfig[$queryTable])) { + $config = t3lib_div::array_merge_recursive_overrule($config, $wizardConfig[$queryTable]); + } + + // 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) + if (is_array($TSconfig['TCEMAIN.']['default.']['suggest.'])) { + $config = t3lib_div::array_merge_recursive_overrule($config, $TSconfig['TCEMAIN.']['default.']['suggest.']); + } + if (is_array($TSconfig['TCEMAIN.'][$queryTable.'.']['suggest.'])) { + $config = t3lib_div::array_merge_recursive_overrule($config, $TSconfig['TCEMAIN.'][$queryTable.'.']['suggest.']); + } + + // use $table instead of $queryTable here because we overlay a config + // for the input-field here, not for the queried table + if (is_array($TSconfig['TCEFORM.'][$table.'.'][$field.'.']['suggest.']['default.'])) { + $config = t3lib_div::array_merge_recursive_overrule($config, $TSconfig['TCEFORM.'][$table.'.'][$field.'.']['suggest.']['default.']); + } + if (is_array($TSconfig['TCEFORM.'][$table.'.'][$field.'.']['suggest.'][$queryTable.'.'])) { + $config = t3lib_div::array_merge_recursive_overrule($config, $TSconfig['TCEFORM.'][$table.'.'][$field.'.']['suggest.'][$queryTable.'.']); + } + + // instantiate the class that should fetch the records for this $queryTable + $receiverClassName = $config['receiverClass']; + if (!class_exists($receiverClassName)) { + $receiverClassName = 't3lib_tceforms_suggest_defaultreceiver'; + } + $receiverObj = t3lib_div::makeInstance($receiverClassName, $queryTable, $config); + + $params = array('value' => $search); + $rows = $receiverObj->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 and sort them + $rowsSort = array(); + foreach ($resultRows as $key => $row) { + $rowsSort[$key] = $row['text']; + } + asort($rowsSort); + $rowsSort = array_keys($rowsSort); + + // maximum of 10 items in the list + $maxItems = min(count($resultRows), 10); + + // put together the selector entry + for ($i = 0; $i < $maxItems; $i++) { + $row = $resultRows[$rowsSort[$i]]; + $rowId = $row['table'] . '-' . $row['uid'] . '-' . $table . '-' . $uid . '-' . $field; + $listItems[] = '' . $row['text'] . '
  • '; + } + } + + if (count($listItems) > 0) { + $list = implode('', $listItems); + } else { + $list = '
  • ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:labels.noRecordFound') . '
  • '; + } + + $list = ''; + $ajaxObj->addContent(0, $list); + } +} + + +if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['classes/t3lib/tceforms/class.t3lib_tceforms_suggest.php']) { + include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['classes/t3lib/tceforms/class.t3lib_tceforms_suggest.php']); +} Index: t3lib/config_default.php =================================================================== --- t3lib/config_default.php (Revision 5524) +++ t3lib/config_default.php (Arbeitskopie) @@ -244,6 +244,7 @@ 't3lib_TCEforms_inline::createNewRecord' => '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', '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 5524) +++ t3lib/class.t3lib_tceforms.php (Arbeitskopie) @@ -171,18 +171,6 @@ - - - - - - - - - - - - /** * 'TCEforms' - Class for creating the backend editing forms. * @@ -361,6 +349,10 @@ 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(); @@ -395,6 +387,7 @@ $this->titleLen = $BE_USER->uc['titleLen']; // @deprecated since TYPO3 4.1 $this->inline->init($this); + $this->suggest->init($this); } @@ -3806,6 +3799,13 @@ $sOnChange = $assignValue.';this.blur();this.selectedIndex=0;'.implode('',$fieldChangeFunc); $outArr[] = ''; break; + case 'suggest': + if (isset($PA['fieldTSConfig']['wizards.']['suggest.']['hide']) && ((bool)$PA['fieldTSConfig']['wizards.']['suggest.']['hide'] == TRUE)) { + break; + } + + $outArr[] = $this->suggest->renderSuggestSelector($PA['itemFormElName'], $table, $field, $row, $PA, $this); + break; } // Color wizard colorbox: @@ -5141,6 +5141,12 @@ '; } + // if Suggest fields were processed, add the JS functions + if ($this->suggest->suggestCount > 0) { + $GLOBALS['SOBE']->doc->loadScriptaculous(); + $this->loadJavascriptLib('../t3lib/js/jsfunc.tceforms_suggest.js'); + } + // Toggle icons: $toggleIcon_open = 'backPath,'gfx/pil2down.gif','width="12" height="7"').' hspace="2" alt="Open" title="Open" />'; $toggleIcon_close = 'backPath,'gfx/pil2right.gif','width="7" height="12"').' hspace="2" alt="Close" title="Close" />'; Index: t3lib/js/jsfunc.tceforms_suggest.js =================================================================== --- t3lib/js/jsfunc.tceforms_suggest.js (Revision 0) +++ t3lib/js/jsfunc.tceforms_suggest.js (Revision 0) @@ -0,0 +1,103 @@ +/*************************************************************** +* 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 + */ +if (!TCEForms) { + var TCEForms = {}; +} + +TCEForms.Suggest = Class.create({ + objectId: '', + suggestField: '', + suggestResultList: '', + minimumCharacters: 2, + defaultValue: '', + + /** + * 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 + * @param integer minimumCharacters the minimum characaters that is need to trigger the initial search + */ + initialize: function(objectId, table, field, uid, pid, minimumCharacters) { + this.objectId = objectId; + this.suggestField = objectId + 'Suggest'; + this.suggestResultList = objectId + 'SuggestChoices'; + + new Ajax.Autocompleter(this.suggestField, this.suggestResultList, top.TS.PATH_typo3 + 'ajax.php', { + paramName: 'value', + minChars: (minimumCharacters ? minimumCharacters : this.minimumCharacters), + updateElement: this.addElementToList.bind(this), + parameters: 'ajaxID=t3lib_TCEforms_suggest::searchRecord&table=' + table + '&field=' + field + '&formfield=' + objectId + '&uid=' + uid + '&pid=' + pid + } + ); + + $(this.suggestField).observe('focus', this.checkDefaultValue.bind(this)); + $(this.suggestField).observe('keydown', this.checkDefaultValue.bind(this)); + }, + + /** + * check for default value of the input field and set it to empty once somebody wants to type something in + */ + checkDefaultValue: function() { + if ($(this.suggestField).value == this.defaultValue) { + $(this.suggestField).value = ''; + } + }, + + /** + * 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) { + if (item.className.indexOf('noresults') == -1) { + var arr = item.id.split('-'); + ins_table = arr[0]; + ins_uid = arr[1]; + rec_table = arr[2]; + rec_uid = arr[3]; + rec_field = arr[4]; + + var formEl = 'data[' + rec_table + '][' + rec_uid + '][' + rec_field + ']'; + setFormValueFromBrowseWin(formEl, ins_table + '_' + ins_uid, item.firstChild.textContent); + TBE_EDITOR.fieldChanged(rec_table, rec_uid, rec_field, formEl); + + $(this.suggestField).value = this.defaultValue; + } + } +}); \ No newline at end of file Index: t3lib/core_autoload.php =================================================================== --- t3lib/core_autoload.php (Revision 5524) +++ t3lib/core_autoload.php (Arbeitskopie) @@ -60,6 +60,8 @@ 't3lib_tceforms' => PATH_t3lib . 'class.t3lib_tceforms.php', 't3lib_tceforms_fe' => PATH_t3lib . 'class.t3lib_tceforms_fe.php', 't3lib_tceforms_inline' => PATH_t3lib . 'class.t3lib_tceforms_inline.php', + 't3lib_tceforms_suggest' => PATH_t3lib . 'tceforms/class.t3lib_tceforms_suggest.php', + 't3lib_tceforms_suggest_defaultreceiver' => PATH_t3lib . 'tceforms/class.t3lib_tceforms_suggest_defaultreceiver.php', 't3lib_tcemain' => PATH_t3lib . 'class.t3lib_tcemain.php', 't3lib_timetrack' => PATH_t3lib . 'class.t3lib_timetrack.php', 't3lib_transferdata' => PATH_t3lib . 'class.t3lib_transferdata.php', Index: typo3/stylesheet.css =================================================================== --- typo3/stylesheet.css (Revision 5524) +++ typo3/stylesheet.css (Arbeitskopie) @@ -1072,7 +1072,66 @@ margin-top: 10px; } +div.typo3-TCEforms-suggest-position-right { + margin-left: 10px; + margin-top: 5px; +} +div.typo3-TCEforms-suggest label { + margin-right: 5px; +} + +input.typo3-TCEforms-suggest-search { + width: 200px; + background-image: url(gfx/zoom.gif); + background-position: 2px center; + background-repeat: no-repeat; + padding-left: 16px; +} + +div.typo3-TCEforms-suggest-choices { + position: absolute; + width: 250px; + background-color: white; + border: 1px solid #888; +} +div.typo3-TCEforms-suggest-choices UL { + list-style-type:none; + margin: 0; + padding: 0; +} +div.typo3-TCEforms-suggest-choices LI.selected { background-color: #ffb !important;} +div.typo3-TCEforms-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.typo3-TCEforms-suggest-choices LI.suggest-noresults { + height: auto; +} +div.typo3-TCEforms-suggest-choices LI.pages { + background-color:#FCC; +} +div.typo3-TCEforms-suggest-choices SPAN.suggest-label { + font-weight:bold; +} +div.typo3-TCEforms-suggest-choices SPAN.suggest-uid { + font-size:0.9em; + margin-left:0.3em; +} +div.typo3-TCEforms-suggest-choices SPAN.suggest-path { + font-size:0.9em; + margin-top:0.3em; +} + + /* - - - - - - - - - - - - - - - - - - - - - TCEforms Inline-Relational-Record-Editing @@ -2810,13 +2869,3 @@ border: 1px dotted #666; } */ - - - - - - - - - - Index: typo3/sysext/t3skin/stylesheets/typo3-TCEforms.css =================================================================== --- typo3/sysext/t3skin/stylesheets/typo3-TCEforms.css (Revision 5524) +++ typo3/sysext/t3skin/stylesheets/typo3-TCEforms.css (Arbeitskopie) @@ -211,3 +211,12 @@ .typo3-TCEforms-palette SELECT.select { margin-top: 2px; } + +input.typo3-TCEforms-suggest-search { + width: 200px; + background-image: url(../icons/gfx/zoom.gif); + background-position: 2px center; + background-repeat: no-repeat; + padding-left: 20px; + vertical-align: middle; +} Index: typo3/sysext/lang/locallang_core.xml =================================================================== --- typo3/sysext/lang/locallang_core.xml (Revision 5524) +++ typo3/sysext/lang/locallang_core.xml (Arbeitskopie) @@ -101,6 +101,8 @@ + +