--- /dev/null
+<?php
+/***************************************************************
+* Copyright notice
+*
+* (c) 2007 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!
+***************************************************************/
+
+if(TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX) {
+ require_once('interfaces/interface.backend_toolbaritem.php');
+ require_once(PATH_t3lib.'class.t3lib_loadmodules.php');
+ require_once(PATH_typo3.'sysext/lang/lang.php');
+
+ $GLOBALS['LANG'] = t3lib_div::makeInstance('language');
+ $GLOBALS['LANG']->init($GLOBALS['BE_USER']->uc['lang']);
+ $GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_misc.xml');
+
+ // needed to get the correct icons when reloading the menu after saving it
+ $loadModules = t3lib_div::makeInstance('t3lib_loadModules');
+ $loadModules->load($GLOBALS['TBE_MODULES']);
+}
+
+
+/**
+ * class to render the shortcut menu
+ *
+ * $Id$
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @package TYPO3
+ * @subpackage core
+ */
+class ShortcutMenu implements backend_toolbarItem {
+
+ private $shortcutGroups;
+
+ /**
+ * all available shortcuts
+ *
+ * @var array
+ */
+ private $shortcuts;
+
+ /**
+ * labels of all groups.
+ * If value is 1, the system will try to find a label in the locallang array.
+ *
+ * @var array
+ */
+ private $groupLabels;
+
+ /**
+ * reference back to the backend object
+ *
+ * @var TYPO3backend
+ */
+ private $backendReference;
+
+ /**
+ * constructor
+ *
+ * @return void
+ */
+ public function __construct() {
+ $this->shortcuts = array();
+
+ // by default, 5 groups are set
+ $this->shortcutGroups = array(
+ 1 => '1',
+ 2 => '1',
+ 3 => '1',
+ 4 => '1',
+ 5 => '1',
+ );
+
+ $this->shortcutGroups = $this->initShortcutGroups();
+ $this->shortcuts = $this->initShortcuts();
+ }
+
+ /**
+ * sets the backend reference
+ *
+ * @param TYPO3backend backend object reference
+ */
+ public function setBackend(&$backendReference) {
+ $this->backendReference = $backendReference;
+ }
+
+ /**
+ * Creates the shortcut menu (default renderer)
+ *
+ * @return string workspace selector as HTML select
+ */
+ public function render() {
+ $this->addJavascriptToBackend();
+
+ $shortcutMenu = array();
+
+ $shortcutMenu[] = '<a href="#" class="toolbar-item"><img'.t3lib_iconWorks::skinImg($this->backPath, 'gfx/toolbar_shortcut.png', 'width="16" height="16"').' title="Shortcuts" alt="" /></a>';
+ $shortcutMenu[] = '<div class="toolbar-item-menu" style="display: none;">';
+ $shortcutMenu[] = $this->renderMenu();
+ $shortcutMenu[] = '</div>';
+
+ return implode("\n", $shortcutMenu);
+ }
+
+ /**
+ * renders the pure contents of the menu
+ *
+ * @return string the menu's content
+ */
+ public function renderMenu() {
+
+ $groupIcon = '<img'.t3lib_iconWorks::skinImg($this->backPath, 'gfx/i/sysf.gif', 'width="18" height="16"').' title="Shortcut Group" alt="" />';
+ $editIcon = '<img'.t3lib_iconWorks::skinImg($this->backPath, 'gfx/edit2.gif', 'width="11" height="12"').' title="Edit Shortcut" alt=""';
+ $deleteIcon = '<img'.t3lib_iconWorks::skinImg($this->backPath, 'gfx/garbage.gif', 'width="11" height="12"').' title="Delete Shortcut" alt="" />';
+
+ $shortcutMenu[] = '<table border="0" cellspacing="0" cellpadding="0" class="shortcut-list">';
+
+ // render shortcuts with no group (group id = 0) first
+ $noGroupShortcuts = $this->getShortcutsByGroup(0);
+ foreach($noGroupShortcuts as $shortcut) {
+ $shortcutMenu[] = '
+ <tr id="shortcut-'.$shortcut['raw']['uid'].'" class="shortcut">
+ <td class="shortcut-icon">'.$shortcut['icon'].'</td>
+ <td class="shortcut-label">
+ <a id="shortcut-label-'.$shortcut['raw']['uid'].'" href="" onclick="'.$shortcut['action'].'">'.$shortcut['label'].'</a>
+ </td>
+ <td class="shortcut-edit">'.$editIcon.' id="shortcut-edit-'.$shortcut['raw']['uid'].'" /></td>
+ <td class="shortcut-delete">'.$deleteIcon.'</td>
+ </tr>';
+ }
+
+ // now render groups and the contained shortcuts
+ $groups = $this->getGroupsFromShortcuts();
+ krsort($groups, SORT_NUMERIC);
+ foreach($groups as $groupId => $groupLabel) {
+ if($groupId != 0 ) {
+ $shortcutGroup = '
+ <tr class="shortcut-group" id="shortcut-group-'.$groupId.'">
+ <td class="shortcut-group-icon">'.$groupIcon.'</td>
+ <td class="shortcut-group-label">'.$groupLabel.'</td>
+ <td colspan="2"> </td>
+ </tr>';
+
+ $shortcuts = $this->getShortcutsByGroup($groupId);
+ $i = 0;
+ foreach($shortcuts as $shortcut) {
+ $i++;
+
+ $firstRow = '';
+ if($i == 1) {
+ $firstRow = ' first-row';
+ }
+
+ $shortcutGroup .= '
+ <tr id="shortcut-'.$shortcut['raw']['uid'].'" class="shortcut'.$firstRow.'">
+ <td class="shortcut-icon">'.$shortcut['icon'].'</td>
+ <td class="shortcut-label">
+ <a id="shortcut-label-'.$shortcut['raw']['uid'].'" href="" onclick="'.$shortcut['action'].'">'.$shortcut['label'].'</a>
+ </td>
+ <td class="shortcut-edit">'.$editIcon.' id="shortcut-edit-'.$shortcut['raw']['uid'].'" /></td>
+ <td class="shortcut-delete">'.$deleteIcon.'</td>
+ </tr>';
+ }
+
+ $shortcutMenu[] = $shortcutGroup;
+ }
+ }
+
+ $shortcutMenu[] = '</table>';
+ $compiledShortcutMenu = implode("\n", $shortcutMenu);
+
+ return $compiledShortcutMenu;
+ }
+
+ /**
+ * renders the menu so that it can be returned as response to an AJAX call
+ *
+ * @param array array of parameters from the AJAX interface, currently unused
+ * @param TYPO3AJAX object of type TYPO3AJAX
+ * @return void
+ */
+ public function renderAjax($params = array(), TYPO3AJAX &$ajaxObj = null) {
+ $menuContent = $this->renderMenu();
+
+ $ajaxObj->addContent('shortcutMenu', $menuContent);
+ }
+
+ /**
+ * adds the neccessary javascript ot the backend
+ *
+ * @return void
+ */
+ private function addJavascriptToBackend() {
+ $this->backendReference->addJavascriptFile('typo3/js/shortcutmenu.js');
+ }
+
+ /**
+ * returns additional attributes for the list item in the toolbar
+ *
+ * @return string list item HTML attibutes
+ */
+ public function getAdditionalAttributes() {
+ return ' id="shortcut-menu"';
+ }
+
+ /**
+ * retrieves the shortcuts for the current user
+ *
+ * @return array array of shortcuts
+ */
+ private function initShortcuts() {
+ $shortcuts = array();
+ $globalGroups = $this->getGlobalShortcutGroups();
+
+ $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
+ '*',
+ 'sys_be_shortcuts',
+ '((userid = '.$GLOBALS['BE_USER']->user['uid'].' AND sc_group>=0) OR sc_group IN ('.implode(',', array_keys($globalGroups)).'))',
+ '',
+ 'sc_group,sorting'
+ );
+
+ // Traverse shortcuts
+ while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
+ $shortcut = array('raw' => $row);
+ $moduleParts = explode('|', $row['module_name']);
+ $row['module_name'] = $moduleParts[0];
+ $row['M_module_name'] = $moduleParts[1];
+ $moduleParts = explode('_', $row['M_module_name'] ?
+ $row['M_module_name'] :
+ $row['module_name']
+ );
+ $queryParts = parse_url($row['url']);
+
+ // check for module access
+ if(!$GLOBALS['BE_USER']->isAdmin()) {
+ if(!isset($GLOBALS['LANG']->moduleLabels['tabs_images'][implode('_', $moduleParts).'_tab'])) {
+ // nice hack to check if the user has access to this module
+ // - otherwise the translation label would not have been loaded :-)
+ continue;
+ }
+
+ $pageId = $this->getLinkedPageId($row['url']);
+ if(t3lib_div::testInt($pageId)) {
+ // check for webmount access
+ if(!$GLOBALS['BE_USER']->isInWebMount($page_id)) {
+ continue;
+ }
+
+ // check for record access
+ $pageRow = t3lib_BEfunc::getRecord('pages', $pageId);
+ if(!$GLOBALS['BE_USER']->doesUserHaveAccess($pageRow, $perms = 1)) {
+ continue;
+ }
+ }
+ }
+
+ $shortcutGroup = $row['sc_group'];
+ if($shortcutGroup && strcmp($lastGroup, $shortcutGroup) && ($shortcutGroup != -100)) {
+ $shortcut['groupLabel'] = $this->getShortcutGroupLabel($shortcutGroup);
+ }
+
+ if($row['description']) {
+ $shortcut['label'] = $row['description'];
+ } else {
+ $shortcut['label'] = t3lib_div::fixed_lgd(rawurldecode($queryParts['query']), 150);
+ }
+
+ $shortcut['group'] = $shortcutGroup;
+ $shortcut['icon'] = $this->getShortcutIcon($row['module_name']);
+ $shortcut['iconTitle'] = $this->getShortcutIconTitle($shortcutLabel, $row['module_name'], $row['M_module_name']);
+ $shortcut['action'] = 'jump(unescape(\''.rawurlencode($row['url']).'\'),\''.implode('_',$moduleParts).'\',\''.$moduleParts[0].'\');';
+
+ $lastGroup = $row['sc_group'];
+ $shortcuts[] = $shortcut;
+ }
+
+ return $shortcuts;
+ }
+
+ /**
+ * gets shortcuts for a specific group
+ *
+ * @param integer group Id
+ * @return array array of shortcuts that matched the group
+ */
+ private function getShortcutsByGroup($groupId) {
+ $shortcuts = array();
+
+ foreach($this->shortcuts as $shortcut) {
+ if($shortcut['group'] == $groupId) {
+ $shortcuts[] = $shortcut;
+ }
+ }
+
+ return $shortcuts;
+ }
+
+ /**
+ * gets a shortcut by its uid
+ *
+ * @param integer shortcut id to get the complete shortcut for
+ * @return mixed an array containing the shortcut's data on success or false on failure
+ */
+ private function getShortcutById($shortcutId) {
+ $returnShortcut = false;
+
+ foreach($this->shortcuts as $shortcut) {
+ if($shortcut['raw']['uid'] == (int) $shortcutId) {
+ $returnShortcut = $shortcut;
+ continue;
+ }
+ }
+
+ return $returnShortcut;
+ }
+
+ /**
+ * gets the available shortcut groups from default gropups, user TSConfig,
+ * and global groups
+ *
+ * @param array array of parameters from the AJAX interface, currently unused
+ * @param TYPO3AJAX object of type TYPO3AJAX
+ * @return array
+ */
+ private function initShortcutGroups($params = array(), TYPO3AJAX &$ajaxObj = null) {
+ // groups from TSConfig
+ $userShortcutGroups = $GLOBALS['BE_USER']->getTSConfig('options.shortcutGroups');
+
+ if(is_array($userShortcutGroups['properties']) && count($userShortcutGroups['properties'])) {
+ foreach($userShortcutGroups['properties'] as $groupId => $label) {
+ if(strcmp('', $label) && strcmp('0', $label)) {
+ $this->shortcutGroups[$groupId] = (string) $label;
+ } elseif($GLOBALS['BE_USER']->isAdmin()) {
+ unset($this->shortcutGroups[$groupId]);
+ }
+ }
+ }
+
+ // generate global groups, all global groups have negative IDs.
+ if(count($this->shortcutGroups)) {
+ $groups = $this->shortcutGroups;
+ foreach($groups as $groupId => $groupLabel) {
+ $this->shortcutGroups[($groupId * -1)] = $groupLabel;
+ }
+ }
+
+ // group -100 is kind of superglobal and can't be changed.
+ $this->shortcutGroups[-100] = 1;
+
+ // add labels
+ foreach($this->shortcutGroups as $groupId => $groupLabel) {
+ $label = $groupLabel;
+
+ if($groupLabel == '1') {
+ $label = $GLOBALS['LANG']->getLL('shortcut_group_'.abs($groupId), 1);
+
+ if(empty($label)) {
+ // fallback label
+ $label = $GLOBALS['LANG']->getLL('shortcut_group', 1).' '.abs($groupId);
+ }
+ }
+
+ if($groupId < 0) {
+ // global group
+ $label = $GLOBALS['LANG']->getLL('shortcut_global', 1).': '.
+ (!empty($label) ?
+ $label :
+ abs($groupId)
+ );
+
+ if($groupId == -100) {
+ $label = $GLOBALS['LANG']->getLL('shortcut_global', 1).': '.$GLOBALS['LANG']->getLL('shortcut_all', 1);
+ }
+ }
+
+ $this->shortcutGroups[$groupId] = $label;
+ }
+
+ return $this->shortcutGroups;
+ }
+
+ /**
+ * gets the available shortcut groups
+ *
+ * @param array array of parameters from the AJAX interface, currently unused
+ * @param TYPO3AJAX object of type TYPO3AJAX
+ * @return void
+ */
+ public function getAjaxShortcutGroups($params = array(), TYPO3AJAX &$ajaxObj = null) {
+
+ //TODO remove global (negative id) groups if the user is no admin !!!
+
+ $ajaxObj->addContent('shortcutGroups', $this->shortcutGroups);
+ $ajaxObj->setContentFormat('json');
+ }
+
+ /**
+ * deletes a shortcut through an AJAX call
+ *
+ * @param array array of parameters from the AJAX interface, currently unused
+ * @param TYPO3AJAX object of type TYPO3AJAX
+ * @return void
+ */
+ public function deleteAjaxShortcut($params = array(), TYPO3AJAX &$ajaxObj = null) {
+ $shortcutId = (int) t3lib_div::_POST('shortcutId');
+ $fullShortcut = $this->getShortcutById($shortcutId);
+ $ajaxReturn = 'failed';
+
+ if($fullShortcut['raw']['userid'] == $GLOBALS['BE_USER']->user['uid']) {
+ $GLOBALS['TYPO3_DB']->exec_DELETEquery(
+ 'sys_be_shortcuts',
+ 'uid = '.$shortcutId
+ );
+
+ if($GLOBALS['TYPO3_DB']->sql_affected_rows() == 1) {
+ $ajaxReturn = 'deleted';
+ }
+ }
+
+ $ajaxObj->addContent('delete', $ajaxReturn);
+ }
+
+ /**
+ * creates a shortcut through an AJAX call
+ *
+ * @param array array of parameters from the AJAX interface, currently unused
+ * @param TYPO3AJAX object of type TYPO3AJAX
+ * @return void
+ */
+ public function createAjaxShortcut($params = array(), TYPO3AJAX &$ajaxObj = null) {
+ $shortcutCreated = 'failed';
+ $shortcutName = 'Shortcut'; // default name
+
+ $url = urldecode(t3lib_div::_POST('url'));
+ $module = t3lib_div::_POST('module');
+ $motherModule = t3lib_div::_POST('motherModName');
+
+ // Lookup the title of this page and use it as default description
+ $pageId = $this->getLinkedPageId($url);
+
+ if(t3lib_div::testInt($pageId)) {
+ $page = t3lib_BEfunc::getRecord('pages', $pageId);
+ if(count($page)) {
+ // set the name to the title of the page
+ $shortcutName = $page['title'];
+ }
+ } else {
+ if (preg_match('/\/$/', $pageId)) {
+ // if $pageId is a string and ends with a slash,
+ // assume it is a fileadmin reference and set
+ // the description to the basename of that path
+ $shortcutName = basename($pageId);
+ }
+ }
+
+ // adding the shortcut
+ if($module && $url) {
+ $fieldValues = array(
+ 'userid' => $GLOBALS['BE_USER']->user['uid'],
+ 'module_name' => $module.'|'.$motherModule,
+ 'url' => $url,
+ 'description' => $shortcutName,
+ 'sorting' => time(),
+ );
+ $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_be_shortcuts', $fieldValues);
+
+ if($GLOBALS['TYPO3_DB']->sql_affected_rows() == 1) {
+ $shortcutCreated = 'success';
+ }
+ }
+
+ $ajaxObj->addContent('create', $shortcutCreated);
+ }
+
+ /**
+ * gets called when a shortcut is changed, checks whether the user has
+ * permissions to do so and saves the changes if everything is ok
+ *
+ * @param array array of parameters from the AJAX interface, currently unused
+ * @param TYPO3AJAX object of type TYPO3AJAX
+ * @return void
+ */
+ public function setAjaxShortcut($params = array(), TYPO3AJAX &$ajaxObj = null) {
+
+ $shortcutId = (int) t3lib_div::_POST('shortcutId');
+ $shortcutName = strip_tags(t3lib_div::_POST('value'));
+ $shortcutGroupId = (int) t3lib_div::_POST('shortcut-group');
+
+ if($shortcutGroupId > 0 || $GLOBALS['BE_USER']->isAdmin()) {
+ // users can delete only their own shortcuts (except admins)
+ $addUserWhere = (!$GLOBALS['BE_USER']->isAdmin() ?
+ ' AND userid='.intval($GLOBALS['BE_USER']->user['uid'])
+ : ''
+ );
+
+ $fieldValues = array(
+ 'description' => $shortcutName,
+ 'sc_group' => $shortcutGroupId
+ );
+
+ if($fieldValues['sc_group'] < 0 && !$GLOBALS['BE_USER']->isAdmin()) {
+ $fieldValues['sc_group'] = 0;
+ }
+
+ $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
+ 'sys_be_shortcuts',
+ 'uid='.$shortcutId.$addUserWhere,
+ $fieldValues
+ );
+
+ $affectedRows = $GLOBALS['TYPO3_DB']->sql_affected_rows();
+ if($affectedRows == 1) {
+ $ajaxObj->addContent('shortcut', $shortcutName);
+ } else {
+ $ajaxObj->addContent('shortcut', 'failed');
+ }
+ }
+
+ $ajaxObj->setContentFormat('plain');
+ }
+
+ /**
+ * gets the label for a shortcut group
+ *
+ * @param integer a shortcut group id
+ * @return string the shortcut group label, can be an empty string if no group was found for the id
+ */
+ private function getShortcutGroupLabel($groupId) {
+ $label = '';
+
+ if($this->shortcutGroups[$groupId]) {
+ $label = $this->shortcutGroups[$groupId];
+ }
+
+ return $label;
+ }
+
+ /**
+ * gets a list of global groups, shortcuts in these groups are available to all users
+ *
+ * @return array array of global groups
+ */
+ private function getGlobalShortcutGroups() {
+ $globalGroups = array();
+
+ foreach($this->shortcutGroups as $groupId => $groupLabel) {
+ if($groupId < 0) {
+ $globalGroups[$groupId] = $groupLabel;
+ }
+ }
+
+ return $globalGroups;
+ }
+
+ /**
+ * runs through the available shortcuts an collects their groups
+ *
+ * @return array array of groups which have shortcuts
+ */
+ private function getGroupsFromShortcuts() {
+ $groups = array();
+
+ foreach($this->shortcuts as $shortcut) {
+ $groups[$shortcut['group']] = $this->shortcutGroups[$shortcut['group']];
+ }
+
+ return array_unique($groups);
+ }
+
+ /**
+ * gets the icon for the shortcut
+ *
+ * @param string backend module name
+ * @return string shortcut icon as img tag
+ */
+ private function getShortcutIcon($moduleName) {
+
+ switch($moduleName) {
+ case 'xMOD_alt_doc.php':
+ $icon = 'gfx/edit2.gif';
+ break;
+ case 'xMOD_file_edit.php':
+ $icon = 'gfx/edit_file.gif';
+ break;
+ case 'xMOD_wizard_rte.php':
+ $icon = 'gfx/edit_rtewiz.gif';
+ break;
+ default:
+ if($GLOBALS['LANG']->moduleLabels['tabs_images'][$moduleName.'_tab']) {
+ $icon = $GLOBALS['LANG']->moduleLabels['tabs_images'][$moduleName.'_tab'];
+
+ // change icon of fileadmin references - otherwise it doesn't differ with Web->List
+ $icon = str_replace('mod/file/list/list.gif', 'mod/file/file.gif', $icon);
+
+ if(t3lib_div::isAbsPath($icon)) {
+ $icon = '../'.substr($icon, strlen(PATH_site));
+ }
+ } else {
+ $icon = 'gfx/dummy_module.gif';
+ }
+ }
+
+ $icon = '<img src="'.$icon.'" alt="shortcut icon" />';
+
+ return $icon;
+ }
+
+ /**
+ * Returns title for the shortcut icon
+ *
+ * @param string shortcut label
+ * @param string backend module name (key)
+ * @param string parent module label
+ * @return string title for the shortcut icon
+ */
+ private function getShortcutIconTitle($shortcutLabel, $moduleName, $parentModuleName = '') {
+ $title = '';
+
+ if(substr($moduleName, 0, 5) == 'xMOD_') {
+ $title = substr($moduleName, 5);
+ } else {
+ $splitModuleName = explode('_', $moduleName);
+ $title = $GLOBALS['LANG']->moduleLabels['tabs'][$splitModuleName[0].'_tab'];
+
+ if(count($splitModuleName) > 1) {
+ $title .= '>'.$GLOBALS['LANG']->moduleLabels['tabs'][$moduleName.'_tab'];
+ }
+ }
+
+ if($parentModuleName) {
+ $title .= ' ('.$parentModuleName.')';
+ }
+
+ $title .= ': '.$shortcutLabel;
+
+ return $title;
+ }
+
+ /**
+ * Return the ID of the page in the URL if found.
+ *
+ * @param string The URL of the current shortcut link
+ * @return string If a page ID was found, it is returned. Otherwise: 0
+ */
+ private function getLinkedPageId($url) {
+ return preg_replace('/.*[\?&]id=([^&]+).*/', '$1', $url);
+ }
+
+}
+
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/classes/class.shortcutmenu.php']) {
+ include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/classes/class.shortcutmenu.php']);
+}
+
+?>
\ No newline at end of file
--- /dev/null
+/***************************************************************
+* Copyright notice
+*
+* (c) 2007 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 handle the shortcut menu
+ *
+ * $Id$
+ */
+var ShortcutMenu = Class.create({
+
+ /**
+ * registers for resize event listener and executes on DOM ready
+ */
+ initialize: function() {
+ Event.observe(window, 'resize', this.positionMenu);
+
+ Event.observe(document, 'dom:loaded', function(){
+ this.positionMenu();
+ this.toolbarItemIcon = $$('#shortcut-menu .toolbar-item img')[0].src;
+
+ Event.observe($$('#shortcut-menu .toolbar-item')[0], 'click', this.toggleMenu);
+ this.initControls();
+ }.bindAsEventListener(this));
+ },
+
+ /**
+ * initializes the controls to follow, edit, and delete shortcuts
+ *
+ */
+ initControls: function() {
+
+ $$('.shortcut-label a').each(function(element) {
+ var shortcutId = element.up('tr.shortcut').identify().slice(9);
+
+ // map InPlaceEditor to edit icons
+ new Ajax.InPlaceEditor('shortcut-label-' + shortcutId, 'ajax.php?ajaxID=ShortcutMenu::saveShortcut', {
+ externalControl : 'shortcut-edit-' + shortcutId,
+ externalControlOnly : true,
+ highlightcolor : 'transparent',
+ onFormCustomization : this.addGroupSelect,
+ onComplete : this.reRenderMenu.bind(this),
+ callback : function(form, nameInputFieldValue) {
+ var params = form.serialize();
+ params += '&shortcutId=' + shortcutId;
+
+ return params;
+ },
+ textBetweenControls : ' ',
+ cancelControl : 'button',
+ clickToEditText : '',
+ htmlResponse : true
+ });
+
+ // follow/execute shortcuts
+ element.observe('click', function(event) {
+ Event.stop(event);
+ this.toggleMenu();
+ }.bind(this));
+
+ }.bind(this));
+
+ // activate delete icon
+ $$('.shortcut-delete img').each(function(element) {
+ element.observe('click', function(event) {
+ if(confirm('Do you really want to remove this shortcut?')) {
+ var deleteControl = event.element();
+ var shortcutId = deleteControl.up('tr.shortcut').identify().slice(9);
+
+ new Ajax.Request('ajax.php', {
+ parameters : 'ajaxID=ShortcutMenu::delete&shortcutId=' + shortcutId,
+ onComplete : this.reRenderMenu.bind(this)
+ });
+ }
+ }.bind(this));
+ }.bind(this));
+
+ },
+
+ /**
+ * positions the menu below the toolbar icon, let's do some math!
+ */
+ positionMenu: function() {
+ var calculatedOffset = 0;
+ var parentWidth = $('shortcut-menu').getWidth();
+ var ownWidth = $$('#shortcut-menu .toolbar-item-menu')[0].getWidth();
+ var parentSiblings = $('shortcut-menu').previousSiblings();
+
+ parentSiblings.each(function(toolbarItem) {
+ calculatedOffset += toolbarItem.getWidth() - 1;
+ // -1 to compensate for the margin-right -1px of the list items,
+ // which itself is necessary for overlaying the separator with the active state background
+
+ if(toolbarItem.down().hasClassName('no-separator')) {
+ calculatedOffset -= 1;
+ }
+ });
+ calculatedOffset = calculatedOffset - ownWidth + parentWidth;
+
+
+ $$('#shortcut-menu .toolbar-item-menu')[0].setStyle({
+ left: calculatedOffset + 'px'
+ });
+ },
+
+ /**
+ * toggles the visibility of the menu and places it under the toolbar icon
+ */
+ toggleMenu: function() {
+ var toolbarItem = $$('#shortcut-menu > a')[0];
+ var menu = $$('#shortcut-menu .toolbar-item-menu')[0];
+ toolbarItem.blur();
+
+ if(!toolbarItem.hasClassName('toolbar-item-active')) {
+ toolbarItem.addClassName('toolbar-item-active');
+ Effect.Appear(menu, {duration: 0.2});
+ TYPO3BackendToolbarManager.hideOthers(toolbarItem);
+ } else {
+ toolbarItem.removeClassName('toolbar-item-active');
+ Effect.Fade(menu, {duration: 0.1});
+ }
+ },
+
+ /**
+ * adds a select field for the groups
+ */
+ addGroupSelect: function(inPlaceEditor, inPlaceEditorForm) {
+ var selectField = document.createElement('select');
+
+ // determine the shortcut id
+ var shortcutId = inPlaceEditorForm.identify().slice(9, -14);
+
+ // now determine the shortcut's group id
+ var shortcut = $('shortcut-' + shortcutId).up('tr.shortcut');
+ var firstInGroup = null;
+ var shortcutGroupId = 0;
+
+ if(shortcut.hasClassName('first-row')) {
+ firstInGroup = shortcut;
+ } else {
+ firstInGroup = shortcut.previous('.first-row');
+ }
+
+ if(undefined != firstInGroup) {
+ shortcutGroupId = firstInGroup.previous().identify().slice(15);
+ }
+
+ selectField.name = 'shortcut-group';
+ selectField.id = 'shortcut-group-select-' + shortcutId;
+ selectField.size = 1;
+ selectField.setStyle({marginBottom: '5px'});
+
+ // create options
+ var option;
+ // first create an option for "no group"
+ option = document.createElement('option');
+ option.value = 0;
+ option.selected = (shortcutGroupId == 0 ? true : false);
+ option.appendChild(document.createTextNode('No Group'));
+ selectField.appendChild(option);
+
+ // get the groups
+ new Ajax.Request('ajax.php', {
+ method: 'get',
+ parameters: 'ajaxID=ShortcutMenu::getGroups',
+ asynchronous: false, // needs to be synchronous to build the options before adding the selectfield
+ requestHeaders: {Accept: 'application/json'},
+ onSuccess: function(transport, json) {
+ var shortcutGroups = transport.responseText.evalJSON(true);
+
+ // explicitly make the object a Hash
+ shortcutGroups = $H(json.shortcutGroups);
+ shortcutGroups.each(function(group) {
+ option = document.createElement('option');
+ option.value = group.key
+ option.selected = (shortcutGroupId == group.key ? true : false);
+ option.appendChild(document.createTextNode(group.value));
+ selectField.appendChild(option);
+ });
+
+ }
+ });
+
+ inPlaceEditor._form.appendChild(selectField);
+ inPlaceEditor._form.appendChild(document.createElement('br'));
+ },
+
+ /**
+ * gets called when the update was succesfull, fetches the complete menu to
+ * honor changes in group assignments
+ */
+ reRenderMenu: function(transport, element, backPath) {
+ var container = $$('#shortcut-menu .toolbar-item-menu')[0];
+ if(!backPath) {
+ var backPath = '';
+ }
+
+
+ container.setStyle({
+ height: container.getHeight() + 'px'
+ });
+ container.update('LOADING');
+
+ new Ajax.Updater(
+ container,
+ backPath + 'ajax.php',
+ {
+ parameters : 'ajaxID=ShortcutMenu::render',
+ asynchronous : false
+ }
+ );
+
+ container.setStyle({
+ height: 'auto'
+ });
+
+ this.initControls();
+ },
+
+ /**
+ * makes a call to the backend class to create a new shortcut,
+ * when finished it reloads the menu
+ */
+ createShortcut: function(backPath, moduleName, url) {
+
+ // synchrous call to wait for it to complete and call the render
+ // method with backpath _afterwards_
+ new Ajax.Request(backPath + 'ajax.php', {
+ parameters : 'ajaxID=ShortcutMenu::create&module=' + moduleName + '&url=' + url,
+ asynchronous : false
+ });
+
+ this.reRenderMenu(null, null, backPath);
+ }
+
+});
+
+var TYPO3BackendShortcutMenu = new ShortcutMenu();