Project

General

Profile

Feature #24092 » 16432_v2.diff

Administrator Admin, 2010-11-17 16:18

View differences:

t3lib/config_default.php (working copy)
)
),
'ExtDirect' => array( // array of key value pairs (provider -> location:className) that holds the classes for the ExtDirect functionality
'TYPO3.CSH.ExtDirect' => 't3lib/extjs/dataprovider/class.extdirect_dataprovider_contexthelp.php:extDirect_DataProvider_ContextHelp'
'TYPO3.CSH.ExtDirect' => 't3lib/extjs/dataprovider/class.extdirect_dataprovider_contexthelp.php:extDirect_DataProvider_ContextHelp',
'TYPO3.LiveSearchActions.ExtDirect' => 't3lib/extjs/dataprovider/class.extdirect_dataprovider_backendlivesearch.php:extDirect_DataProvider_BackendLiveSearch'
),
),
'EXTCONF' => array( // Here you may add manually set configuration options for your extensions. Eg. $TYPO3_CONF_VARS['EXTCONF']['my_extension_key']['my_option'] = 'my_value';
t3lib/search/class.t3lib_search_livesearch.php (revision 0)
<?php
/***************************************************************
* Copyright notice
*
* (c) 2009-2010 Michael Klapper <michael.klapper@aoemedia.de>
* (c) 2010 Jeff Segars <jeff@webempoweredchurch.org>
* 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!
***************************************************************/
/**
* Class for handling backend live search.
*
* @author Michael Klapper <michael.klapper@aoemedia.de>
* @author Jeff Segars <jeff@webempoweredchurch.org>
* @package TYPO3
* @subpackage t3lib
*/
class t3lib_search_livesearch {
/**
* @var string
*/
const PAGE_JUMP_TABLE = 'pages';
/**
* @var integer
*/
const RECURSIVE_PAGE_LEVEL = 99;
/**
* @var integer
*/
const GROUP_TITLE_MAX_LENGTH = 15;
/**
* @var integer
*/
const RECORD_TITLE_MAX_LENGTH = 37;
/**
* @var string
*/
private $queryString = '';
/**
* @var integer
*/
private $startCount = 0;
/**
* @var integer
*/
private $limitCount = 5;
/**
* @var string
*/
protected $userPermissions = '';
/**
* @var t3lib_search_livesearch_queryParser
*/
protected $queryParser = null;
/**
* Initialize access settings.
*
* @return void
*/
public function __construct() {
$this->userPermissions = $GLOBALS['BE_USER']->getPagePermsClause(1);
$this->queryParser = t3lib_div::makeInstance('t3lib_search_livesearch_queryParser');
}
/**
* Find records from database based on the given $searchQuery.
*
* @param string $searchQuery
* @return string Edit link to an page record if exists. Otherwise an empty string will returned
*/
public function findPage($searchQuery) {
$link = '';
$pageId = $this->queryParser->getId($searchQuery);
$pageRecord = $this->findPageById($pageId);
if (!empty($pageRecord)) {
$link = $this->getEditLink(self::PAGE_JUMP_TABLE, $this->findPageById($pageId));
}
return $link;
}
/**
* Find records from database based on the given $searchQuery.
*
* @param string $searchQuery
* @return array Result list of database search.
*/
public function find($searchQuery) {
$recordArray = array();
$pageIdList = $this->getAvailablePageIds (
implode(',', $GLOBALS['BE_USER']->returnWebmounts()),
self::RECURSIVE_PAGE_LEVEL
);
$limit = $this->startCount . ',' . $this->limitCount;
if ($this->queryParser->isValidCommand($searchQuery)) {
$this->setQueryString($this->queryParser->getSearchQueryValue($searchQuery));
$tableName = $this->queryParser->getTableNameFromCommand($searchQuery);
try {
$recordArray[] = $this->findByTable($tableName, $pageIdList, $limit);
} catch (Exception $e) {
// @todo Can we at least log this exception somewhere?
}
} else {
$this->setQueryString($searchQuery);
$recordArray = $this->findByGlobalTableList($pageIdList, $limit);
}
// @todo Need to make sure we don't return too many records.
$recordArray = array_slice($recordArray, 0, 4);
return $recordArray;
}
/**
* Retrieve the page record from given $id.
*
* @param integer $id
* @return array
*/
protected function findPageById($id) {
$pageRecord = array();
$row = t3lib_BEfunc::getRecord(self::PAGE_JUMP_TABLE, $id);
if (is_array($row)) {
$pageRecord = $row;
}
return $pageRecord;
}
/**
* Find records from all registered TCA table & column values.
*
* @param string $pageIdList Comma seperated list of page IDs
* @param string $limit MySql Limit notation
* @return array Records found in the database matching the searchQuery
*/
protected function findByGlobalTableList($pageIdList, $limit) {
$getRecordArray = array();
foreach ($GLOBALS['TCA'] as $tableName => $value) {
try {
$getRecordArray[] = $this->findByTable($tableName, $pageIdList, $limit);
} catch (Exception $e) {
// nothing found for table
// @todo Need to at least log the exception or something.
}
}
return $getRecordArray;
}
/**
* Find records by given table name.
*
* @param string $tableName Database table name
* @param string $pageIdList Comma seperated list of page IDs
* @param string $limit MySql Limit notation
* @return array Records found in the database matching the searchQuery
*
* @see getRecordArray()
* @see makeOrderByTable()
* @see makeQuerySearchByTable()
* @see extractSearchableFieldsFromTable()
*/
protected function findByTable($tableName, $pageIdList, $limit) {
$getRecordArray = array();
$fieldsToSearchWithin = $this->extractSearchableFieldsFromTable($tableName);
$pageBasedPermission = ($tableName == 'pages' && $this->userPermissions) ? $this->userPermissions : '1=1 ' ;
$where = 'pid IN(' . $pageIdList . ')' . $pageBasedPermission . $this->makeQuerySearchByTable($tableName, $fieldsToSearchWithin);
$orderBy = $this->makeOrderByTable($tableName);
try {
$getRecordArray = $this->getRecordArray(
$tableName,
$pageBasedPermission . $this->makeQuerySearchByTable($tableName, $fieldsToSearchWithin),
$this->makeOrderByTable($tableName),
$limit
);
} catch (Exception $e) {
}
return $getRecordArray;
}
/**
* Proccess the Database operation to get the search result.
*
* @param string $tableName Database table name
* @param string $where
* @param string $orderBy
* @param string $limit MySql Limit notation
* @return array
*
* @see t3lib_db::exec_SELECT_queryArray()
* @see t3lib_db::sql_num_rows()
* @see t3lib_db::sql_fetch_assoc()
* @see t3lib_iconWorks::getSpriteIconForRecord()
* @see getTitleFromCurrentRow()
* @see getEditLink()
*/
protected function getRecordArray($tableName, $where, $orderBy, $limit) {
$collect = array();
$isFirst = true;
$queryParts = array(
'SELECT' => '*',
'FROM' => $tableName,
'WHERE' => $where,
'ORDERBY' => $orderBy,
'LIMIT' => $limit
);
$result = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts);
$dbCount = $GLOBALS['TYPO3_DB']->sql_num_rows($result);
if ($dbCount == 0) {
// @todo Should we be throwing an exception here?
// throw new Exception('Nothing found for table: '. $tableName);
}
while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
$collect[] = array (
'id' => $tableName . ':' . $row['uid'],
'recordTitle' => ($isFirst) ? $this->getRecordTitlePrep($this->getTitleOfCurrentRecordType($tableName), self::GROUP_TITLE_MAX_LENGTH) : '',
'iconHTML' => t3lib_iconWorks::getSpriteIconForRecord($tableName, $row),
'title' => $this->getRecordTitlePrep($this->getTitleFromCurrentRow($tableName, $row), self::RECORD_TITLE_MAX_LENGTH),
'editLink' => $this->getEditLink($tableName, $row),
);
$isFirst = false;
}
return $collect;
}
/**
* Build a backend edit link based on given record.
*
* @param string $tableName Record table name
* @param array $row Current record row from database.
* @return string Link to open an edit window for record.
*
* @see t3lib_BEfunc::readPageAccess()
*/
protected function getEditLink($tableName, $row) {
$pageInfo = t3lib_BEfunc::readPageAccess($row['pid'], $this->userPermissions);
$calcPerms = $GLOBALS['BE_USER']->calcPerms($pageInfo);
$editLink = '';
if ($tableName == 'pages') {
$localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages',$row['uid']));
$permsEdit = $localCalcPerms&2;
} else {
$permsEdit = $calcPerms&16;
}
// "Edit" link: ( Only if permissions to edit the page-record of the content of the parent page ($this->id)
// @todo Is there an existing function to generate this link?
if ($permsEdit) {
$editLink = 'alt_doc.php?' . '&edit['.$tableName.']['.$row['uid'].']=edit';
}
return $editLink;
}
/**
* Retrieve the record name
*
* @param string $tableName Record table name
* @return string
*/
protected function getTitleOfCurrentRecordType($tableName) {
return $GLOBALS['LANG']->sL($GLOBALS['TCA'][$tableName]['ctrl']['title']);
}
/**
* Crops a title string to a limited lenght and if it really was cropped, wrap it in a <span title="...">|</span>,
* which offers a tooltip with the original title when moving mouse over it.
*
* @param string $title: The title string to be cropped
* @param integer $titleLength: Crop title after this length - if not set, BE_USER->uc['titleLen'] is used
* @return string The processed title string, wrapped in <span title="...">|</span> if cropped
*/
public function getRecordTitlePrep($title, $titleLength = 0) {
// If $titleLength is not a valid positive integer, use BE_USER->uc['titleLen']:
if (!$titleLength || !t3lib_div::testInt($titleLength) || $titleLength < 0) {
$titleLength = $GLOBALS['BE_USER']->uc['titleLen'];
}
return htmlspecialchars(t3lib_div::fixed_lgd_cs($title, $titleLength));;
}
/**
* Retrieve the column name which contains the title value
*
* @param string $tableName Record table name
* @param array $row Current record row from database.
* @return string
*
* @todo Use the backend function to get the calculated label instead.
*/
protected function getTitleFromCurrentRow($tableName, $row) {
$titleColumnName = $GLOBALS['TCA'][$tableName]['ctrl']['label'];
return $row[$titleColumnName];
}
/**
* Build the MySql where clause by table.
*
* @param string $tableName Record table name
* @param array $fieldsToSearchWithin User right based visible fields where we can search within.
* @return string
*/
protected function makeQuerySearchByTable($tableName, $fieldsToSearchWithin) {
// free text search
$queryLikeStatement = ' LIKE \'%' . $this->getQueryString() . '%\'';
$queryPart = ' AND (' . implode($queryLikeStatement . ' OR ', $fieldsToSearchWithin) . $queryLikeStatement . ')';
$queryPart .= t3lib_BEfunc::deleteClause($tableName);
$queryPart .= t3lib_BEfunc::versioningPlaceholderClause($tableName);
return $queryPart;
}
/**
* Build the MySql ORDER BY statement.
*
*
* @param string $tableName Record table name
* @return string
* @see t3lib_db::stripOrderBy()
*/
protected function makeOrderByTable($tableName) {
$orderBy = '';
if (is_array($GLOBALS['TCA'][$tableName]['ctrl']) && array_key_exists('sortby', $GLOBALS['TCA'][$tableName]['ctrl'])) {
$orderBy = 'ORDER BY '.$GLOBALS['TCA'][$tableName]['ctrl']['sortby'];
} else {
$orderBy = $GLOBALS['TCA'][$tableName]['ctrl']['default_sortby'];
}
return $GLOBALS['TYPO3_DB']->stripOrderBy($orderBy);
}
/**
* Get all fields from given table where we can search for.
*
* @param string $tableName
* @return array
*/
protected function extractSearchableFieldsFromTable($tableName) {
$fieldListArray = array();
// Traverse configured columns and add them to field array, if available for user.
foreach((array) $GLOBALS['TCA'][$tableName]['columns'] as $fieldName => $fieldValue) {
// @todo Reformat
if (
(!$fieldValue['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields', $tableName . ':' . $fieldName)) // does current user have access to the field
&&
($fieldValue['config']['type'] != 'passthrough') // field type is not searchable
&&
(!preg_match('/date|time|int/', $fieldValue['config']['eval'])) // field can't be of type date, time, int
&&
(
($fieldValue['config']['type'] == 'text')
||
($fieldValue['config']['type'] == 'input')
)
) {
$fieldListArray[] = $fieldName;
}
}
// Add special fields:
if ($GLOBALS['BE_USER']->isAdmin()) {
$fieldListArray[] = 'uid';
$fieldListArray[] = 'pid';
}
return $fieldListArray;
}
/**
* Safely retrieve the queryString.
*
* @return string
* @see t3lib_db::quoteStr()
*/
public function getQueryString() {
return $GLOBALS['TYPO3_DB']->quoteStr($this->queryString, '');
}
/**
* Setter for limit value.
*
* @param integer $limitCount
* @return void
*/
public function setLimitCount($limitCount) {
$limit = t3lib_div::intval_positive($limitCount);
if ($limit > 0) {
$this->limitCount = $limit;
}
}
/**
* Setter for start count value.
*
* @param integer $startCount
* @return void
*/
public function setStartCount($startCount) {
$this->startCount = t3lib_div::intval_positive($startCount);
}
/**
* Setter for the search query string.
*
* @param string $queryString
* @return void
* @see t3lib_div::removeXSS()
*/
public function setQueryString($queryString) {
$this->queryString = t3lib_div::removeXSS($queryString);
}
/**
* Creates an instance of t3lib_pageTree which will select a page tree to
* $depth and return the object. In that object we will find the ids of the tree.
*
* @param integer Page id.
* @param integer Depth to go down.
*
* @return string coma separated list of uids
*/
protected function getAvailablePageIds($id, $depth) {
$idList = '';
$tree = t3lib_div::makeInstance('t3lib_pageTree');
$tree->init('AND ' . $this->userPermissions);
$tree->makeHTML = 0;
$tree->fieldArray = Array('uid','php_tree_stop');
if ($depth) {
$tree->getTree($id, $depth, '');
}
$tree->ids[] = $id;
$idList = implode(',', $tree->ids);
return $idList;
}
}
?>
t3lib/search/class.t3lib_search_livesearch_queryParser.php (revision 0)
<?php
/***************************************************************
* Copyright notice
*
* (c) 2009-2010 Michael Klapper <michael.klapper@aoemedia.de>
* (c) 2010 Jeff Segars <jeff@webempoweredchurch.org>
* 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!
***************************************************************/
/**
* Class for parsing query parameters in backend live search.
*
* @author Michael Klapper <michael.klapper@aoemedia.de>
* @author Jeff Segars <jeff@webempoweredchurch.org>
* @package TYPO3
* @subpackage t3lib
*/
class t3lib_search_livesearch_queryParser {
/**
* @var string
*/
protected $commandKey = '';
/**
* @var string
*/
protected $tableName = '';
/**
* @var string
*/
const COMMAND_KEY_INDICATOR = '#';
/**
* @var string
*/
const COMMAND_SPLIT_INDICATOR = ':';
/**
* Retrive the validated command key
*
* @return string Command name
*/
protected function extractKeyFromQuery($query) {
$keyAndValue = substr($query, 1);
$key = explode(':', $keyAndValue);
$this->commandKey = $key[0];
}
/**
* Extract the search value from the full search query which contains also the command part.
*
* @param string $query For example #news:weather
* @return string The extracted search value
*/
public function getSearchQueryValue($query) {
$this->extractKeyFromQuery($query);
return str_replace(self::COMMAND_KEY_INDICATOR . $this->commandKey . self::COMMAND_SPLIT_INDICATOR, '', $query);
}
/**
* Find the registerd table command and retrieve the matching table name.
*
* @param string $query
* @return string Database Table name
*/
public function getTableNameFromCommand($query) {
$tableName = '';
$this->extractKeyFromQuery($query);
if (is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['livesearch']) && array_key_exists($this->commandKey, $GLOBALS['TYPO3_CONF_VARS']['SYS']['livesearch'])) {
$tableName = $GLOBALS['TYPO3_CONF_VARS']['SYS']['livesearch'][$this->commandKey];
}
return $tableName;
}
/**
* Verify if an given query contains a page jump command.
*
* @param string $query A valid value looks like '#14'
* @return integer
*/
public function getId($query) {
return str_replace(self::COMMAND_KEY_INDICATOR, '', $query);
}
/**
* Verify if a given query contains a page jump command.
*
* @param string $query A valid value looks like '#14'
* @return boolean
*/
public function isValidPageJump($query) {
$isValid = false;
if (preg_match('~^#(\d)+$~', $query)) {
$isValid = true;
}
return $isValid;
}
/**
* Verify if an given query contains an registered command key.
*
* @param string $query
* @return boolean
*/
public function isValidCommand($query) {
$isValid = false;
if (strpos($query, self::COMMAND_KEY_INDICATOR) === 0 && strpos($query, self::COMMAND_SPLIT_INDICATOR) > 1) {
$isValid = true;
}
return $isValid;
}
}
?>
t3lib/core_autoload.php (working copy)
't3lib_registry' => PATH_t3lib . 'class.t3lib_registry.php',
't3lib_rteapi' => PATH_t3lib . 'class.t3lib_rteapi.php',
't3lib_scbase' => PATH_t3lib . 'class.t3lib_scbase.php',
't3lib_search_livesearch' => PATH_t3lib . 'search/class.t3lib_search_livesearch.php',
't3lib_search_livesearch_queryParser' => PATH_t3lib . 'search/class.t3lib_search_livesearch_queryParser.php',
't3lib_softrefproc' => PATH_t3lib . 'class.t3lib_softrefproc.php',
't3lib_sqlengine' => PATH_t3lib . 'class.t3lib_sqlengine.php',
't3lib_sqlengine_resultobj' => PATH_t3lib . 'class.t3lib_sqlengine.php',
t3lib/extjs/dataprovider/class.extdirect_dataprovider_backendlivesearch.php (revision 0)
<?php
/***************************************************************
* Copyright notice
*
* (c) 2009-2010 Michael Klapper <michael.klapper@aoemedia.de>
* (c) 2010 Jeff Segars <jeff@webempoweredchurch.org>
* 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!
***************************************************************/
/**
* ExtDirect Class for handling backend live search.
*
* @author Michael Klapper <michael.klapper@aoemedia.de>
* @author Jeff Segars <jeff@webempoweredchurch.org>
* @package TYPO3
* @subpackage t3lib
*/
class extDirect_dataProvider_BackendLiveSearch {
/**
* @var array
*/
protected $searchResults = array (
'pageJump' => '',
'searchItems' => array()
);
/**
* @var array
*/
protected $helpContent = array (
'title' => 'How to use advanced search tags',
'text' => 'Search in certain tables:<br />page:Home will search for all pages with the title "Home"',
'keys' => array(),
);
/**
* @var t3lib_search_livesearch
*/
protected $liveSearch = null;
/**
* @var t3lib_search_livesearch_queryParser
*/
protected $queryParser = null;
/**
* Initialize the live search
*/
public function __construct() {
// @todo Use the autoloader for this. Not sure why its not working.
require_once(PATH_t3lib . 'search/class.t3lib_search_livesearch_queryParser.php');
$this->liveSearch = t3lib_div::makeInstance('t3lib_search_livesearch');
$this->queryParser = t3lib_div::makeInstance('t3lib_search_livesearch_queryParser');
}
/**
*
*
* @param stdClass $command
*
* @return array
*/
public function find($command) {
$this->liveSearch->setStartCount($command->start);
$this->liveSearch->setLimitCount($command->limit);
$this->liveSearch->setQueryString($command->query);
// jump & edit - find page and retrieve an edit link (this is only for pages
if ($this->queryParser->isValidPageJump($command->query)) {
$this->searchResults['pageJump'] = $this->liveSearch->findPage($command->query);
// search through the database and find records who match to the given search string
} else {
$resultArray = $this->liveSearch->find($command->query);
foreach ($resultArray as $resultFromTable) {
foreach ($resultFromTable as $item) {
$this->searchResults['searchItems'][] = $item;
}
}
}
return $this->searchResults;
}
/**
* Build up and retrieve the general and custom help text "How can you search"
*
* @return array
*/
public function getHelp() {
$content = array();
$this->helpContent['keys'] = $this->getRegisteredHelpContent();
return $this->helpContent;
}
/**
* Find all registerd help information.
*
* @return array All registered help content will collected returned
* @todo Doesn't actually return any data
*/
public function getRegisteredHelpContent() {
$helpArray = array();
$liveSearchConfiguration = ((is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['livesearch'])) ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['livesearch'] : array());
foreach ($liveSearchConfiguration as $key => $table) {
$helpArray[] = '#' . $key;
}
return $helpArray;
}
}
?>
typo3/js/livesearch.js (revision 0)
/***************************************************************
* Copyright notice
*
* (c) 2009-2010 Michael Klapper <michael.klapper@aoemedia.de>
* (c) 2010 Jeff Segars <jeff@webempoweredchurch.org>
* 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!
***************************************************************/
Ext.namespace('TYPO3');
TYPO3.BackendLiveSearch = Ext.extend(Ext.form.ComboBox, {
autoSelect: false,
ctCls: 'live-search-results',
dataProvider: null,
dbListUrl : 'id=0&search_levels=4&search_field=',
displayField: 'title',
emptyText: null,
enableKeyEvents: true,
helpTitle: null,
itemSelector: 'div.search-item-title',
listAlign : 'tr-br',
listClass: 'live-search-list',
listEmptyText: null,
listWidth: 315,
loadingText: null,
minChars: 2,
resizable: false,
title: null,
width: 205,
triggerClass : 'x-form-clear-trigger',
triggerConfig: '<span tag="a" class="t3-icon t3-icon-actions t3-icon-actions-input t3-icon-input-clear t3-tceforms-input-clearer">&nbsp;</span>',
onTriggerClick: function() {
// Empty the form field, give it focus, and collapse the results
this.reset(this);
this.focus();
this.collapse();
},
tpl: new Ext.XTemplate(
'<table border="0" cellspacing="0">',
'<tpl for=".">',
'<tr class="search-item">',
'<td class="search-item-type" width="105" align="right">{recordTitle}</td>',
'<td class="search-item-content" width="195">',
'<div class="search-item-title">{iconHTML} {title}</span>',
'</td>',
'</tr>',
'</tpl>',
'</table>'
),
dataReader : new Ext.data.JsonReader({
idProperty : 'type',
root : 'searchItems',
fields : [
{name: 'recordTitle'},
{name: 'id'},
{name: 'iconHTML'},
{name: 'title'},
{name: 'editLink'}
]
}),
listeners: {
select : {
scope: this,
fn: function (combo, record, index) {
jump(record.data.editLink, 'web_list', 'web');
}
},
focus : {
fn: function() {
if (this.getValue() == this.emptyText) {
this.reset(this);
}
}
},
specialkey : function () {
TYPO3.ModuleMenu.App.showModule('web_list', this.dbListUrl + this.getValue());
}
},
/**
* Initializes the component.
*/
initComponent: function() {
this.store = new Ext.data.DirectStore({
directFn: this.dataProvider.find,
reader: this.dataReader
});
TYPO3.BackendLiveSearch.superclass.initComponent.apply(this, arguments);
},
restrictHeight : function(){
this.innerList.dom.style.height = '';
var inner = this.innerList.dom;
var pad = this.list.getFrameWidth('tb')+(this.resizable?this.handleHeight:0)+this.assetHeight + 30; // @todo Remove hardcoded 30
var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight);
var ha = this.getPosition()[1]-Ext.getBody().getScroll().top;
var hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height;
var space = Math.max(ha, hb, this.minHeight || 0)-pad-2;
/** BUG FIX **/
if (this.shadow === true) { space-=this.list.shadow.offset; }
h = Math.min(h, space, this.maxHeight);
/**
* @internal The calcated height of "h" in the line before seems not working as expected.
* If i define a min height, the box shold at least use this height also if only one entry is in there
*/
//h = this.maxHeight;
this.innerList.setHeight(h);
this.list.beginUpdate();
this.list.setHeight(h+pad);
this.list.alignTo(this.el, this.listAlign);
this.list.endUpdate();
},
initList : function () {
TYPO3.BackendLiveSearch.superclass.initList.apply(this, arguments);
var cls = 'x-combo-list';
/**
* Create bottom Toolbar to the result layer
*/
this.footer = this.list.createChild({cls:cls+'-ft'});
this.pageTb = new Ext.Toolbar({
renderTo:this.footer,
height: 30,
items: [{
xtype: 'tbfill',
autoWidth : true
},{
xtype: 'button',
text: TYPO3.LLL.liveSearch.showAllResults,
arrowAlign : 'right',
shadow: false,
icon : '../typo3/sysext/t3skin/icons/module_web_list.gif',
listeners : {
scope : this,
click : function () {
// go to db_list.php and search for given search value
// @todo the current selected page ID from the page tree is required, also we need the
// values of $BE_USER->returnWebmounts() to search only during the allowed pages
TYPO3.ModuleMenu.App.showModule('web_list', this.dbListUrl + this.getValue());
this.collapse();
}
}
}]
});
this.assetHeight += this.footer.getHeight();
},
// private
onLoad : function(){
TYPO3.BackendLiveSearch.superclass.onLoad.apply(this, arguments);
// If an pageJump request is done this will immediately load the record for editing.
if (this.dataReader.jsonData.pageJump != '') {
this.collapse();
jump(this.dataReader.jsonData.pageJump, 'web_list', 'web');
} else {
// Add an event handler to each iframe, closing the search window when there's a click inside the iframe
// @todo Is there a cleaner way to handle this?
var iframes = Ext.query('iframe');
Ext.each(iframes, function(item, index, allItems) {
item.contentWindow.document.body.onclick = function() {
if (parent.TYPO3LiveSearch && parent.TYPO3LiveSearch.isExpanded()) {
parent.TYPO3LiveSearch.collapse();
}
};
}, this);
}
},
initQuery : function(){
TYPO3.BackendLiveSearch.superclass.initQuery.apply(this, arguments);
this.removeHelp();
},
initHelp : function () {
if(!this.helpList){
var cls = 'search-list-help';
this.helpList = new Ext.Layer({
parentEl: this.getListParent(),
shadow: this.shadow,
cls: [cls, this.listClass].join(' '),
constrain:false
});
var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
this.helpList.setSize(lw);
this.helpList.swallowEvent('mousewheel');
if(this.syncFont !== false){
this.helpList.setStyle('font-size', this.el.getStyle('font-size'));
}
this.innerHelpList = this.helpList.createChild({cls:cls+'-inner'});
this.mon(this.innerHelpList, 'mouseover', this.onViewOver, this);
this.mon(this.innerHelpList, 'mousemove', this.onViewMove, this);
this.innerHelpList.setWidth(lw - this.helpList.getFrameWidth('lr'));
if(!this.helpTpl){
this.helpTpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';
}
/**
* The {@link Ext.DataView DataView} used to display the ComboBox's options.
* @type Ext.DataView
*/
this.helpView = new Ext.DataView({
applyTo: this.innerHelpList,
tpl: this.helpTpl,
singleSelect: true,
selectedClass: this.selectedClass,
itemSelector: this.itemSelector || '.' + cls + '-item',
emptyText: this.listEmptyText
});
this.helpList.createChild({
cls: cls + '-content',
// @todo Can we grab this content via ExtDirect?
html: '<strong>' + this.helpTitle + '</strong><p>' + TYPO3.LLL.liveSearch.helpDescription + '<br /> ' + TYPO3.LLL.liveSearch.helpDescriptionPages + '</p>'
});
this.helpList.alignTo(this.wrap, this.listAlign);
this.helpList.show();
var iframes = Ext.query('iframe');
Ext.each(iframes, function(item, index, allItems) {
item.contentWindow.document.body.onclick = function() {
if (parent.TYPO3LiveSearch && parent.TYPO3LiveSearch.helpList.isVisible()) {
parent.TYPO3LiveSearch.helpList.remove();
}
};
}, this);
}
},
removeHelp : function() {
if (this.helpList) {
this.helpList.destroy();
}
},
onFocus : function() {
TYPO3.BackendLiveSearch.superclass.onFocus.apply(this, arguments);
// If search is blank, show the help on focus. Otherwise, show last results
if (this.getValue() == '') {
this.initHelp();
} else {
this.expand();
}
},
postBlur : function() {
TYPO3.BackendLiveSearch.superclass.postBlur.apply(this, arguments);
this.removeHelp();
},
getTriggerWidth : function() {
// Trigger is inset, so width used in calculations is 0
return 0;
},
reset : function() {
this.originalValue = this.emptyText;
TYPO3.BackendLiveSearch.superclass.reset.apply(this, arguments);
}
});
var TYPO3LiveSearch;
Ext.onReady(function() {
TYPO3LiveSearch = new TYPO3.BackendLiveSearch({
dataProvider: TYPO3.LiveSearchActions.ExtDirect,
title: TYPO3.LLL.liveSearch.title,
helpTitle: TYPO3.LLL.liveSearch.helpTitle,
emptyText: TYPO3.LLL.liveSearch.emptyText,
loadingText: TYPO3.LLL.liveSearch.loadingText,
listEmptyText: TYPO3.LLL.liveSearch.listEmptyText
});
TYPO3LiveSearch.applyToMarkup(Ext.get('live-search-box'));
});
typo3/classes/class.livesearch.php (revision 0)
<?php
/***************************************************************
* Copyright notice
*
* (c) 2009-2010 Michael Klapper <michael.klapper@aoemedia.de>
* (c) 2010 Jeff Segars <jeff@webempoweredchurch.org>
* 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!
***************************************************************/
/**
* Adds backend live search. to the toolbar
*
* @author Michael Klapper <michael.klapper@aoemedia.de>
* @author Jeff Segars <jeff@webempoweredchurch.org>
* @package TYPO3
* @subpackage t3lib
*/
class LiveSearch implements backend_toolbarItem {
/**
* reference back to the backend object
*
* @var TYPO3backend
*/
protected $backendReference;
/**
* constructor
*
* @param TYPO3backend TYPO3 backend object reference
*/
public function __construct(TYPO3backend &$backendReference = null) {
$this->backendReference = $backendReference;
}
/**
* checks whether the user has access to this toolbar item
*
* @return boolean true if user has access, false if not
*/
public function checkAccess() {
// LiveSearch module is enabled for everybody
return true;
}
/**
* Creates the selector for workspaces
*
* @return string workspace selector as HTML select
*/
public function render() {
$this->addJavascriptToBackend();
return '<div class="live-search-wrapper">
<span title="Search" class="t3-icon t3-icon-apps t3-icon-apps-toolbar t3-icon-toolbar-menu-search">&nbsp;</span>
<input id="live-search-box" />
</div>';
}
/**
* adds the necessary JavaScript to the backend
*
* @return void
*/
protected function addJavascriptToBackend() {
$pageRenderer = $GLOBALS['TBE_TEMPLATE']->getPageRenderer();
$pageRenderer->addJsFile('ajax.php?ajaxID=ExtDirect::getAPI&namespace=TYPO3.LiveSearchActions', 'text/javascript', $compress = FALSE);
$this->backendReference->addJavascriptFile('js/livesearch.js');
}
/**
* returns additional attributes for the list item in the toolbar
*
* @return string list item HTML attibutes
*/
public function getAdditionalAttributes() {
return ' id="live-search-menu"';
}
}
?>
typo3/classes/class.backendsearchmenu.php (working copy)
<?php
/***************************************************************
* Copyright notice
*
* (c) 2007-2010 Ingo Renner <ingo@typo3.org>
* 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!
***************************************************************/
/**
* class to render the backend search toolbar item menu
*
* $Id$
*
* @author Ingo Renner <ingo@typo3.org>
* @package TYPO3
* @subpackage core
*/
class BackendSearchMenu implements backend_toolbarItem {
/**
* reference back to the backend object
*
* @var TYPO3backend
*/
protected $backendReference;
/**
* constructor
*
* @param TYPO3backend TYPO3 backend object reference
*/
public function __construct(TYPO3backend &$backendReference = null) {
$this->backendReference = $backendReference;
}
/**
* checks whether the user has access to this toolbar item
*
* @return boolean true if user has access, false if not
*/
public function checkAccess() {
// Backendsearch module is enabled for everybody
return true;
}
/**
* Creates the selector for workspaces
*
* @return string workspace selector as HTML select
*/
public function render() {
$title = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:toolbarItems.search', true);
$this->addJavascriptToBackend();
$searchMenu = array();
$searchMenu[] = '<a href="#" class="toolbar-item">' .
t3lib_iconWorks::getSpriteIcon('apps-toolbar-menu-search', array('title' => $title)) .
'</a>';
$searchMenu[] = '<div class="toolbar-item-menu" style="display: none;">';
$searchMenu[] = '<input type="text" id="search-query" name="search-query" value="" />';
$searchMenu[] = '</div>';
return implode(LF, $searchMenu);
}
/**
* adds the necessary JavaScript to the backend
*
* @return void
*/
protected function addJavascriptToBackend() {
$this->backendReference->addJavascriptFile('js/backendsearch.js');
}
/**
* returns additional attributes for the list item in the toolbar
*
* @return string list item HTML attibutes
*/
public function getAdditionalAttributes() {
return ' id="backend-search-menu"';
}
}
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/classes/class.backendsearchmenu.php']) {
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/classes/class.backendsearchmenu.php']);
}
?>
typo3/backend.php (working copy)
// core toolbar items
require('classes/class.clearcachemenu.php');
require('classes/class.shortcutmenu.php');
require('classes/class.backendsearchmenu.php');
require('classes/class.livesearch.php');
require_once('class.alt_menu_functions.inc');
$GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_misc.xml');
......
$coreToolbarItems = array(
'shortcuts' => 'ShortcutMenu',
'clearCacheActions' => 'ClearCacheMenu',
'backendSearch' => 'BackendSearchMenu'
'liveSearch' => 'LiveSearch'
);
foreach($coreToolbarItems as $toolbarItemName => $toolbarItemClassName) {
......
protected function renderToolbar() {
// move search to last position
$search = $this->toolbarItems['backendSearch'];
unset($this->toolbarItems['backendSearch']);
$this->toolbarItems['backendSearch'] = $search;
$search = $this->toolbarItems['liveSearch'];
unset($this->toolbarItems['liveSearch']);
$this->toolbarItems['liveSearch'] = $search;
$toolbar = '<ul id="typo3-toolbar">';
$toolbar.= '<li>'.$this->getLoggedInUserLabel().'</li>
......
'allError401' => $GLOBALS['LANG']->getLL('fileUpload_allError401'),
'allError2038' => $GLOBALS['LANG']->getLL('fileUpload_allError2038'),
);
$t3LLLliveSearch = array(
'title' => $GLOBALS['LANG']->getLL('liveSearch_title'),
'helpTitle' => $GLOBALS['LANG']->getLL('liveSearch_helpTitle'),
'emptyText' => $GLOBALS['LANG']->getLL('liveSearch_emptyText'),
'loadingText' => $GLOBALS['LANG']->getLL('liveSearch_loadingText'),
'listEmptyText' => $GLOBALS['LANG']->getLL('liveSearch_listEmptyText'),
'showAllResults' => $GLOBALS['LANG']->getLL('liveSearch_showAllResults'),
'helpDescription' => $GLOBALS['LANG']->getLL('liveSearch_helpDescription'),
'helpDescriptionPages' => $GLOBALS['LANG']->getLL('liveSearch_helpDescriptionPages'),
'helpDescriptionContent' => $GLOBALS['LANG']->getLL('liveSearch_helpDescriptionContent')
);
// Convert labels/settings back to UTF-8 since json_encode() only works with UTF-8:
if ($GLOBALS['LANG']->charSet !== 'utf-8') {
$t3Configuration['username'] = $GLOBALS['LANG']->csConvObj->conv($t3Configuration['username'], $GLOBALS['LANG']->charSet, 'utf-8');
$GLOBALS['LANG']->csConvObj->convArray($t3LLLcore, $GLOBALS['LANG']->charSet, 'utf-8');
$GLOBALS['LANG']->csConvObj->convArray($t3LLLfileUpload, $GLOBALS['LANG']->charSet, 'utf-8');
$GLOBALS['LANG']->csCOnfObj->convArray($t3LLLliveSearch, $GLOBALS['LANG']->charSet, 'utf-8');
}
$this->js .= '
TYPO3.configuration = ' . json_encode($t3Configuration) . ';
TYPO3.LLL = {
core : ' . json_encode($t3LLLcore) . ',
fileUpload: ' . json_encode($t3LLLfileUpload) . '
fileUpload: ' . json_encode($t3LLLfileUpload) . ',
liveSearch: ' . json_encode($t3LLLliveSearch) . '
};
/**
typo3/sysext/t3skin/stylesheets/visual/toolbar_livesearch.css (revision 0)
/* - - - - - - - - - - - - - - - - - - - - -
Backend Live Search
- - - - - - - - - - - - - - - - - - - - - */
.live-search-results .t3-icon-toolbar-menu-search {
position: absolute;
z-index: 3000;
top: 0;
margin: 3px;
}
.t3-icon-input-clear {
position: absolute;
top: 0px;
right: 20px;
}
#live-search-box {
padding-left: 20px;
width: 180px;
border: none;
}
.live-search-list {
background-color: white;
border: none;
}
.live-search-list .x-combo-list {
background-color: white;
}
.live-search-list .x-combo-list-inner {
padding-bottom: 5px;
}
.live-search-list .x-combo-list-hd {
background: none;
border: none;
margin-left: 110px;
color: #ddd;
}
.search-list-help-content {
margin: 5px;
height: 100%;
padding: 0.6em 0.6em 0.6em 2.6em;
background-repeat: no-repeat;
background-position: 0.5em 0.7em;
border: 1px solid;
color: #000000;
background-color: #ddeef9;
border-color: #8aafc4;
}
.live-search-list .search-item-type {
border-right: 1px solid #ddd;
padding: 2px 5px 2px 0;
}
.live-search-list .search-item-content {
padding: 0 8px;
}
.live-search-list .search-item-content .search-item-title {
padding: 2px;
border: none !important;
}
typo3/sysext/t3skin/stylesheets/visual/toolbar_search.css (working copy)
/* - - - - - - - - - - - - - - - - - - - - -
Backend Search
$Id$
- - - - - - - - - - - - - - - - - - - - - */
#backend-search-menu div {
background-color: #f9f9f9;
border: 1px solid #abb2bc;
border-top: none;
text-align: right;
}
#search-query {
border: 1px #848484 solid;
}
... This diff was truncated because it exceeds the maximum size that can be displayed.
(2-2/3)