Added feature #16396: Implement a Grid View + wizard to enable the backend layout...
authorSteffen Kamper <info@sk-typo3.de>
Tue, 16 Nov 2010 11:47:53 +0000 (11:47 +0000)
committerSteffen Kamper <info@sk-typo3.de>
Tue, 16 Nov 2010 11:47:53 +0000 (11:47 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@9393 709f56b5-9817-0410-a4d7-c38de5d9e867

49 files changed:
ChangeLog
t3lib/class.t3lib_befunc.php
t3lib/stddb/tables.sql
t3lib/stddb/tbl_be.php
t3lib/stddb/tbl_pages.php
typo3/sysext/cms/class.tx_cms_be_layout.php [new file with mode: 0644]
typo3/sysext/cms/ext_tables.php
typo3/sysext/cms/ext_tables.sql
typo3/sysext/cms/layout/class.tx_cms_layout.php
typo3/sysext/cms/layout/db_layout.php
typo3/sysext/cms/layout/locallang.xml
typo3/sysext/cms/layout/res/grideditor.css [new file with mode: 0644]
typo3/sysext/cms/layout/res/grideditor.js [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-edit-inactive-1.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-edit-inactive.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-edit.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-editor-down-inactive.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-editor-down.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-editor-left-inactive.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-editor-left.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-editor-right-inactive.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-editor-right.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-editor-up-inactive.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-editor-up.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-layer-icon-close.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-layer-icon-help.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-layer-icon-save.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-tabledown.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-tableleft.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-tableright.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/t3grid-tableup.png [new file with mode: 0644]
typo3/sysext/cms/layout/res/typo3.pageModule.js [new file with mode: 0644]
typo3/sysext/cms/layout/wizard_be_layout.php [new file with mode: 0644]
typo3/sysext/cms/locallang_tca.xml
typo3/sysext/cms/tbl_cms.php
typo3/sysext/cms/tbl_tt_content.php
typo3/sysext/lang/locallang_wizards.xml
typo3/sysext/t3skin/icons/gfx/i/be_layout.gif [new file with mode: 0644]
typo3/sysext/t3skin/icons/gfx/i/be_layout__f.gif [new file with mode: 0644]
typo3/sysext/t3skin/icons/gfx/i/be_layout__h.gif [new file with mode: 0644]
typo3/sysext/t3skin/icons/gfx/i/be_layout__hf.gif [new file with mode: 0644]
typo3/sysext/t3skin/icons/gfx/i/be_layout__hfu.gif [new file with mode: 0644]
typo3/sysext/t3skin/icons/gfx/i/be_layout__ht.gif [new file with mode: 0644]
typo3/sysext/t3skin/icons/gfx/i/be_layout__htu.gif [new file with mode: 0644]
typo3/sysext/t3skin/icons/gfx/i/be_layout__hu.gif [new file with mode: 0644]
typo3/sysext/t3skin/icons/gfx/i/be_layout__t.gif [new file with mode: 0644]
typo3/sysext/t3skin/icons/gfx/i/be_layout__u.gif [new file with mode: 0644]
typo3/sysext/t3skin/icons/gfx/i/be_layout__x.gif [new file with mode: 0644]
typo3/sysext/t3skin/images/icons/mimetypes/x_belayout.png [new file with mode: 0644]

index 257f50c..524966f 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,14 +1,6 @@
-2010-11-15  Ingo Renner  <ingo@typo3.org>
+2010-11-16  Steffen Kamper  <steffen@typo3.org>
 
-       * Resolved issue #16388: Clean up installed services report
-
-2010-11-15  Christian Kuhn  <lolli@schwarzbu.ch>
-
-       * Added feature #16410: [Caching framework] Implement redis as cache backend
-
-2010-11-15  Steffen Gebert  <steffen@steffen-gebert.de>
-
-       * Added feature #16403: Integrate modernizr into the TYPO3 Backend
+       * Added feature #16396: Implement a Grid View + wizard to enable the backend layout to be adapted to the frontend look and feel (Thanks to Joey Hasenau, Martin Ficzel and Thomas Hempel)
 
 2010-11-15  Steffen Kamper  <steffen@typo3.org>
 
@@ -22,7 +14,6 @@
 2010-11-15  Ernesto Baschny  <ernst@cron-it.de>
 
        * Added feature #16170: Increase DB-fields spaceBefore and spaceAfter (tt_content) (Thanks to Henrik Ziegenhain)
-       * Added feature #16111: Change the layout of thumbnails and allowed file types so that they don't waste so much space anymore (Thanks to Jo Hasenau)
 
 2010-11-14  Steffen Kamper  <steffen@typo3.org>
 
index c481609..a0780d2 100644 (file)
@@ -617,7 +617,8 @@ final class t3lib_BEfunc {
                                        't3ver_wsid' => $val['t3ver_wsid'],
                                        't3ver_state' => $val['t3ver_state'],
                                        't3ver_swapmode' => $val['t3ver_swapmode'],
-                                       't3ver_stage' => $val['t3ver_stage']
+                                       't3ver_stage' => $val['t3ver_stage'],
+                                       'be_layout' => $val['be_layout']
                                );
                                if (isset($val['_ORIG_pid'])) {
                                        $output[$c]['_ORIG_pid'] = $val['_ORIG_pid'];
@@ -645,7 +646,7 @@ final class t3lib_BEfunc {
                        $row = $getPageForRootline_cache[$ident];
                } else {
                        $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
-                               'pid,uid,title,TSconfig,is_siteroot,storage_pid,t3ver_oid,t3ver_wsid,t3ver_state,t3ver_swapmode,t3ver_stage',
+                               'pid,uid,title,TSconfig,is_siteroot,storage_pid,t3ver_oid,t3ver_wsid,t3ver_state,t3ver_swapmode,t3ver_stage,be_layout',
                                'pages',
                                'uid=' . intval($uid) . ' ' .
                                        self::deleteClause('pages') . ' ' .
index f538a67..bc5165d 100644 (file)
@@ -215,6 +215,8 @@ CREATE TABLE pages (
   alias varchar(32) DEFAULT '' NOT NULL,
   l18n_cfg tinyint(4) DEFAULT '0' NOT NULL,
   fe_login_mode tinyint(4) DEFAULT '0' NOT NULL,
+  be_layout int(10) DEFAULT '0' NOT NULL,
+  be_layout_next_level int(10) DEFAULT '0' NOT NULL,
   PRIMARY KEY (uid),
   KEY t3ver_oid (t3ver_oid,t3ver_wsid),
   KEY parent (pid,sorting,deleted,hidden),
index 656c2bb..f90c22f 100644 (file)
@@ -702,7 +702,6 @@ $TCA['be_groups'] = array(
 );
 
 
-
 /**
  * System filemounts - Defines filepaths on the server which can be mounted for users so they can upload and manage files online by eg. the Filelist module
  */
index ca2bb53..4598c9f 100644 (file)
@@ -6,7 +6,7 @@ if (!defined('TYPO3_MODE')) {
 $TCA['pages'] = array(
        'ctrl' => $TCA['pages']['ctrl'],
        'interface' => array(
-               'showRecordFieldList' => 'doktype,title,alias,hidden,starttime,endtime,fe_group,url,target,no_cache,shortcut,keywords,description,abstract,newUntil,lastUpdated,cache_timeout',
+               'showRecordFieldList' => 'doktype,title,alias,hidden,starttime,endtime,fe_group,url,target,no_cache,shortcut,keywords,description,abstract,newUntil,lastUpdated,cache_timeout,be_layout,be_layout_next_level',
                'maxDBListItems' => 30,
                'maxSingleDBListItems' => 50,
        ),
@@ -732,6 +732,40 @@ $TCA['pages'] = array(
                                ),
                        ),
                ),
+               'be_layout' => array (
+                       'exclude' => 1,
+                       'label' => 'LLL:EXT:cms/locallang_tca.xml:pages.be_layout',
+                       'config' => array (
+                               'type' => 'select',
+                               'foreign_table' => 'be_layouts',
+                               'foreign_table_where' => 'AND ( ( ###PAGE_TSCONFIG_ID### = 0 AND ###STORAGE_PID### = 0 ) OR ( be_layouts.pid = ###PAGE_TSCONFIG_ID### OR be_layouts.pid = ###STORAGE_PID### ) ) AND be_layouts.hidden = 0',
+                               'items' => array (
+                                       array ('', 0),
+                                       array ('none', -1)
+                               ),
+                               'selicon_cols' => 5,
+                               'size' => 1,
+                               'maxitems' => 1,
+                               'default' => ''
+                       )
+               ),
+               'be_layout_next_level' => array (
+                       'exclude' => 1,
+                       'label' => 'LLL:EXT:cms/locallang_tca.xml:pages.be_layout_next_level',
+                       'config' => array (
+                               'type' => 'select',
+                               'foreign_table' => 'be_layouts',
+                               'foreign_table_where' => 'AND ( ( ###PAGE_TSCONFIG_ID### = 0 AND ###STORAGE_PID### = 0 ) OR ( be_layouts.pid = ###PAGE_TSCONFIG_ID### OR be_layouts.pid = ###STORAGE_PID### ) ) AND be_layouts.hidden = 0',
+                               'items' => array (
+                                       array ('', 0),
+                                       array ('none', -1)
+                               ),
+                               'selicon_cols' => 5,
+                               'size' => 1,
+                               'maxitems' => 1,
+                               'default' => ''
+                       )
+               )
        ),
        'types' => array(
                        // normal
@@ -915,6 +949,9 @@ $TCA['pages'] = array(
                '7' => array(
                        'showitem' => 'is_siteroot',
                ),
+               '8' => array(
+                       'showitem' => 'be_layout_next_level'
+               ),
                'standard' => array(
                        'showitem' => 'doktype;LLL:EXT:cms/locallang_tca.xml:pages.doktype_formlabel',
                        'canNotCollapse' => 1,
@@ -972,7 +1009,7 @@ $TCA['pages'] = array(
                        'canNotCollapse' => 1,
                ),
                'layout' => array(
-                       'showitem' => 'layout;LLL:EXT:cms/locallang_tca.xml:pages.layout_formlabel, newUntil;LLL:EXT:cms/locallang_tca.xml:pages.newUntil_formlabel',
+                       'showitem' => 'layout;LLL:EXT:cms/locallang_tca.xml:pages.layout_formlabel, newUntil;LLL:EXT:cms/locallang_tca.xml:pages.newUntil_formlabel, --linebreak--, be_layout;LLL:EXT:cms/locallang_tca.xml:pages.be_layout_formlabel, be_layout_next_level;LLL:EXT:cms/locallang_tca.xml:pages.be_layout_next_level_formlabel',
                        'canNotCollapse' => 1,
                ),
                'module' => array(
@@ -1014,8 +1051,8 @@ $TCA['pages'] = array(
                'config' => array(
                        'showitem' => 'TSconfig;LLL:EXT:cms/locallang_tca.xml:pages.TSconfig_formlabel',
                        'canNotCollapse' => 1,
-               ),
-       ),
+               )
+       )
 );
 
 
@@ -1048,7 +1085,7 @@ if (!t3lib_div::compat_version('4.2')) {
                        --div--;LLL:EXT:cms/locallang_tca.xml:pages.tabs.access,
                                starttime, endtime, fe_group, extendToSubpages,
                        --div--;LLL:EXT:cms/locallang_tca.xml:pages.tabs.options,
-                               TSconfig;;6;nowrap;4-4-4, storage_pid;;7, l18n_cfg,
+                               TSconfig;;6;nowrap;4-4-4, storage_pid;;7, l18n_cfg, be_layout;;8,
                        --div--;LLL:EXT:cms/locallang_tca.xml:pages.tabs.extended,
        ');
                // adding doktype 2 ("Advanced")
@@ -1062,7 +1099,7 @@ if (!t3lib_div::compat_version('4.2')) {
                        --div--;LLL:EXT:cms/locallang_tca.xml:pages.tabs.access,
                                starttime, endtime, fe_login_mode, fe_group, extendToSubpages,
                        --div--;LLL:EXT:cms/locallang_tca.xml:pages.tabs.options,
-                               TSconfig;;6;nowrap;6-6-6, storage_pid;;7, l18n_cfg, module, content_from_pid,
+                               TSconfig;;6;nowrap;6-6-6, storage_pid;;7, l18n_cfg, module, content_from_pid, be_layout;;8,
                        --div--;LLL:EXT:cms/locallang_tca.xml:pages.tabs.extended,
        ');
 }
diff --git a/typo3/sysext/cms/class.tx_cms_be_layout.php b/typo3/sysext/cms/class.tx_cms_be_layout.php
new file mode 100644 (file)
index 0000000..9a73979
--- /dev/null
@@ -0,0 +1,178 @@
+<?php
+
+class tx_cms_be_layout {
+
+       /**
+        * @mficzel
+        * @todo add items
+        * @param unknown_type $params
+        */
+       function colPosListItemProcFunc( &$params ){
+               $params['items'] = $this->addColPosListLayoutItems ( $params['row']['pid'], $params['items'] );
+       }
+
+       function addColPosListLayoutItems ( $pageId, $items ){
+               $layout = $this->getSelectedBackendLayout($pageId);
+               if( $layout && $layout['__items'] ){
+                       $items = $layout['__items'];
+               }
+               return $items;
+       }
+
+       function getColPosListItemsParsed ( $id ){
+
+               $tsConfig = t3lib_BEfunc::getModTSconfig( $id ,'TCEFORM.tt_content.colPos');
+               $tcaConfig = $GLOBALS['TCA']['tt_content']['columns']['colPos']['config'];
+
+               $TCEForms = t3lib_div::makeInstance( 't3lib_TCEForms' );
+               $tcaItems = $tcaConfig['items'];
+               $tcaItems = $TCEForms->addItems($tcaItems, $tsConfig['properties']['addItems.']);
+               if (isset($tcaConfig['itemsProcFunc']) && $tcaConfig['itemsProcFunc']) {
+                       $tcaItems = $this->addColPosListLayoutItems ($id , $tcaItems ) ;
+               }
+               foreach ( t3lib_div::trimExplode(',',$tsConfig['properties']['removeItems'],1) as $removeId ){
+                       unset( $tcaItems[$removeId] );
+               }
+               return $tcaItems;
+       }
+
+       function getSelectedBackendLayout($id) {
+               $rootline = t3lib_BEfunc::BEgetRootLine($id);
+               $backendLayoutUid = null;
+               for ($i = count($rootline); $i > 0; $i--) {
+                       $res = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,be_layout,be_layout_next_level','pages','uid='.intval($rootline[$i]['uid']));
+                       $page = $res[0];
+                       if (intval($page['be_layout_next_level']) > 0 && $page['uid'] != $id ) {
+                               $backendLayoutUid = intval($page['be_layout_next_level']);
+                               break;
+                       } else if (intval($page['be_layout']) > 0) {
+                               $backendLayoutUid = intval($page['be_layout']);
+                               break;
+                       }
+               }
+               $backendLayout = null;
+               if ($backendLayoutUid){
+                       $res = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*','be_layouts','uid='.$backendLayoutUid  );
+                       if ($res){
+                               $backendLayout = $res[0];
+                               $parser = t3lib_div::makeInstance('t3lib_TSparser');
+                               $parser->parse($backendLayout['config']);
+                               $backendLayout['__config'] = $parser->setup;
+                               $backendLayout['__items'] = array();
+                               $backendLayout['__colPosList'] = array();
+
+                                       // create items and colPosList
+                               if ( $backendLayout['__config']['be_layout.'] && $backendLayout['__config']['be_layout.']['rows.'] ){
+                                       foreach( $backendLayout['__config']['be_layout.']['rows.']  as  $row){
+                                               if ( true && count($row['columns.'])){
+                                                       foreach ( $row['columns.'] as $column) {
+                                                               if ( true ){
+                                                                       $backendLayout['__items'][] = array (
+                                                                               $column['name'],
+                                                                               $column['colPos'],
+                                                                               null
+                                                                       );
+                                                                       $backendLayout['__colPosList'][] =  $column['colPos'];
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+
+                       }
+               }
+               return $backendLayout;
+       }
+
+}
+
+?>
+<?php
+
+class tx_cms_be_layout {
+
+       /**
+        * @mficzel
+        * @todo add items
+        * @param unknown_type $params
+        */
+       function colPosListItemProcFunc( &$params ){
+               $params['items'] = $this->addColPosListLayoutItems ( $params['row']['pid'], $params['items'] );
+       }
+
+       function addColPosListLayoutItems ( $pageId, $items ){
+               $layout = $this->getSelectedBackendLayout($pageId);
+               if( $layout && $layout['__items'] ){
+                       $items = $layout['__items'];
+               }
+               return $items;
+       }
+
+       function getColPosListItemsParsed ( $id ){
+
+               $tsConfig = t3lib_BEfunc::getModTSconfig( $id ,'TCEFORM.tt_content.colPos');
+               $tcaConfig = $GLOBALS['TCA']['tt_content']['columns']['colPos']['config'];
+
+               $TCEForms = t3lib_div::makeInstance( 't3lib_TCEForms' );
+               $tcaItems = $tcaConfig['items'];
+               $tcaItems = $TCEForms->addItems($tcaItems, $tsConfig['properties']['addItems.']);
+               if (isset($tcaConfig['itemsProcFunc']) && $tcaConfig['itemsProcFunc']) {
+                       $tcaItems = $this->addColPosListLayoutItems ($id , $tcaItems ) ;
+               }
+               foreach ( t3lib_div::trimExplode(',',$tsConfig['properties']['removeItems'],1) as $removeId ){
+                       unset( $tcaItems[$removeId] );
+               }
+               return $tcaItems;
+       }
+
+       function getSelectedBackendLayout($id) {
+               $rootline = t3lib_BEfunc::BEgetRootLine($id);
+               $backendLayoutUid = null;
+               for ($i = count($rootline); $i > 0; $i--) {
+                       $res = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,be_layout,be_layout_next_level','pages','uid='.intval($rootline[$i]['uid']));
+                       $page = $res[0];
+                       if (intval($page['be_layout_next_level']) > 0 && $page['uid'] != $id ) {
+                               $backendLayoutUid = intval($page['be_layout_next_level']);
+                               break;
+                       } else if (intval($page['be_layout']) > 0) {
+                               $backendLayoutUid = intval($page['be_layout']);
+                               break;
+                       }
+               }
+               $backendLayout = null;
+               if ($backendLayoutUid){
+                       $res = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*','be_layouts','uid='.$backendLayoutUid  );
+                       if ($res){
+                               $backendLayout = $res[0];
+                               $parser = t3lib_div::makeInstance('t3lib_TSparser');
+                               $parser->parse($backendLayout['config']);
+                               $backendLayout['__config'] = $parser->setup;
+                               $backendLayout['__items'] = array();
+                               $backendLayout['__colPosList'] = array();
+
+                                       // create items and colPosList
+                               if ( $backendLayout['__config']['be_layout.'] && $backendLayout['__config']['be_layout.']['rows.'] ){
+                                       foreach( $backendLayout['__config']['be_layout.']['rows.']  as  $row){
+                                               if ( true && count($row['columns.'])){
+                                                       foreach ( $row['columns.'] as $column) {
+                                                               if ( true ){
+                                                                       $backendLayout['__items'][] = array (
+                                                                               $column['name'],
+                                                                               $column['colPos'],
+                                                                               null
+                                                                       );
+                                                                       $backendLayout['__colPosList'][] =  $column['colPos'];
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+
+                       }
+               }
+               return $backendLayout;
+       }
+
+}
+
+?>
index 0e1ff84..89e01d4 100755 (executable)
@@ -24,7 +24,7 @@ if (TYPO3_MODE == 'BE') {
 
 
        // Add allowed records to pages:
-       t3lib_extMgm::allowTableOnStandardPages('pages_language_overlay,tt_content,sys_template,sys_domain');
+t3lib_extMgm::allowTableOnStandardPages('pages_language_overlay,tt_content,sys_template,sys_domain,be_layouts');
 
 
 // ******************************************************************
@@ -256,4 +256,29 @@ $TCA['sys_template'] = array (
 );
 
 
+// ******************************************************************
+// layouts
+// ******************************************************************
+$TCA['be_layouts'] = array (
+       'ctrl' => array (
+               'title'     => 'LLL:EXT:cms/locallang_tca.xml:be_layouts',
+               'label'     => 'title',
+               'tstamp'    => 'tstamp',
+               'crdate'    => 'crdate',
+               'cruser_id' => 'cruser_id',
+               'versioningWS' => TRUE,
+               'origUid' => 't3_origuid',
+               'sortby' => 'sorting',
+               'delete' => 'deleted',
+               'enablecolumns' => array (
+                       'disabled' => 'hidden',
+               ),
+               'dynamicConfigFile' => t3lib_extMgm::extPath($_EXTKEY).'tbl_cms.php',
+               'iconfile' => 'be_layout.gif',
+               'selicon_field' => 'icon',
+               'selicon_field_path' => 'uploads/media',
+               'thumbnail' => 'resources',
+       )
+);
+
 ?>
\ No newline at end of file
index 254ac91..5208243 100755 (executable)
@@ -436,3 +436,34 @@ CREATE TABLE tt_content (
   KEY parent (pid,sorting),
   KEY language (l18n_parent,sys_language_uid)
 );
+
+#
+# Table structure for table 'be_layouts'
+#
+CREATE TABLE be_layouts (
+  uid int(11) NOT NULL auto_increment,
+  pid int(11) DEFAULT '0' NOT NULL,
+  t3ver_oid int(11) DEFAULT '0' NOT NULL,
+  t3ver_id int(11) DEFAULT '0' NOT NULL,
+  t3ver_wsid int(11) DEFAULT '0' NOT NULL,
+  t3ver_label varchar(255) DEFAULT '' NOT NULL,
+  t3ver_state tinyint(4) DEFAULT '0' NOT NULL,
+  t3ver_stage tinyint(4) DEFAULT '0' NOT NULL,
+  t3ver_count int(11) DEFAULT '0' NOT NULL,
+  t3ver_tstamp int(11) DEFAULT '0' NOT NULL,
+  t3ver_move_id int(11) DEFAULT '0' NOT NULL,
+  t3_origuid int(11) DEFAULT '0' NOT NULL,
+  tstamp int(11) unsigned DEFAULT '0' NOT NULL,
+  crdate int(11) unsigned DEFAULT '0' NOT NULL,
+  cruser_id int(11) unsigned DEFAULT '0' NOT NULL,
+  hidden tinyint(4) unsigned DEFAULT '0' NOT NULL,
+  deleted tinyint(4) DEFAULT '0' NOT NULL,
+  sorting int(11) unsigned DEFAULT '0' NOT NULL,
+  title varchar(255) DEFAULT '' NOT NULL,
+  description text NOT NULL,
+  config text NOT NULL,
+  icon text NOT NULL,
+  PRIMARY KEY (uid),
+  KEY parent (pid),
+  KEY t3ver_oid (t3ver_oid,t3ver_wsid)
+);
index 564bf76..73dc17f 100755 (executable)
@@ -138,6 +138,7 @@ class tx_cms_layout extends recordList {
                'showInfo' => 1,                                        // Boolean: Display info-marks or not
                'showCommands' => 1,                            // Boolean: Display up/down arrows and edit icons for tt_content records
                'single' => 1,                                          // Boolean: If set, the content of column(s) $this->tt_contentConfig['showSingleCol'] is shown in the total width of the page
+               'showAsGrid' => 0,                                      // Boolean: If set, the content of columns is shown in grid
                'showSingleCol' => 0,                           // The column(s) to show if single mode (under each other)
                'languageCols' => 0,
                'languageMode' => 0,
@@ -392,6 +393,29 @@ class tx_cms_layout extends recordList {
        }
 
        /**
+        * Returns the backend layout which should be used for this page.
+        *
+        * @param integer $id: Uid of the current
+        * @return integer The Uid of the backend layout record
+        */
+       function getSelectedBackendLayoutUid($id) {
+               $rootline = t3lib_BEfunc::BEgetRootLine($id);
+               $backendLayoutUid = null;
+               for ($i = count($rootline); $i > 0; $i--) {
+                       $res = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,be_layout,be_layout_next_level','pages','uid='.intval($rootline[$i]['uid']));
+                       $page = $res[0];
+                       if (intval($page['be_layout_next_level']) > 0 && $page['uid'] != $id ) {
+                               $backendLayoutUid = intval($page['be_layout_next_level']);
+                               break;
+                       } else if (intval($page['be_layout']) > 0) {
+                               $backendLayoutUid = intval($page['be_layout']);
+                               break;
+                       }
+               }
+               return $backendLayoutUid;
+       }
+
+       /**
         * Renders Content Elements from the tt_content table from page id
         *
         * @param       integer         Page id
@@ -493,41 +517,109 @@ class tx_cms_layout extends recordList {
 
                                                // Add new-icon link, header:
                                        $newP = $this->newContentElementOnClick($id,$key,$lP);
-                                       $head[$key].= $this->tt_content_drawColHeader(t3lib_BEfunc::getProcessedValue('tt_content','colPos',$key), ($this->doEdit&&count($rowArr)?'&edit[tt_content]['.$editUidList.']=edit'.$pageTitleParamForAltDoc:''), $newP);
+                                       $colTitle = t3lib_BEfunc::getProcessedValue('tt_content','colPos',$key);
+                                       /**
+                                        * @mficzel
+                                        * @todo get complete title from tca inclusive ts config manipulations by user func and tsConfig
+                                        */
+                                       $tcaItems = t3lib_div::callUserFunction( 'EXT:cms/class.tx_cms_be_layout.php:tx_cms_be_layout->getColPosListItemsParsed' , $id, $this );
+                                       foreach( $tcaItems as $item) {
+                                               if ( $item[1] == $key) {
+                                                       $colTitle =  $GLOBALS['LANG']->sL( $item[0] );
+                                               }
+                                       }
+                                       $head[$key].= $this->tt_content_drawColHeader($colTitle , ($this->doEdit&&count($rowArr)?'&edit[tt_content]['.$editUidList.']=edit'.$pageTitleParamForAltDoc:''), $newP);
                                        $editUidList = '';
                                }
 
                                        // For EACH column, fit the rendered content into a table cell:
                                $out='';
-                               foreach($cList as $k => $key)   {
-                                       if (!$k)        {
-                                               $out.= '
-                                                       <td><img src="clear.gif" width="'.$lMarg.'" height="1" alt="" /></td>';
-                                       } else {
-                                               $out.= '
-                                                       <td><img src="clear.gif" width="4" height="1" alt="" /></td>
-                                                       <td bgcolor="#cfcfcf"><img src="clear.gif" width="1" height="1" alt="" /></td>
-                                                       <td><img src="clear.gif" width="4" height="1" alt="" /></td>';
+
+                               if ($this->tt_contentConfig['showAsGrid']) {
+                                       $backendLayoutUid = $this->getSelectedBackendLayoutUid($id);
+                                       $backendLayoutRecord = t3lib_BEfunc::getRecord('be_layouts', intval($backendLayoutUid));
+                                       if (empty($backendLayoutRecord['config'])) {
+                                               // TODO: show a message that no layout was found
+                                               $this->tt_contentConfig['showAsGrid'] = 0;
                                        }
-                                       $out.= '
-                                                       <td class="t3-page-column t3-page-column-' . $key . '">' . $head[$key] . $content[$key] . '</td>';
-
-                                               // Storing content for use if languageMode is set:
-                                       if ($this->tt_contentConfig['languageMode'])    {
-                                               $languageColumn[$key][$lP] = $head[$key].$content[$key];
-                                               if (!$this->defLangBinding)     {
-                                                       $languageColumn[$key][$lP].='<br /><br />'.$this->newLanguageButton($this->getNonTranslatedTTcontentUids($defLanguageCount[$key],$id,$lP),$lP);
+                               }
+
+                               if (!$this->tt_contentConfig['showAsGrid']) {
+                                       foreach($cList as $k => $key)   {
+
+                                               if (!$k)        {
+                                                       $out.= '
+                                                               <td><img src="clear.gif" width="'.$lMarg.'" height="1" alt="" /></td>';
+                                               } else {
+                                                       $out.= '
+                                                               <td><img src="clear.gif" width="4" height="1" alt="" /></td>
+                                                               <td bgcolor="#cfcfcf"><img src="clear.gif" width="1" height="1" alt="" /></td>
+                                                               <td><img src="clear.gif" width="4" height="1" alt="" /></td>';
+                                               }
+                                               $out.= '
+                                                               <td class="t3-page-column t3-page-column-' . $key . '">' . $head[$key] . $content[$key] . '</td>';
+
+                                                       // Storing content for use if languageMode is set:
+                                               if ($this->tt_contentConfig['languageMode'])    {
+                                                       $languageColumn[$key][$lP] = $head[$key].$content[$key];
+                                                       if (!$this->defLangBinding)     {
+                                                               $languageColumn[$key][$lP].='<br /><br />'.$this->newLanguageButton($this->getNonTranslatedTTcontentUids($defLanguageCount[$key],$id,$lP),$lP);
+                                                       }
                                                }
                                        }
-                               }
 
-                                       // Wrap the cells into a table row:
-                               $out = '
+                                               // Wrap the cells into a table row:
+                                       $out = '
                                        <table border="0" cellpadding="0" cellspacing="0" class="t3-page-columns">
                                                <tr>'.$out.'
                                                </tr>
                                        </table>';
 
+                               } else {
+                                               // GRID VIEW:
+
+                                               // initialize TS parser to parse config to array
+                                       $parser = t3lib_div::makeInstance('t3lib_TSparser');
+                                       $parser->parse($backendLayoutRecord['config']);
+
+                                       $grid .= '<div class="t3-gridContainer"><table border="0" cellspacing="1" cellpadding="4" width="80%" height="100%" class="t3-page-columns t3-gridTable">';
+
+                                               // add colgroups
+                                       $colCount = intval($parser->setup['be_layout.']['colCount']);
+                                       $grid .= '<colgroup>';
+                                       for ($i = 0; $i < $colCount; $i++) {
+                                               $grid .= '<col style="width:'.(100/$colCount).'%"></col>';
+                                       }
+                                       $grid .= '</colgroup>';
+
+                                               // cycle through rows
+                                       if(count($parser->setup['be_layout.']['rows.'])) {
+                                               foreach ($parser->setup['be_layout.']['rows.'] as $rowConfig) {
+                                                       $grid .= '<tr>';
+
+                                                               // and colummns
+                                                       if(count($rowConfig['columns.'])) {
+                                                               foreach ($rowConfig['columns.'] as $columnConfig) {
+
+                                                                               // which tt_content colPos should be displayed inside this cell
+                                                                       $columnKey = intval($columnConfig['colPos']);
+
+                                                                               // render the grid cell
+                                                                       $grid .= '<td valign="top"'.
+                                                                               (isset($columnConfig['colspan']) ? ' colspan="'.$columnConfig['colspan'].'"' : '').
+                                                                               (isset($columnConfig['rowspan']) ? ' rowspan="'.$columnConfig['rowspan'].'"' : '').
+                                                                               ' class="t3-gridCell t3-page-column t3-page-column-' . $columnKey .
+                                                                               (isset($columnConfig['colspan']) ? ' t3-gridCell-width'.$columnConfig['colspan'] : '') .
+                                                                               (isset($columnConfig['rowspan']) ? ' t3-gridCell-height'.$columnConfig['rowspan'] : '').'">';
+                                                                       $grid .= $head[$columnKey] . $content[$columnKey] . '</td>';
+                                                               }
+                                                       }
+                                                       $grid .= '</tr>';
+                                               }
+                                       }
+                                       $out .= $grid.'</table></div>';
+                               }
+
                                        // CSH:
                                $out.= t3lib_BEfunc::cshItem($this->descrTable,'columns_multi',$GLOBALS['BACK_PATH']);
                        }
@@ -2480,7 +2572,7 @@ class tx_cms_layout extends recordList {
 
                                $lines[]='';
                                $lines[]=array($LANG->getLL('pI_hitsPeriod').':',t3lib_BEfunc::date($rrow2[0]).' - '.t3lib_BEfunc::date($rrow2[1]).' ('.t3lib_BEfunc::calcAge($rrow2[1]-$rrow2[0],$this->agePrefixes).')');
-                               $lines[]=array($LANG->getLL('pI_hitsTotal').':',$rrow[0]);
+                               $lines[]=array($LANG->getLL('pI_hitsTotal').':',$rrow2[0]);
 
 
                                        // Last 10 days
index 903a98f..16bfedd 100755 (executable)
@@ -322,7 +322,8 @@ class SC_db_layout {
                                0 => $LANG->getLL('m_function_0'),
                                1 => $LANG->getLL('m_function_1'),
                                2 => $LANG->getLL('m_function_2'),
-                               3 => $LANG->getLL('pageInformation')
+                               3 => $LANG->getLL('pageInformation'),
+                               4 => $LANG->getLL('gridView')
                        ),
                        'language' => array(
                                0 => $LANG->getLL('m_default')
@@ -535,9 +536,16 @@ class SC_db_layout {
                                // Find columns
                        $modTSconfig_SHARED = t3lib_BEfunc::getModTSconfig($this->id,'mod.SHARED');             // SHARED page-TSconfig settings.
                        $this->colPosList = strcmp(trim($this->modTSconfig['properties']['tt_content.']['colPos_list']),'') ? trim($this->modTSconfig['properties']['tt_content.']['colPos_list']) : $modTSconfig_SHARED['properties']['colPos_list'];
-                       $this->colPosList = strcmp($this->colPosList,'')?$this->colPosList:'1,0,2,3';
-                       $this->colPosList = implode(',',array_unique(t3lib_div::intExplode(',',$this->colPosList)));            // Removing duplicates, if any
-
+                       if( !strcmp($this->colPosList,'') ) {
+                               $beLayout = t3lib_div::callUserFunction( 'EXT:cms/class.tx_cms_be_layout.php:tx_cms_be_layout->getSelectedBackendLayout' , $this->id, $this );
+                               if(count($beLayout['__colPosList'])) {
+                                       $this->colPosList = implode(',', $beLayout['__colPosList']);
+                               }
+                       }
+                       if( !strcmp($this->colPosList, '') ){
+                               $this->colPosList = '1,0,2,3';
+                       }
+                       $this->colPosList = implode(',', array_unique(t3lib_div::intExplode(',',$this->colPosList)));           // Removing duplicates, if any
 
                                // Render the primary module content:
                        if ($this->MOD_SETTINGS['function']==0) {
@@ -1026,10 +1034,16 @@ class SC_db_layout {
                                                $dblist->tt_contentConfig['showInfo'] = 1;              // Boolean: Display info-marks or not
                                                $dblist->tt_contentConfig['single'] = 0;                // Boolean: If set, the content of column(s) $this->tt_contentConfig['showSingleCol'] is shown in the total width of the page
 
+                                               if ($this->MOD_SETTINGS['function'] == 4) {
+                                                               // grid view
+                                                       $dblist->tt_contentConfig['showAsGrid'] = 1;
+                                               }
+
                                                        // Setting up the tt_content columns to show:
                                                if (is_array($TCA['tt_content']['columns']['colPos']['config']['items']))       {
                                                        $colList = array();
-                                                       foreach($TCA['tt_content']['columns']['colPos']['config']['items'] as $temp)    {
+                                                       $tcaItems = t3lib_div::callUserFunction( 'EXT:cms/class.tx_cms_be_layout.php:tx_cms_be_layout->getColPosListItemsParsed' , $this->id, $this );
+                                                       foreach($tcaItems as $temp)     {
                                                                $colList[] = $temp[1];
                                                        }
                                                } else {        // ... should be impossible that colPos has no array. But this is the fallback should it make any sense:
index 07632e0..6181611 100755 (executable)
@@ -57,6 +57,7 @@
                        <label index="m_function_0">QuickEdit</label>
                        <label index="m_function_1">Columns</label>
                        <label index="m_function_2">Languages</label>
+                       <label index="gridView">Grid-View</label>
                        <label index="m_tt_board_0">List topics only</label>
                        <label index="m_tt_board_expand">Expand Threads</label>
                        <label index="m_tt_address_0">Short List</label>
diff --git a/typo3/sysext/cms/layout/res/grideditor.css b/typo3/sysext/cms/layout/res/grideditor.css
new file mode 100644 (file)
index 0000000..44b276d
--- /dev/null
@@ -0,0 +1,268 @@
+* {
+       padding: 0;
+       margin: 0;
+       position: relative;
+}
+
+body, html {
+       height: 100%;
+       width: 100%;
+}
+
+div.typo3-noDoc {
+       width: 98%;
+       height: 90%;
+       margin: 0;
+       padding: 5px;
+}
+
+table#outer_container td, table#editor td {
+       vertical-align: middle;
+}
+
+table#outer_container td.editor_cell {
+       height: 100%;
+}
+
+table.editor {
+       border-right: 1px gray dashed;
+       border-bottom: 1px gray dashed;
+}
+
+table.editor td {
+       border-top: 1px gray dashed;
+       border-left: 1px gray dashed;
+       text-align: center;
+       z-index: 2000;
+       background-color: white;
+       min-height: 100px;
+}
+
+div#editor {
+       height: 100%;
+}
+
+div.cell_container {
+       width: 60px;
+       height: 60px;
+       position: relative;
+       left: 50%;
+       margin-left: -30px;
+       opacity: 0.3;
+}
+
+div.cell_container:hover {
+       opacity: 1;
+}
+
+.link_expand_right, .link_shrink_left, .link_expand_down, .link_shrink_up, .link_editor {
+       display: block;
+       position: absolute;
+       width: 14px;
+       height: 32px;
+       z-index: 1100;
+}
+
+.link_expand_down, .link_shrink_up {
+       width: 32px;
+       height: 14px;
+}
+
+.link_expand_right {
+       background-image: url(t3grid-editor-right-inactive.png);
+       left: 46px;
+       top: 14px;
+}
+
+.link_expand_right:hover {
+       background-image: url(t3grid-editor-right.png);
+}
+
+
+.link_shrink_left {
+       background-image: url(t3grid-editor-left-inactive.png);
+       left: 0px;
+       top: 14px;
+}
+
+.link_shrink_left:hover {
+       background-image: url(t3grid-editor-left.png);
+}
+
+.link_expand_down {
+       background-image: url(t3grid-editor-down-inactive.png);
+       left: 14px;
+       top: 46px;
+}
+
+.link_expand_down:hover {
+       background-image: url(t3grid-editor-down.png);
+}
+
+.link_shrink_up {
+       background-image: url(t3grid-editor-up-inactive.png);
+       left: 14px;
+       top: 0px;
+}
+
+.link_shrink_up:hover {
+       background-image: url(t3grid-editor-up.png);
+}
+
+.link_editor {
+       background-image: url(t3grid-edit-inactive.png);
+       width: 32px;
+       height: 32px;
+       left: 14px;
+       top: 14px;
+}
+
+.link_editor:hover {
+       background-image: url(t3grid-edit.png);
+}
+
+.question {
+       background-image: url(t3grid-layer-icon-help.png) !important;
+}
+
+.save {
+       background-image: url(t3grid-layer-icon-save.png) !important;
+}
+
+.cancel {
+       background-image: url(t3grid-layer-icon-close.png) !important;
+}
+* {
+       padding: 0;
+       margin: 0;
+       position: relative;
+}
+
+body, html {
+       height: 100%;
+       width: 100%;
+}
+
+div.typo3-noDoc {
+       width: 98%;
+       height: 90%;
+       margin: 0;
+       padding: 5px;
+}
+
+table#outer_container td, table#editor td {
+       vertical-align: middle;
+}
+
+table#outer_container td.editor_cell {
+       height: 100%;
+}
+
+table.editor {
+       border-right: 1px gray dashed;
+       border-bottom: 1px gray dashed;
+}
+
+table.editor td {
+       border-top: 1px gray dashed;
+       border-left: 1px gray dashed;
+       text-align: center;
+       z-index: 2000;
+       background-color: white;
+       min-height: 100px;
+}
+
+div#editor {
+       height: 100%;
+}
+
+div.cell_container {
+       width: 60px;
+       height: 60px;
+       position: relative;
+       left: 50%;
+       margin-left: -30px;
+       opacity: 0.3;
+}
+
+div.cell_container:hover {
+       opacity: 1;
+}
+
+.link_expand_right, .link_shrink_left, .link_expand_down, .link_shrink_up, .link_editor {
+       display: block;
+       position: absolute;
+       width: 14px;
+       height: 32px;
+       z-index: 1100;
+}
+
+.link_expand_down, .link_shrink_up {
+       width: 32px;
+       height: 14px;
+}
+
+.link_expand_right {
+       background-image: url(t3grid-editor-right-inactive.png);
+       left: 46px;
+       top: 14px;
+}
+
+.link_expand_right:hover {
+       background-image: url(t3grid-editor-right.png);
+}
+
+
+.link_shrink_left {
+       background-image: url(t3grid-editor-left-inactive.png);
+       left: 0px;
+       top: 14px;
+}
+
+.link_shrink_left:hover {
+       background-image: url(t3grid-editor-left.png);
+}
+
+.link_expand_down {
+       background-image: url(t3grid-editor-down-inactive.png);
+       left: 14px;
+       top: 46px;
+}
+
+.link_expand_down:hover {
+       background-image: url(t3grid-editor-down.png);
+}
+
+.link_shrink_up {
+       background-image: url(t3grid-editor-up-inactive.png);
+       left: 14px;
+       top: 0px;
+}
+
+.link_shrink_up:hover {
+       background-image: url(t3grid-editor-up.png);
+}
+
+.link_editor {
+       background-image: url(t3grid-edit-inactive.png);
+       width: 32px;
+       height: 32px;
+       left: 14px;
+       top: 14px;
+}
+
+.link_editor:hover {
+       background-image: url(t3grid-edit.png);
+}
+
+.question {
+       background-image: url(t3grid-layer-icon-help.png) !important;
+}
+
+.save {
+       background-image: url(t3grid-layer-icon-save.png) !important;
+}
+
+.cancel {
+       background-image: url(t3grid-layer-icon-close.png) !important;
+}
diff --git a/typo3/sysext/cms/layout/res/grideditor.js b/typo3/sysext/cms/layout/res/grideditor.js
new file mode 100644 (file)
index 0000000..2cf60be
--- /dev/null
@@ -0,0 +1,1136 @@
+/**
+ * A JavaScript object to handle, edit, draw and export a grid. The grid is basically
+ * a table with some colspan and rowspan. Each cell can additionally hold a name and
+ * column.
+ *
+ * @author Thomas Hempel <thomas@typo3.org>
+ */
+Ext.namespace('TYPO3.Backend.t3Grid');
+
+TYPO3.Backend.t3Grid = Ext.extend(Ext.Component, {
+       /*
+       colCount: 0,
+       rowCount: 0,
+       data: [],
+       nameLabel: '',
+       columnLabel: '',
+       */
+       constructor: function(config) {
+
+               config = Ext.apply({
+                       colCount: config.colCount,
+                       rowCount: config.rowCount,
+                       data: config.data,
+                       nameLabel: config.nameLabel,
+                       columnLabel: config.columnLabel,
+                       targetElement: config.targetElement
+               }, config);
+
+               TYPO3.Backend.t3Grid.superclass.constructor.call(this, config);
+       },
+
+       /**
+        * Adds a row below the grid
+        */
+       addRow: function() {
+               var newRow = [];
+               for (var i = 0; i < this.colCount; i++) {
+                       newRow[i] =  {spanned:false,rowspan:1,colspan:1};
+               }
+               this.data.push(newRow);
+               this.rowCount++;
+       },
+
+       /**
+        * Removes the last row of the grid and adjusts all cells that might be effected
+        * by that change. (Removing colspans)
+        *
+        * @returns void
+        */
+       removeRow: function() {
+               if (this.rowCount <= 1) return false;
+               var newData = [];
+               for (var rowIndex = 0; rowIndex < this.rowCount-1; rowIndex++) {
+                       newData.push(this.data[rowIndex]);
+               }
+
+                       // fix rowspan in former last row
+               for (var colIndex = 0; colIndex < this.colCount; colIndex++) {
+                       if (this.data[this.rowCount-1][colIndex].spanned == true) {
+                               this.findUpperCellWidthRowspanAndDecreaseByOne(colIndex,this.rowCount-1);
+                       }
+               }
+
+               this.data = newData;
+               this.rowCount--;
+       },
+
+       /**
+        * Takes a cell and looks above it if there are any cells that have colspans that
+        * spanns into the given cell. This is used when a row was removed from the grid
+        * to make sure that no cell with wrong colspans exists in the grid.
+        *
+        * @param col integer
+        * @param row integer
+        * @return void
+        */
+       findUpperCellWidthRowspanAndDecreaseByOne: function(col,row) {
+               var upperCell = this.getCell(col, row-1);
+               if (!upperCell) return false;
+
+               if (upperCell.spanned == true) {
+                       this.findUpperCellWidthRowspanAndDecreaseByOne(col, row-1);
+               } else {
+                       if (upperCell.rowspan > 1) {
+                               this.removeRowspan(col, row-1);
+                       }
+               }
+       },
+
+       /**
+        * Removes the outermost right column from the grid.
+        *
+        * @return void
+        */
+       removeColumn: function() {
+               if (this.colCount <= 1) return false;
+               var newData = [];
+
+               for (var rowIndex = 0; rowIndex < this.rowCount; rowIndex++) {
+                       var newRow = [];
+                       for (colIndex = 0; colIndex < this.colCount-1; colIndex++) {
+                               newRow.push(this.data[rowIndex][colIndex]);
+                       }
+                       if (this.data[rowIndex][this.colCount-1].spanned == true) {
+                               this.findLeftCellWidthColspanAndDecreaseByOne(this.colCount-1, rowIndex);
+                       }
+                       newData.push(newRow);
+               }
+
+               this.data = newData;
+               this.colCount--;
+       },
+
+       /**
+        * Checks if there are any cells on the left side of a given cell with a
+        * rowspan that spans over the given cell.
+        *
+        * @param col integer
+        * @param row integer
+        * @return void
+        */
+       findLeftCellWidthColspanAndDecreaseByOne: function(col,row) {
+               var leftCell = this.getCell(col-1, row);
+               if (!leftCell) return false;
+
+               if (leftCell.spanned == true) {
+                       this.findLeftCellWidthColspanAndDecreaseByOne(col-1, row);
+               } else {
+                       if (leftCell.colspan > 1) {
+                               this.removeColspan(col-1, row);
+                       }
+               }
+       },
+
+       /**
+        * Adds a column at the right side of the grid.
+        *
+        * @return void
+        */
+       addColumn: function() {
+               for (var rowIndex = 0; rowIndex < this.rowCount; rowIndex++) {
+                       this.data[rowIndex].push({spanned:false,rowspan:1,colspan:1,name:this.colCount+'x'+rowIndex});
+               }
+               this.colCount++;
+       },
+
+       /**
+        * Draws the grid as table into a given container.
+        * It also adds all needed links and bindings to the cells to make it editable.
+        *
+        * @return void
+        */
+       drawTable: function() {
+               var domHelper = Ext.DomHelper;
+               var newTable = {tag:'table',children:[],id:'base',border:'0',width:'100%',height:'100%','class':'editor',cellspacing:'0',cellpadding:'0'};
+
+               var colgroups = {tag:'colgroup',children:[]};
+               for (var col = 0; col < this.colCount; col++) {
+                       colgroups.children.push({tag:'col',style:'width:'+parseInt(100/this.colCount)+'%'});
+               }
+               newTable.children.push(colgroups);
+
+               for (var row = 0; row < this.rowCount; row++) {
+                       var rowData = this.data[row];
+                       if (rowData.length == 0) continue;
+
+                       var rowSpec = {tag: 'tr', children:[]};
+
+                       for (var col = 0; col < this.colCount; col++) {
+                               var cell = this.data[row][col];
+                               if (cell.spanned == true) {
+                                       continue;
+                               }
+
+
+                               var cellHtml = '<div class="cell_container"><a class="link_editor" id="e_'+col+'_'+row+'" href="#"><!-- --></a>';
+                               if (this.cellCanSpanRight(col, row)) cellHtml += '<a href="#" id="r_'+col+'_'+row+'" class="link_expand_right"><!-- --></a>';
+                               if (this.cellCanShrinkLeft(col, row)) cellHtml += '<a href="#" id="l_'+col+'_'+row+'" class="link_shrink_left"><!-- --></a>';
+                               if (this.cellCanSpanDown(col, row)) cellHtml += '<a href="#" id="d_'+col+'_'+row+'" class="link_expand_down"><!-- --></a>';
+                               if (this.cellCanShrinkUp(col, row)) cellHtml += '<a href="#" id="u_'+col+'_'+row+'" class="link_shrink_up"><!-- --></a>';
+                               cellHtml += '</div>';
+
+                               cellHtml += '<div class="cell_data">Name: '+(cell.name ? cell.name : 'not set')+'<br />Column: '+((parseInt(cell.column) === false) ? 'not set' : cell.column)+'</div>';
+
+                                       // create cells
+                               var child = {
+                                       tag: 'td',
+                                       height: parseInt(100/this.rowCount)*cell.rowspan+'%',
+                                       width: parseInt(100/this.colCount)*cell.colspan+'%',
+                                       html: cellHtml
+                               };
+                               if (cell.colspan > 1) {
+                                       child.colspan = cell.colspan;
+                               }
+                               if (cell.rowspan > 1) {
+                                       child.rowspan = cell.rowspan;
+                               }
+                               rowSpec.children.push(child);
+                       }
+
+                       newTable.children.push(rowSpec);
+
+               }
+
+               domHelper.overwrite(Ext.Element.get(this.targetElement), newTable);
+               this.bindLinks();
+       },
+
+       /**
+        * Sets the name of a certain grid element.
+        *
+        * @param newName string
+        * @param col integer
+        * @param row integer
+        *
+        * @return boolean
+        */
+       setName: function(newName, col, row) {
+               var cell = this.getCell(col, row);
+               if (!cell) return false;
+               cell.name = newName;
+               return true;
+       },
+
+       /**
+        * Sets the column field for a certain grid element. This is NOT the column of the
+        * element itself.
+        *
+        * @param newColumn integer
+        * @param col integer
+        * @param row integer
+        *
+        * @return boolean
+        */
+       setColumn: function(newColumn, col, row) {
+               var cell = this.getCell(col, row);
+               if (!cell) return false;
+               cell.column = newColumn;
+               return true;
+       },
+
+       /**
+        * Searches for all a tags with certain classes and binds some actions to them.
+        *
+        * @return void
+        */
+       bindLinks: function() {
+               for (var row = 0; row < this.rowCount; row++) {
+                       for (var col = 0; col < this.colCount; col++) {
+                               // span right
+                               var el = Ext.Element.get('r_'+col+'_'+row);
+                               if (el) {
+                                       el.addListener('click', function(e, sender, params) {
+                                               this.addColspan(params.colIndex, params.rowIndex);
+                                               this.drawTable();
+                                       }, this, {stopEvent:true, colIndex:col, rowIndex:row});
+                               }
+
+                               // reduce to left
+                               var el = Ext.Element.get('l_'+col+'_'+row);
+                               if (el) {
+                                       el.addListener('click', function(e, sender, params) {
+                                               this.removeColspan(params.colIndex, params.rowIndex);
+                                               this.drawTable();
+                                       }, this, {stopEvent:true, colIndex:col, rowIndex:row});
+                               }
+
+                               // span down
+                               var el = Ext.Element.get('d_'+col+'_'+row);
+                               if (el) {
+                                       el.addListener('click', function(e, sender, params) {
+                                               this.addRowspan(params.colIndex, params.rowIndex);
+                                               this.drawTable();
+                                       }, this, {stopEvent:true, colIndex:col, rowIndex:row});
+                               }
+
+                               // reduce up
+                               var el = Ext.Element.get('u_'+col+'_'+row);
+                               if (el) {
+                                       el.addListener('click', function(e, sender, params) {
+                                               this.removeRowspan(params.colIndex, params.rowIndex);
+                                               this.drawTable();
+                                       }, this, {stopEvent:true, colIndex:col, rowIndex:row});
+                               }
+
+                               // edit
+                               var el = Ext.Element.get('e_'+col+'_'+row);
+                               if (el) {
+                                       el.addListener('click', function(e, sender, params) {
+                                               this.showOptions(sender, params.colIndex, params.rowIndex);
+                                       }, this, {stopEvent:true, colIndex:col, rowIndex:row});
+                               }
+                       }
+               }
+       },
+
+       /**
+        * Creates an ExtJs Window with two input fields and shows it. On save, the data
+        * is written into the grid element.
+        *
+        * @param sender DOM-object (the link)
+        * @param col integer
+        * @param row integer
+        */
+       showOptions: function(sender, col, row) {
+               var win;
+               sender = Ext.get('base');
+               var cell = this.getCell(col, row);
+               if (!cell) return false;
+
+               if(!win){
+                       var fieldName = new Ext.form.TextField({
+                               fieldLabel: TYPO3.lang.name,
+               name: 'name',
+               width: 200,
+               value: cell.name,
+                               tabIndex: 1
+                       });
+
+                       var fieldColumn = new Ext.form.NumberField({
+                               fieldLabel: TYPO3.lang.column,
+                       name: 'column',
+                       width: 50,
+                       value: cell.column,
+                               tabIndex: 2
+                       });
+
+
+                       win = new Ext.Window({
+                               layout: 'fit',
+                               title: TYPO3.lang.title,
+                               width: '50%',
+                               modal: true,
+                               closable: true,
+                               resizable: false,
+
+                               items: [{
+                                       xtype: 'fieldset',
+                                       autoHeight: true,
+                                       autoWidth: true,
+                                       labelWidth: 100,
+                                       border: false,
+
+                                       items: [fieldName, fieldColumn]
+                               }],
+
+                               buttons: [{
+                                       iconCls:'save',
+                                       text: TYPO3.lang.save,
+                                       handler: function(fieldName, fieldColumn, col, row) {
+                                               t3Grid.setName(fieldName.getValue(), col, row);
+                                               t3Grid.setColumn(fieldColumn.getValue(), col, row);
+                                               win.close();
+                                               t3Grid.drawTable();
+                                       }.createDelegate(this, [fieldName, fieldColumn, col, row])
+                               }]
+                       });
+               }
+               win.show(this);
+       },
+
+       /**
+        * Returns a cell element from the grid.
+        *
+        * @param col integer
+        * @param row integer
+        * return Object
+        */
+       getCell: function(col, row) {
+               if (col > this.colCount-1) return false;
+               if (row > this.rowCount-1) return false;
+               return this.data[row][col];
+       },
+
+       /**
+        * Checks wether a cell can span to the right or not. A cell can span to the right
+        * if it is not in the last column and if there is no cell beside it that is
+        * already overspanned by some other cell.
+        *
+        * @param col integer
+        * @param row integer
+        *
+        * @return boolean
+        */
+       cellCanSpanRight: function(col, row) {
+               if (col == this.colCount-1) {
+                       return false;
+               }
+
+               var cell = this.getCell(col, row);
+               if (cell.rowspan > 1) {
+                       for (var rowIndex = row; rowIndex < row+cell.rowspan; rowIndex++) {
+                               var checkCell = this.getCell(col+cell.colspan, rowIndex);
+                               if (!checkCell || checkCell.spanned == true || checkCell.colspan > 1 || checkCell.rowspan > 1) {
+                                       return false;
+                               }
+                       }
+               } else {
+                       var checkCell = this.getCell(col+cell.colspan, row);
+                       if (!checkCell || cell.spanned == true || checkCell.spanned == true || checkCell.colspan > 1 || checkCell.rowspan > 1) {
+                               return false;
+                       }
+               }
+
+               return true;
+       },
+
+       /**
+        * Checks wether a cell can span down or not.
+        *
+        * @param col integer
+        * @param row integer
+        *
+        * @return boolean
+        */
+       cellCanSpanDown: function(col, row) {
+               if (row == this.rowCount-1) {
+                       return false;
+               }
+
+               var cell = this.getCell(col, row);
+               if (cell.colspan > 1) {
+                       // we have to check all cells on the right side for the complete colspan
+                       for (var colIndex = col; colIndex < col+cell.colspan; colIndex++) {
+                               var checkCell = this.getCell(colIndex, row+cell.rowspan);
+                               if (!checkCell || checkCell.spanned == true || checkCell.colspan > 1 || checkCell.rowspan > 1) {
+                                       return false;
+                               }
+                       }
+               } else {
+                       var checkCell = this.getCell(col, row+cell.rowspan);
+                       if (!checkCell || cell.spanned == true || checkCell.spanned == true || checkCell.colspan > 1 || checkCell.rowspan > 1) {
+                               return false;
+                       }
+               }
+
+               return true;
+       },
+
+       /**
+        * Checks if a cell can shrink to the left. It can shrink if the colspan of the
+        * cell is bigger than 1.
+        *
+        * @param col integr
+        * @param row integer
+        *
+        * @return boolean
+        */
+       cellCanShrinkLeft: function(col, row) {
+               return (this.data[row][col].colspan > 1);
+       },
+
+       /**
+        * Returns if a cell can shrink up. This is the case if a cell has at least
+        * a rowspan of 2.
+        *
+        * @param col integr
+        * @param row integer
+        *
+        * @return boolean
+        */
+       cellCanShrinkUp: function(col, row) {
+               return (this.data[row][col].rowspan > 1);
+       },
+
+       /**
+        * Adds a colspan to a grid element.
+        *
+        * @param col integr
+        * @param row integer
+        */
+       addColspan: function(col, row) {
+               var cell = this.getCell(col, row);
+               if (!cell || !this.cellCanSpanRight(col, row)) return false;
+
+               for (var rowIndex = row; rowIndex < row+cell.rowspan; rowIndex++) {
+                       this.data[rowIndex][col+cell.colspan].spanned = true;
+               }
+               cell.colspan += 1;
+       },
+
+       /**
+        * Adds a rowspan to grid element.
+        *
+        * @param col integr
+        * @param row integer
+        *
+        * @return void
+        */
+       addRowspan: function(col, row) {
+               var cell = this.getCell(col, row);
+               if (!cell || !this.cellCanSpanDown(col, row)) return false;
+
+               for (var colIndex = col; colIndex < col+cell.colspan; colIndex++) {
+                       this.data[row+cell.rowspan][colIndex].spanned = true;
+               }
+               cell.rowspan += 1;
+       },
+
+       /**
+        * Removes a colspan from a grid element.
+        *
+        * @param col integr
+        * @param row integer
+        *
+        * @return void
+        */
+       removeColspan: function(col, row) {
+               var cell = this.getCell(col, row);
+               if (!cell || !this.cellCanShrinkLeft(col, row)) return false;
+
+               cell.colspan -= 1;
+               for (var rowIndex = row; rowIndex < row+cell.rowspan; rowIndex++) {
+                       this.data[rowIndex][col+cell.colspan].spanned = false;
+               }
+       },
+
+       /**
+        * Removes a rowspan from a grid element.
+        *
+        * @param col integr
+        * @param row integer
+        *
+        * @return void
+        */
+       removeRowspan: function(col, row) {
+               var cell = this.getCell(col, row);
+               if (!cell || !this.cellCanShrinkUp(col, row)) return false;
+
+               cell.rowspan -= 1;
+               for (var colIndex = col; colIndex < col+cell.colspan; colIndex++) {
+                       this.data[row+cell.rowspan][colIndex].spanned = false;
+               }
+       },
+
+       /**
+        * Exports the current grid to a TypoScript notation that can be read by the
+        * page module and is human readable.
+        *
+        * @return string
+        */
+       export2LayoutRecord: function() {
+               var result = "be_layout {\n\tcolCount = "+this.colCount+"\n\trowCount = "+this.rowCount+ "\n\trows {\n";
+               for (var row = 0; row < this.rowCount; row++) {
+                       result += "\t\t"+(row+1)+" {\n";
+                       result += "\t\t\tcolumns {\n";
+                       colIndex = 0;
+                       for (var col = 0; col < this.colCount; col++) {
+                               var cell = this.getCell(col, row);
+                               if (cell && !cell.spanned) {
+                                       colIndex++;
+                                       result += "\t\t\t\t"+(colIndex)+" {\n";
+                                       result += "\t\t\t\t\tname = "+((!cell.name) ? col+"x"+row : cell.name)+"\n";
+                                       if (cell.colspan > 1) result += "\t\t\t\t\tcolspan = "+cell.colspan+"\n";
+                                       if (cell.rowspan > 1) result += "\t\t\t\t\trowspan = "+cell.rowspan+"\n";
+                                       if (typeof(cell.column) === 'number') result += "\t\t\t\t\tcolPos = "+cell.column+"\n";
+                                       result += "\t\t\t\t}\n";
+                               }
+
+                       }
+                       result += "\t\t\t}\n";
+                       result += "\t\t}\n";
+               }
+
+               result += "\t}\n}\n";
+               return result;
+       }
+});
+/**
+ * A JavaScript object to handle, edit, draw and export a grid. The grid is basically
+ * a table with some colspan and rowspan. Each cell can additionally hold a name and
+ * column.
+ *
+ * @author Thomas Hempel <thomas@typo3.org>
+ */
+Ext.namespace('TYPO3.Backend.t3Grid');
+
+TYPO3.Backend.t3Grid = Ext.extend(Ext.Component, {
+       /*
+       colCount: 0,
+       rowCount: 0,
+       data: [],
+       nameLabel: '',
+       columnLabel: '',
+       */
+       constructor: function(config) {
+
+               config = Ext.apply({
+                       colCount: config.colCount,
+                       rowCount: config.rowCount,
+                       data: config.data,
+                       nameLabel: config.nameLabel,
+                       columnLabel: config.columnLabel,
+                       targetElement: config.targetElement
+               }, config);
+
+               TYPO3.Backend.t3Grid.superclass.constructor.call(this, config);
+       },
+
+       /**
+        * Adds a row below the grid
+        */
+       addRow: function() {
+               var newRow = [];
+               for (var i = 0; i < this.colCount; i++) {
+                       newRow[i] =  {spanned:false,rowspan:1,colspan:1};
+               }
+               this.data.push(newRow);
+               this.rowCount++;
+       },
+
+       /**
+        * Removes the last row of the grid and adjusts all cells that might be effected
+        * by that change. (Removing colspans)
+        *
+        * @returns void
+        */
+       removeRow: function() {
+               if (this.rowCount <= 1) return false;
+               var newData = [];
+               for (var rowIndex = 0; rowIndex < this.rowCount-1; rowIndex++) {
+                       newData.push(this.data[rowIndex]);
+               }
+
+                       // fix rowspan in former last row
+               for (var colIndex = 0; colIndex < this.colCount; colIndex++) {
+                       if (this.data[this.rowCount-1][colIndex].spanned == true) {
+                               this.findUpperCellWidthRowspanAndDecreaseByOne(colIndex,this.rowCount-1);
+                       }
+               }
+
+               this.data = newData;
+               this.rowCount--;
+       },
+
+       /**
+        * Takes a cell and looks above it if there are any cells that have colspans that
+        * spanns into the given cell. This is used when a row was removed from the grid
+        * to make sure that no cell with wrong colspans exists in the grid.
+        *
+        * @param col integer
+        * @param row integer
+        * @return void
+        */
+       findUpperCellWidthRowspanAndDecreaseByOne: function(col,row) {
+               var upperCell = this.getCell(col, row-1);
+               if (!upperCell) return false;
+
+               if (upperCell.spanned == true) {
+                       this.findUpperCellWidthRowspanAndDecreaseByOne(col, row-1);
+               } else {
+                       if (upperCell.rowspan > 1) {
+                               this.removeRowspan(col, row-1);
+                       }
+               }
+       },
+
+       /**
+        * Removes the outermost right column from the grid.
+        *
+        * @return void
+        */
+       removeColumn: function() {
+               if (this.colCount <= 1) return false;
+               var newData = [];
+
+               for (var rowIndex = 0; rowIndex < this.rowCount; rowIndex++) {
+                       var newRow = [];
+                       for (colIndex = 0; colIndex < this.colCount-1; colIndex++) {
+                               newRow.push(this.data[rowIndex][colIndex]);
+                       }
+                       if (this.data[rowIndex][this.colCount-1].spanned == true) {
+                               this.findLeftCellWidthColspanAndDecreaseByOne(this.colCount-1, rowIndex);
+                       }
+                       newData.push(newRow);
+               }
+
+               this.data = newData;
+               this.colCount--;
+       },
+
+       /**
+        * Checks if there are any cells on the left side of a given cell with a
+        * rowspan that spans over the given cell.
+        *
+        * @param col integer
+        * @param row integer
+        * @return void
+        */
+       findLeftCellWidthColspanAndDecreaseByOne: function(col,row) {
+               var leftCell = this.getCell(col-1, row);
+               if (!leftCell) return false;
+
+               if (leftCell.spanned == true) {
+                       this.findLeftCellWidthColspanAndDecreaseByOne(col-1, row);
+               } else {
+                       if (leftCell.colspan > 1) {
+                               this.removeColspan(col-1, row);
+                       }
+               }
+       },
+
+       /**
+        * Adds a column at the right side of the grid.
+        *
+        * @return void
+        */
+       addColumn: function() {
+               for (var rowIndex = 0; rowIndex < this.rowCount; rowIndex++) {
+                       this.data[rowIndex].push({spanned:false,rowspan:1,colspan:1,name:this.colCount+'x'+rowIndex});
+               }
+               this.colCount++;
+       },
+
+       /**
+        * Draws the grid as table into a given container.
+        * It also adds all needed links and bindings to the cells to make it editable.
+        *
+        * @return void
+        */
+       drawTable: function() {
+               var domHelper = Ext.DomHelper;
+               var newTable = {tag:'table',children:[],id:'base',border:'0',width:'100%',height:'100%','class':'editor',cellspacing:'0',cellpadding:'0'};
+
+               var colgroups = {tag:'colgroup',children:[]};
+               for (var col = 0; col < this.colCount; col++) {
+                       colgroups.children.push({tag:'col',style:'width:'+parseInt(100/this.colCount)+'%'});
+               }
+               newTable.children.push(colgroups);
+
+               for (var row = 0; row < this.rowCount; row++) {
+                       var rowData = this.data[row];
+                       if (rowData.length == 0) continue;
+
+                       var rowSpec = {tag: 'tr', children:[]};
+
+                       for (var col = 0; col < this.colCount; col++) {
+                               var cell = this.data[row][col];
+                               if (cell.spanned == true) {
+                                       continue;
+                               }
+
+
+                               var cellHtml = '<div class="cell_container"><a class="link_editor" id="e_'+col+'_'+row+'" href="#"><!-- --></a>';
+                               if (this.cellCanSpanRight(col, row)) cellHtml += '<a href="#" id="r_'+col+'_'+row+'" class="link_expand_right"><!-- --></a>';
+                               if (this.cellCanShrinkLeft(col, row)) cellHtml += '<a href="#" id="l_'+col+'_'+row+'" class="link_shrink_left"><!-- --></a>';
+                               if (this.cellCanSpanDown(col, row)) cellHtml += '<a href="#" id="d_'+col+'_'+row+'" class="link_expand_down"><!-- --></a>';
+                               if (this.cellCanShrinkUp(col, row)) cellHtml += '<a href="#" id="u_'+col+'_'+row+'" class="link_shrink_up"><!-- --></a>';
+                               cellHtml += '</div>';
+
+                               cellHtml += '<div class="cell_data">Name: '+(cell.name ? cell.name : 'not set')+'<br />Column: '+((parseInt(cell.column) === false) ? 'not set' : cell.column)+'</div>';
+
+                                       // create cells
+                               var child = {
+                                       tag: 'td',
+                                       height: parseInt(100/this.rowCount)*cell.rowspan+'%',
+                                       width: parseInt(100/this.colCount)*cell.colspan+'%',
+                                       html: cellHtml
+                               };
+                               if (cell.colspan > 1) {
+                                       child.colspan = cell.colspan;
+                               }
+                               if (cell.rowspan > 1) {
+                                       child.rowspan = cell.rowspan;
+                               }
+                               rowSpec.children.push(child);
+                       }
+
+                       newTable.children.push(rowSpec);
+
+               }
+
+               domHelper.overwrite(Ext.Element.get(this.targetElement), newTable);
+               this.bindLinks();
+       },
+
+       /**
+        * Sets the name of a certain grid element.
+        *
+        * @param newName string
+        * @param col integer
+        * @param row integer
+        *
+        * @return boolean
+        */
+       setName: function(newName, col, row) {
+               var cell = this.getCell(col, row);
+               if (!cell) return false;
+               cell.name = newName;
+               return true;
+       },
+
+       /**
+        * Sets the column field for a certain grid element. This is NOT the column of the
+        * element itself.
+        *
+        * @param newColumn integer
+        * @param col integer
+        * @param row integer
+        *
+        * @return boolean
+        */
+       setColumn: function(newColumn, col, row) {
+               var cell = this.getCell(col, row);
+               if (!cell) return false;
+               cell.column = newColumn;
+               return true;
+       },
+
+       /**
+        * Searches for all a tags with certain classes and binds some actions to them.
+        *
+        * @return void
+        */
+       bindLinks: function() {
+               for (var row = 0; row < this.rowCount; row++) {
+                       for (var col = 0; col < this.colCount; col++) {
+                               // span right
+                               var el = Ext.Element.get('r_'+col+'_'+row);
+                               if (el) {
+                                       el.addListener('click', function(e, sender, params) {
+                                               this.addColspan(params.colIndex, params.rowIndex);
+                                               this.drawTable();
+                                       }, this, {stopEvent:true, colIndex:col, rowIndex:row});
+                               }
+
+                               // reduce to left
+                               var el = Ext.Element.get('l_'+col+'_'+row);
+                               if (el) {
+                                       el.addListener('click', function(e, sender, params) {
+                                               this.removeColspan(params.colIndex, params.rowIndex);
+                                               this.drawTable();
+                                       }, this, {stopEvent:true, colIndex:col, rowIndex:row});
+                               }
+
+                               // span down
+                               var el = Ext.Element.get('d_'+col+'_'+row);
+                               if (el) {
+                                       el.addListener('click', function(e, sender, params) {
+                                               this.addRowspan(params.colIndex, params.rowIndex);
+                                               this.drawTable();
+                                       }, this, {stopEvent:true, colIndex:col, rowIndex:row});
+                               }
+
+                               // reduce up
+                               var el = Ext.Element.get('u_'+col+'_'+row);
+                               if (el) {
+                                       el.addListener('click', function(e, sender, params) {
+                                               this.removeRowspan(params.colIndex, params.rowIndex);
+                                               this.drawTable();
+                                       }, this, {stopEvent:true, colIndex:col, rowIndex:row});
+                               }
+
+                               // edit
+                               var el = Ext.Element.get('e_'+col+'_'+row);
+                               if (el) {
+                                       el.addListener('click', function(e, sender, params) {
+                                               this.showOptions(sender, params.colIndex, params.rowIndex);
+                                       }, this, {stopEvent:true, colIndex:col, rowIndex:row});
+                               }
+                       }
+               }
+       },
+
+       /**
+        * Creates an ExtJs Window with two input fields and shows it. On save, the data
+        * is written into the grid element.
+        *
+        * @param sender DOM-object (the link)
+        * @param col integer
+        * @param row integer
+        */
+       showOptions: function(sender, col, row) {
+               var win;
+               sender = Ext.get('base');
+               var cell = this.getCell(col, row);
+               if (!cell) return false;
+
+               if(!win){
+                       var fieldName = new Ext.form.TextField({
+                               fieldLabel: TYPO3.lang.name,
+               name: 'name',
+               width: 200,
+               value: cell.name,
+                               tabIndex: 1
+                       });
+
+                       var fieldColumn = new Ext.form.NumberField({
+                               fieldLabel: TYPO3.lang.column,
+                       name: 'column',
+                       width: 50,
+                       value: cell.column,
+                               tabIndex: 2
+                       });
+
+
+                       win = new Ext.Window({
+                               layout: 'fit',
+                               title: TYPO3.lang.title,
+                               width: '50%',
+                               modal: true,
+                               closable: true,
+                               resizable: false,
+
+                               items: [{
+                                       xtype: 'fieldset',
+                                       autoHeight: true,
+                                       autoWidth: true,
+                                       labelWidth: 100,
+                                       border: false,
+
+                                       items: [fieldName, fieldColumn]
+                               }],
+
+                               buttons: [{
+                                       iconCls:'save',
+                                       text: TYPO3.lang.save,
+                                       handler: function(fieldName, fieldColumn, col, row) {
+                                               t3Grid.setName(fieldName.getValue(), col, row);
+                                               t3Grid.setColumn(fieldColumn.getValue(), col, row);
+                                               win.close();
+                                               t3Grid.drawTable();
+                                       }.createDelegate(this, [fieldName, fieldColumn, col, row])
+                               }]
+                       });
+               }
+               win.show(this);
+       },
+
+       /**
+        * Returns a cell element from the grid.
+        *
+        * @param col integer
+        * @param row integer
+        * return Object
+        */
+       getCell: function(col, row) {
+               if (col > this.colCount-1) return false;
+               if (row > this.rowCount-1) return false;
+               return this.data[row][col];
+       },
+
+       /**
+        * Checks wether a cell can span to the right or not. A cell can span to the right
+        * if it is not in the last column and if there is no cell beside it that is
+        * already overspanned by some other cell.
+        *
+        * @param col integer
+        * @param row integer
+        *
+        * @return boolean
+        */
+       cellCanSpanRight: function(col, row) {
+               if (col == this.colCount-1) {
+                       return false;
+               }
+
+               var cell = this.getCell(col, row);
+               if (cell.rowspan > 1) {
+                       for (var rowIndex = row; rowIndex < row+cell.rowspan; rowIndex++) {
+                               var checkCell = this.getCell(col+cell.colspan, rowIndex);
+                               if (!checkCell || checkCell.spanned == true || checkCell.colspan > 1 || checkCell.rowspan > 1) {
+                                       return false;
+                               }
+                       }
+               } else {
+                       var checkCell = this.getCell(col+cell.colspan, row);
+                       if (!checkCell || cell.spanned == true || checkCell.spanned == true || checkCell.colspan > 1 || checkCell.rowspan > 1) {
+                               return false;
+                       }
+               }
+
+               return true;
+       },
+
+       /**
+        * Checks wether a cell can span down or not.
+        *
+        * @param col integer
+        * @param row integer
+        *
+        * @return boolean
+        */
+       cellCanSpanDown: function(col, row) {
+               if (row == this.rowCount-1) {
+                       return false;
+               }
+
+               var cell = this.getCell(col, row);
+               if (cell.colspan > 1) {
+                       // we have to check all cells on the right side for the complete colspan
+                       for (var colIndex = col; colIndex < col+cell.colspan; colIndex++) {
+                               var checkCell = this.getCell(colIndex, row+cell.rowspan);
+                               if (!checkCell || checkCell.spanned == true || checkCell.colspan > 1 || checkCell.rowspan > 1) {
+                                       return false;
+                               }
+                       }
+               } else {
+                       var checkCell = this.getCell(col, row+cell.rowspan);
+                       if (!checkCell || cell.spanned == true || checkCell.spanned == true || checkCell.colspan > 1 || checkCell.rowspan > 1) {
+                               return false;
+                       }
+               }
+
+               return true;
+       },
+
+       /**
+        * Checks if a cell can shrink to the left. It can shrink if the colspan of the
+        * cell is bigger than 1.
+        *
+        * @param col integr
+        * @param row integer
+        *
+        * @return boolean
+        */
+       cellCanShrinkLeft: function(col, row) {
+               return (this.data[row][col].colspan > 1);
+       },
+
+       /**
+        * Returns if a cell can shrink up. This is the case if a cell has at least
+        * a rowspan of 2.
+        *
+        * @param col integr
+        * @param row integer
+        *
+        * @return boolean
+        */
+       cellCanShrinkUp: function(col, row) {
+               return (this.data[row][col].rowspan > 1);
+       },
+
+       /**
+        * Adds a colspan to a grid element.
+        *
+        * @param col integr
+        * @param row integer
+        */
+       addColspan: function(col, row) {
+               var cell = this.getCell(col, row);
+               if (!cell || !this.cellCanSpanRight(col, row)) return false;
+
+               for (var rowIndex = row; rowIndex < row+cell.rowspan; rowIndex++) {
+                       this.data[rowIndex][col+cell.colspan].spanned = true;
+               }
+               cell.colspan += 1;
+       },
+
+       /**
+        * Adds a rowspan to grid element.
+        *
+        * @param col integr
+        * @param row integer
+        *
+        * @return void
+        */
+       addRowspan: function(col, row) {
+               var cell = this.getCell(col, row);
+               if (!cell || !this.cellCanSpanDown(col, row)) return false;
+
+               for (var colIndex = col; colIndex < col+cell.colspan; colIndex++) {
+                       this.data[row+cell.rowspan][colIndex].spanned = true;
+               }
+               cell.rowspan += 1;
+       },
+
+       /**
+        * Removes a colspan from a grid element.
+        *
+        * @param col integr
+        * @param row integer
+        *
+        * @return void
+        */
+       removeColspan: function(col, row) {
+               var cell = this.getCell(col, row);
+               if (!cell || !this.cellCanShrinkLeft(col, row)) return false;
+
+               cell.colspan -= 1;
+               for (var rowIndex = row; rowIndex < row+cell.rowspan; rowIndex++) {
+                       this.data[rowIndex][col+cell.colspan].spanned = false;
+               }
+       },
+
+       /**
+        * Removes a rowspan from a grid element.
+        *
+        * @param col integr
+        * @param row integer
+        *
+        * @return void
+        */
+       removeRowspan: function(col, row) {
+               var cell = this.getCell(col, row);
+               if (!cell || !this.cellCanShrinkUp(col, row)) return false;
+
+               cell.rowspan -= 1;
+               for (var colIndex = col; colIndex < col+cell.colspan; colIndex++) {
+                       this.data[row+cell.rowspan][colIndex].spanned = false;
+               }
+       },
+
+       /**
+        * Exports the current grid to a TypoScript notation that can be read by the
+        * page module and is human readable.
+        *
+        * @return string
+        */
+       export2LayoutRecord: function() {
+               var result = "be_layout {\n\tcolCount = "+this.colCount+"\n\trowCount = "+this.rowCount+ "\n\trows {\n";
+               for (var row = 0; row < this.rowCount; row++) {
+                       result += "\t\t"+(row+1)+" {\n";
+                       result += "\t\t\tcolumns {\n";
+                       colIndex = 0;
+                       for (var col = 0; col < this.colCount; col++) {
+                               var cell = this.getCell(col, row);
+                               if (cell && !cell.spanned) {
+                                       colIndex++;
+                                       result += "\t\t\t\t"+(colIndex)+" {\n";
+                                       result += "\t\t\t\t\tname = "+((!cell.name) ? col+"x"+row : cell.name)+"\n";
+                                       if (cell.colspan > 1) result += "\t\t\t\t\tcolspan = "+cell.colspan+"\n";
+                                       if (cell.rowspan > 1) result += "\t\t\t\t\trowspan = "+cell.rowspan+"\n";
+                                       if (typeof(cell.column) === 'number') result += "\t\t\t\t\tcolPos = "+cell.column+"\n";
+                                       result += "\t\t\t\t}\n";
+                               }
+
+                       }
+                       result += "\t\t\t}\n";
+                       result += "\t\t}\n";
+               }
+
+               result += "\t}\n}\n";
+               return result;
+       }
+});
diff --git a/typo3/sysext/cms/layout/res/t3grid-edit-inactive-1.png b/typo3/sysext/cms/layout/res/t3grid-edit-inactive-1.png
new file mode 100644 (file)
index 0000000..348127d
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-edit-inactive-1.png differ
diff --git a/typo3/sysext/cms/layout/res/t3grid-edit-inactive.png b/typo3/sysext/cms/layout/res/t3grid-edit-inactive.png
new file mode 100644 (file)
index 0000000..348127d
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-edit-inactive.png differ
diff --git a/typo3/sysext/cms/layout/res/t3grid-edit.png b/typo3/sysext/cms/layout/res/t3grid-edit.png
new file mode 100644 (file)
index 0000000..9327b4b
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-edit.png differ
diff --git a/typo3/sysext/cms/layout/res/t3grid-editor-down-inactive.png b/typo3/sysext/cms/layout/res/t3grid-editor-down-inactive.png
new file mode 100644 (file)
index 0000000..4bfded5
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-editor-down-inactive.png differ
diff --git a/typo3/sysext/cms/layout/res/t3grid-editor-down.png b/typo3/sysext/cms/layout/res/t3grid-editor-down.png
new file mode 100644 (file)
index 0000000..04649fa
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-editor-down.png differ
diff --git a/typo3/sysext/cms/layout/res/t3grid-editor-left-inactive.png b/typo3/sysext/cms/layout/res/t3grid-editor-left-inactive.png
new file mode 100644 (file)
index 0000000..5f44586
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-editor-left-inactive.png differ
diff --git a/typo3/sysext/cms/layout/res/t3grid-editor-left.png b/typo3/sysext/cms/layout/res/t3grid-editor-left.png
new file mode 100644 (file)
index 0000000..eb6fef8
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-editor-left.png differ
diff --git a/typo3/sysext/cms/layout/res/t3grid-editor-right-inactive.png b/typo3/sysext/cms/layout/res/t3grid-editor-right-inactive.png
new file mode 100644 (file)
index 0000000..27b6b3f
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-editor-right-inactive.png differ
diff --git a/typo3/sysext/cms/layout/res/t3grid-editor-right.png b/typo3/sysext/cms/layout/res/t3grid-editor-right.png
new file mode 100644 (file)
index 0000000..4aaf56b
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-editor-right.png differ
diff --git a/typo3/sysext/cms/layout/res/t3grid-editor-up-inactive.png b/typo3/sysext/cms/layout/res/t3grid-editor-up-inactive.png
new file mode 100644 (file)
index 0000000..200f2b5
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-editor-up-inactive.png differ
diff --git a/typo3/sysext/cms/layout/res/t3grid-editor-up.png b/typo3/sysext/cms/layout/res/t3grid-editor-up.png
new file mode 100644 (file)
index 0000000..a835a6b
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-editor-up.png differ
diff --git a/typo3/sysext/cms/layout/res/t3grid-layer-icon-close.png b/typo3/sysext/cms/layout/res/t3grid-layer-icon-close.png
new file mode 100644 (file)
index 0000000..70a2adf
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-layer-icon-close.png differ
diff --git a/typo3/sysext/cms/layout/res/t3grid-layer-icon-help.png b/typo3/sysext/cms/layout/res/t3grid-layer-icon-help.png
new file mode 100644 (file)
index 0000000..fc69dd8
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-layer-icon-help.png differ
diff --git a/typo3/sysext/cms/layout/res/t3grid-layer-icon-save.png b/typo3/sysext/cms/layout/res/t3grid-layer-icon-save.png
new file mode 100644 (file)
index 0000000..65e6bec
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-layer-icon-save.png differ
diff --git a/typo3/sysext/cms/layout/res/t3grid-tabledown.png b/typo3/sysext/cms/layout/res/t3grid-tabledown.png
new file mode 100644 (file)
index 0000000..b2dc72a
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-tabledown.png differ
diff --git a/typo3/sysext/cms/layout/res/t3grid-tableleft.png b/typo3/sysext/cms/layout/res/t3grid-tableleft.png
new file mode 100644 (file)
index 0000000..97e2394
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-tableleft.png differ
diff --git a/typo3/sysext/cms/layout/res/t3grid-tableright.png b/typo3/sysext/cms/layout/res/t3grid-tableright.png
new file mode 100644 (file)
index 0000000..173a1e4
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-tableright.png differ
diff --git a/typo3/sysext/cms/layout/res/t3grid-tableup.png b/typo3/sysext/cms/layout/res/t3grid-tableup.png
new file mode 100644 (file)
index 0000000..b5579d3
Binary files /dev/null and b/typo3/sysext/cms/layout/res/t3grid-tableup.png differ
diff --git a/typo3/sysext/cms/layout/res/typo3.pageModule.js b/typo3/sysext/cms/layout/res/typo3.pageModule.js
new file mode 100644 (file)
index 0000000..a1baaee
--- /dev/null
@@ -0,0 +1,714 @@
+
+var typo3pageModule = {
+       placeholder: null,
+       el: null,
+       idCache: {},
+       spinner: null,
+
+       /**
+        * Initialization
+        */
+       init: function(){
+               typo3pageModule.enableHighlighting();
+               typo3pageModule.registerDragAndDrop();
+       },
+
+       /**
+        * Each id param contains the id of the element and its language.
+        *
+        * Example: ttContent_4711_1
+        *
+        * To use them on the client side they need to be split. This method
+        * splits the string in to a id and language part and caches it.
+        */
+       _parseIdString: function(elementPart,idString){
+               if(typo3pageModule.idCache[idString] == null){
+                       idArray = idString.replace(elementPart,'').split('_');
+                       var res = {
+                               id: idArray[0],
+                               language: idArray[1]
+                       };
+
+                       typo3pageModule.idCache[idString] = res;
+               }
+
+               return typo3pageModule.idCache[idString];
+       },
+
+       /**
+        * Appends a loading spinner to the body.
+        *
+        */
+       showSpinner: function(){
+               typo3pageModule.spinner = new Element('div');
+               Ext.get(typo3pageModule.spinner).addClass('loadingSpinner').fadeIn({ endOpacity: .75, duration: 1});
+
+               Ext.select('body').appendChild(typo3pageModule.spinner);
+       },
+       /**
+        * Removes the loading spinner from the body.
+        */
+       hideSpinner: function(){
+               Ext.get(typo3pageModule.spinner).fadeOut({ endOpacity: 1.0, duration: 1}).remove();
+       },
+       /**
+        * This method is used as an event handler when the
+        * user hovers the headline of an content element.
+        */
+       enableContentHeader: function(e,t){
+               var parent = Ext.get(t).findParent('div.contentElement',null,true);
+               parent.child('div.ttContentHeader').show();
+               parent.addClass('active')
+       },
+
+       /**
+        * This method is used as event handler to hide the headline of
+        * an content element when the mouse of the user leaves the
+        * header of the content element.
+        */
+       disableContentHeader: function(e,t){
+               var parent = Ext.get(t).findParent('div.contentElement',null,true);
+               parent.child('div.ttContentHeader').hide();
+               parent.removeClass('active');
+
+       },
+
+       /**
+        * This method is used to bind the higlighting function "enableContentHeader"
+        * to the mouseenter event and the "disableContentHeader" to the mouselease event.
+        */
+       enableHighlighting: function(){
+               Ext.select('div.contentElement').on('mouseenter',typo3pageModule.enableContentHeader,typo3pageModule).on('mouseleave',typo3pageModule.disableContentHeader,typo3pageModule);
+       },
+
+       /**
+        * This method is used to unbind the higlighting function "enableContentHeader"
+        * from the mouseenter event and the "disableContentHeader" from the mouselease event.
+        */
+       disableHighlighting: function(){
+               Ext.select('div.contentElement').un('mouseenter',typo3pageModule.enableContentHeader,typo3pageModule).un('mouseleave',typo3pageModule.disableContentHeader,typo3pageModule);
+       },
+
+       /**
+        * This method is used to create the draggable items and the drop zones.
+        *
+        * The method additionaly add eventhandler methods and passes the to the
+        * draggable object.
+        */
+       registerDragAndDrop: function(){
+               var overrides = {
+                       // Called the instance the element is dragged.
+                       b4StartDrag:    typo3pageModule.b4StartDrag,
+                       onInvalidDrop:  typo3pageModule.invalidDrop,
+                       endDrag:                typo3pageModule.moveToDropTargetAndEnrich,
+                       onDragDrop:     typo3pageModule.handleElementDrop,
+                       onDragEnter:    typo3pageModule.enableDropZone,
+                       onDragOut:              typo3pageModule.disableDropZone
+               };
+
+               Ext.select('div.contentElement').each(function(el){
+                       var parsedId = typo3pageModule._parseIdString('ttContent_',el.dom.id);
+                       var dd = new Ext.dd.DD(el, 'contentelements_' + parsedId.language, { isTarget  : false});
+                   Ext.apply(dd, overrides);
+               });
+
+               Ext.select('div.columnDropZone').each(function(el){
+                       var parsedId = typo3pageModule._parseIdString('contentElementGroup_',el.parent().id);
+                       var target = new Ext.dd.DDTarget(el,'contentelements_' + parsedId.language);
+               });
+               Ext.select('div.contentElementDropZoneAfter').each(function(el){
+                       var parsedId = typo3pageModule._parseIdString('contentElementGroup_',el.parent().parent().id);
+                       var target = new Ext.dd.DDTarget(el,'contentelements_' + parsedId.language);
+               });
+       },
+
+       /**
+        * This method is used to higlight all drop zones for a certain
+        * language.
+        *
+        * @param int uid of the language
+        */
+       highlightLanguageDropZones: function(languageId){
+               Ext.select('div.dropZone.language_'+languageId).each(function(el){
+                       el.addClass('active');
+               });
+
+               Ext.select('table.typo3-page-ceFooter').each(
+                       function(el){   el.hide(); }
+               );
+       },
+
+       /**
+        * This method unhighlights all drop zones.
+        */
+       unhighlightAllDropZones: function(){
+               Ext.select('div.dropZone').each(function(el){
+                       el.removeClass('active');
+               });
+               Ext.select('table.typo3-page-ceFooter').each(
+                       function(el){   el.show(); }
+               );
+       },
+
+       /**
+        * When an element is dragged a few layers will be hidden
+        * and the z-index will be increased to bring the element
+        * to the front.
+        *
+        * @param Ext.Element element
+        */
+       reduceDraggedElement: function(element){
+               element.select('table.typo3-page-ceHeader').addClass('displayNone');
+           element.select('span.exampleContent').addClass('displayNone');
+           element.select('div.contentElementDropZoneAfter').addClass('displayNone');
+           element.addClass('onDrag');
+
+           var footerTable = element.select('table.typo3-page-ceFooter');
+           if(footerTable != null){
+               footerTable.addClass('displayNone');
+           }
+
+           var colSubHeader = element.select('tr.colSubHeader td');
+           if(colSubHeader != null){
+               colSubHeader.addClass('displayNone');
+           }
+
+           element.setStyle('z-index',999);
+       },
+
+       /**
+        * This method is used to display all hidden layers of a dragged
+        * element to bring it to the state before the dragging was started.
+        *
+        * @param Ext.Element element
+        */
+       enrichDraggedElement: function(element){
+               Ext.get(typo3pageModule.placeholder).remove();
+
+               element.select('table.typo3-page-ceHeader').removeClass('displayNone');
+           element.select('span.exampleContent').removeClass('displayNone');
+           element.select('div.contentElementDropZoneAfter').removeClass('displayNone');
+           element.setStyle('z-index',null);
+           element.removeClass('onDrag');
+           var footerTable = element.select('table.typo3-page-ceFooter');
+           if(footerTable != null){ footerTable.removeClass('displayNone'); }
+       },
+
+
+       /**
+        * Handler method for invalid drops.
+        */
+       invalidDrop: function() {
+           // Set a flag to invoke the animated repair
+           this.invalidDrop = true;
+       },
+
+       /**
+        * Handler method before dragging starts.
+        */
+       b4StartDrag: function(x,y) {
+               //disable the menubar highlighting during dragging
+           typo3pageModule.disableHighlighting();
+
+           // Cache the drag element
+           if (!this.el) { this.el = Ext.get(this.getEl()); }
+
+           //Cache the original XY Coordinates of the element, we'll use this later.
+           this.originalXY = this.el.getXY();
+
+           //move the draggable item to the mouse position
+           this.setDelta(0,0);
+
+           //highlight dropable targets
+       var parsedId = typo3pageModule._parseIdString('ttContent_',this.el.id);
+           typo3pageModule.highlightLanguageDropZones(parsedId.language);
+
+           //calculate width and height before reducing
+           var heightBefore = this.el.getHeight();
+           var widthBefore  = this.el.getWidth();
+
+           //make some layers of the draggable element invisible
+           typo3pageModule.reduceDraggedElement(this.el);
+
+           //caluclate height after reducing
+           var heightAfter = this.el.getHeight();
+           var widthAfter      = this.el.getWidth();
+
+           //create a placeholder for the dragged element
+           typo3pageModule.placeholder = new Element('div');
+           typo3pageModule.placeholder.setStyle({position: 'relative', height: heightBefore - heightAfter+ 'px', width: widthBefore - widthAfter+ 'px'});
+
+           //insert placeholder before the dragged element
+           Ext.get(typo3pageModule.placeholder).insertAfter(this.el.prev());
+        },
+        /**
+         * Handler method for "endDrag" event.
+         * Used to move the element to the prev. position when
+         * the element has been droppen on an invalid location.
+         */
+       moveToDropTargetAndEnrich: function() {
+           // Invoke the animation if the invalidDrop flag is set to true
+
+                if (this.invalidDrop === true) {
+               var animCfgObj = {
+                               easing   : null,
+                               duration : 0,
+                       scope    : this,
+                               callback : function() {
+                           // Remove the position attribute
+                           this.el.dom.style.position = '';
+                           this.el.dom.style.left = 0;
+                           this.el.dom.style.top = 0;
+                       }
+                  };
+
+               // Apply the repair animation
+               this.el.moveTo(this.originalXY[0], this.originalXY[1],animCfgObj);
+               typo3pageModule.enrichDraggedElement(this.el);
+               delete this.invalidDrop;
+           }
+           typo3pageModule.unhighlightAllDropZones();
+           typo3pageModule.enableHighlighting();
+       },
+
+       /**
+        * Event handler to process a valid drop.
+        */
+       handleElementDrop: function(evtObj, targetElId) {
+           // Wrap the drop target element with Ext.Element
+           var dropEl = Ext.get(targetElId);
+
+           // Perform the node move only if the drag element's
+           // parent is not the same as the drop target
+           if (this.el.dom.parentNode.id != targetElId) {
+               // Move the element
+               typo3pageModule.enrichDraggedElement(this.el);
+
+               var ttContentParsedId = typo3pageModule._parseIdString('ttContent_',this.el.id);
+               var rowParsedId = typo3pageModule._parseIdString('contentElementGroup_',dropEl.findParent('div.contentElementGroup').id);
+
+               if(dropEl.hasClass('contentElementDropZoneAfter')){
+                        var dropZoneAfterParsedId = typo3pageModule._parseIdString('contentElementDropZoneAfter_',dropEl.id);
+                        var idBehind = dropZoneAfterParsedId.id;
+                        this.el.insertAfter(dropEl.parent());
+               }
+               if(dropEl.hasClass('columnDropZone')){
+                               var idBehind  = pageId;
+                       this.el.insertAfter(dropEl);
+               }
+
+               var url = pageModuleMoveUrl.replace(/###MOVE_AFTER###/,idBehind).replace(/###MOVE_ITEM###/, ttContentParsedId.id ).replace(/###COL_POS###/,rowParsedId.id);
+
+               typo3pageModule.showSpinner();
+
+               Ext.Ajax.request({
+                  url: url,
+                  success: function(response, opts) {
+                               typo3pageModule.hideSpinner();
+                               window.location.reload();
+                       },
+                  failure: function(response, opts) { alert('server-side failure with status code ' + response.status); }
+               });
+
+               // Remove the drag invitation
+               this.onDragOut(evtObj, targetElId);
+
+               // Clear the styles
+               this.el.dom.style.position ='';
+               this.el.dom.style.top = '';
+               this.el.dom.style.left = '';
+           }
+           else {
+               // This was an invalid drop, initiate a repair
+               this.onInvalidDrop();
+           }
+       },
+
+       /**
+        * This method is called when an element has been drag over a valid drop zone.
+        * It highlights the drop zone to indicate to the user, that he can drop an item here.
+        *
+        * @param event
+        * @param string idString of the target element.
+        */
+       enableDropZone: function(evtObj, targetElId) {
+               if (targetElId != this.el.dom.parentNode.id) {
+                       var dropEl = Ext.get(targetElId);
+                       dropEl.addClass('validDrop');
+               }
+       },
+       /**
+        * This method is called when an element is removed from a dropZone.
+        *
+        * @param event
+        * @param string idString of the target element.
+        */
+       disableDropZone: function(evtObj, targetElId) {
+               if (targetElId != this.el.dom.parentNode.id) {
+
+                       var dropEl = Ext.get(targetElId);
+                       dropEl.removeClass('validDrop');
+               }
+       }
+}
+
+Event.observe(window, 'load', function() {
+       typo3pageModule.init();
+});
+
+var typo3pageModule = {
+       placeholder: null,
+       el: null,
+       idCache: {},
+       spinner: null,
+
+       /**
+        * Initialization
+        */
+       init: function(){
+               typo3pageModule.enableHighlighting();
+               typo3pageModule.registerDragAndDrop();
+       },
+
+       /**
+        * Each id param contains the id of the element and its language.
+        *
+        * Example: ttContent_4711_1
+        *
+        * To use them on the client side they need to be split. This method
+        * splits the string in to a id and language part and caches it.
+        */
+       _parseIdString: function(elementPart,idString){
+               if(typo3pageModule.idCache[idString] == null){
+                       idArray = idString.replace(elementPart,'').split('_');
+                       var res = {
+                               id: idArray[0],
+                               language: idArray[1]
+                       };
+
+                       typo3pageModule.idCache[idString] = res;
+               }
+
+               return typo3pageModule.idCache[idString];
+       },
+
+       /**
+        * Appends a loading spinner to the body.
+        *
+        */
+       showSpinner: function(){
+               typo3pageModule.spinner = new Element('div');
+               Ext.get(typo3pageModule.spinner).addClass('loadingSpinner').fadeIn({ endOpacity: .75, duration: 1});
+
+               Ext.select('body').appendChild(typo3pageModule.spinner);
+       },
+       /**
+        * Removes the loading spinner from the body.
+        */
+       hideSpinner: function(){
+               Ext.get(typo3pageModule.spinner).fadeOut({ endOpacity: 1.0, duration: 1}).remove();
+       },
+       /**
+        * This method is used as an event handler when the
+        * user hovers the headline of an content element.
+        */
+       enableContentHeader: function(e,t){
+               var parent = Ext.get(t).findParent('div.contentElement',null,true);
+               parent.child('div.ttContentHeader').show();
+               parent.addClass('active')
+       },
+
+       /**
+        * This method is used as event handler to hide the headline of
+        * an content element when the mouse of the user leaves the
+        * header of the content element.
+        */
+       disableContentHeader: function(e,t){
+               var parent = Ext.get(t).findParent('div.contentElement',null,true);
+               parent.child('div.ttContentHeader').hide();
+               parent.removeClass('active');
+
+       },
+
+       /**
+        * This method is used to bind the higlighting function "enableContentHeader"
+        * to the mouseenter event and the "disableContentHeader" to the mouselease event.
+        */
+       enableHighlighting: function(){
+               Ext.select('div.contentElement').on('mouseenter',typo3pageModule.enableContentHeader,typo3pageModule).on('mouseleave',typo3pageModule.disableContentHeader,typo3pageModule);
+       },
+
+       /**
+        * This method is used to unbind the higlighting function "enableContentHeader"
+        * from the mouseenter event and the "disableContentHeader" from the mouselease event.
+        */
+       disableHighlighting: function(){
+               Ext.select('div.contentElement').un('mouseenter',typo3pageModule.enableContentHeader,typo3pageModule).un('mouseleave',typo3pageModule.disableContentHeader,typo3pageModule);
+       },
+
+       /**
+        * This method is used to create the draggable items and the drop zones.
+        *
+        * The method additionaly add eventhandler methods and passes the to the
+        * draggable object.
+        */
+       registerDragAndDrop: function(){
+               var overrides = {
+                       // Called the instance the element is dragged.
+                       b4StartDrag:    typo3pageModule.b4StartDrag,
+                       onInvalidDrop:  typo3pageModule.invalidDrop,
+                       endDrag:                typo3pageModule.moveToDropTargetAndEnrich,
+                       onDragDrop:     typo3pageModule.handleElementDrop,
+                       onDragEnter:    typo3pageModule.enableDropZone,
+                       onDragOut:              typo3pageModule.disableDropZone
+               };
+
+               Ext.select('div.contentElement').each(function(el){
+                       var parsedId = typo3pageModule._parseIdString('ttContent_',el.dom.id);
+                       var dd = new Ext.dd.DD(el, 'contentelements_' + parsedId.language, { isTarget  : false});
+                   Ext.apply(dd, overrides);
+               });
+
+               Ext.select('div.columnDropZone').each(function(el){
+                       var parsedId = typo3pageModule._parseIdString('contentElementGroup_',el.parent().id);
+                       var target = new Ext.dd.DDTarget(el,'contentelements_' + parsedId.language);
+               });
+               Ext.select('div.contentElementDropZoneAfter').each(function(el){
+                       var parsedId = typo3pageModule._parseIdString('contentElementGroup_',el.parent().parent().id);
+                       var target = new Ext.dd.DDTarget(el,'contentelements_' + parsedId.language);
+               });
+       },
+
+       /**
+        * This method is used to higlight all drop zones for a certain
+        * language.
+        *
+        * @param int uid of the language
+        */
+       highlightLanguageDropZones: function(languageId){
+               Ext.select('div.dropZone.language_'+languageId).each(function(el){
+                       el.addClass('active');
+               });
+
+               Ext.select('table.typo3-page-ceFooter').each(
+                       function(el){   el.hide(); }
+               );
+       },
+
+       /**
+        * This method unhighlights all drop zones.
+        */
+       unhighlightAllDropZones: function(){
+               Ext.select('div.dropZone').each(function(el){
+                       el.removeClass('active');
+               });
+               Ext.select('table.typo3-page-ceFooter').each(
+                       function(el){   el.show(); }
+               );
+       },
+
+       /**
+        * When an element is dragged a few layers will be hidden
+        * and the z-index will be increased to bring the element
+        * to the front.
+        *
+        * @param Ext.Element element
+        */
+       reduceDraggedElement: function(element){
+               element.select('table.typo3-page-ceHeader').addClass('displayNone');
+           element.select('span.exampleContent').addClass('displayNone');
+           element.select('div.contentElementDropZoneAfter').addClass('displayNone');
+           element.addClass('onDrag');
+
+           var footerTable = element.select('table.typo3-page-ceFooter');
+           if(footerTable != null){
+               footerTable.addClass('displayNone');
+           }
+
+           var colSubHeader = element.select('tr.colSubHeader td');
+           if(colSubHeader != null){
+               colSubHeader.addClass('displayNone');
+           }
+
+           element.setStyle('z-index',999);
+       },
+
+       /**
+        * This method is used to display all hidden layers of a dragged
+        * element to bring it to the state before the dragging was started.
+        *
+        * @param Ext.Element element
+        */
+       enrichDraggedElement: function(element){
+               Ext.get(typo3pageModule.placeholder).remove();
+
+               element.select('table.typo3-page-ceHeader').removeClass('displayNone');
+           element.select('span.exampleContent').removeClass('displayNone');
+           element.select('div.contentElementDropZoneAfter').removeClass('displayNone');
+           element.setStyle('z-index',null);
+           element.removeClass('onDrag');
+           var footerTable = element.select('table.typo3-page-ceFooter');
+           if(footerTable != null){ footerTable.removeClass('displayNone'); }
+       },
+
+
+       /**
+        * Handler method for invalid drops.
+        */
+       invalidDrop: function() {
+           // Set a flag to invoke the animated repair
+           this.invalidDrop = true;
+       },
+
+       /**
+        * Handler method before dragging starts.
+        */
+       b4StartDrag: function(x,y) {
+               //disable the menubar highlighting during dragging
+           typo3pageModule.disableHighlighting();
+
+           // Cache the drag element
+           if (!this.el) { this.el = Ext.get(this.getEl()); }
+
+           //Cache the original XY Coordinates of the element, we'll use this later.
+           this.originalXY = this.el.getXY();
+
+           //move the draggable item to the mouse position
+           this.setDelta(0,0);
+
+           //highlight dropable targets
+       var parsedId = typo3pageModule._parseIdString('ttContent_',this.el.id);
+           typo3pageModule.highlightLanguageDropZones(parsedId.language);
+
+           //calculate width and height before reducing
+           var heightBefore = this.el.getHeight();
+           var widthBefore  = this.el.getWidth();
+
+           //make some layers of the draggable element invisible
+           typo3pageModule.reduceDraggedElement(this.el);
+
+           //caluclate height after reducing
+           var heightAfter = this.el.getHeight();
+           var widthAfter      = this.el.getWidth();
+
+           //create a placeholder for the dragged element
+           typo3pageModule.placeholder = new Element('div');
+           typo3pageModule.placeholder.setStyle({position: 'relative', height: heightBefore - heightAfter+ 'px', width: widthBefore - widthAfter+ 'px'});
+
+           //insert placeholder before the dragged element
+           Ext.get(typo3pageModule.placeholder).insertAfter(this.el.prev());
+        },
+        /**
+         * Handler method for "endDrag" event.
+         * Used to move the element to the prev. position when
+         * the element has been droppen on an invalid location.
+         */
+       moveToDropTargetAndEnrich: function() {
+           // Invoke the animation if the invalidDrop flag is set to true
+
+                if (this.invalidDrop === true) {
+               var animCfgObj = {
+                               easing   : null,
+                               duration : 0,
+                       scope    : this,
+                               callback : function() {
+                           // Remove the position attribute
+                           this.el.dom.style.position = '';
+                           this.el.dom.style.left = 0;
+                           this.el.dom.style.top = 0;
+                       }
+                  };
+
+               // Apply the repair animation
+               this.el.moveTo(this.originalXY[0], this.originalXY[1],animCfgObj);
+               typo3pageModule.enrichDraggedElement(this.el);
+               delete this.invalidDrop;
+           }
+           typo3pageModule.unhighlightAllDropZones();
+           typo3pageModule.enableHighlighting();
+       },
+
+       /**
+        * Event handler to process a valid drop.
+        */
+       handleElementDrop: function(evtObj, targetElId) {
+           // Wrap the drop target element with Ext.Element
+           var dropEl = Ext.get(targetElId);
+
+           // Perform the node move only if the drag element's
+           // parent is not the same as the drop target
+           if (this.el.dom.parentNode.id != targetElId) {
+               // Move the element
+               typo3pageModule.enrichDraggedElement(this.el);
+
+               var ttContentParsedId = typo3pageModule._parseIdString('ttContent_',this.el.id);
+               var rowParsedId = typo3pageModule._parseIdString('contentElementGroup_',dropEl.findParent('div.contentElementGroup').id);
+
+               if(dropEl.hasClass('contentElementDropZoneAfter')){
+                        var dropZoneAfterParsedId = typo3pageModule._parseIdString('contentElementDropZoneAfter_',dropEl.id);
+                        var idBehind = dropZoneAfterParsedId.id;
+                        this.el.insertAfter(dropEl.parent());
+               }
+               if(dropEl.hasClass('columnDropZone')){
+                               var idBehind  = pageId;
+                       this.el.insertAfter(dropEl);
+               }
+
+               var url = pageModuleMoveUrl.replace(/###MOVE_AFTER###/,idBehind).replace(/###MOVE_ITEM###/, ttContentParsedId.id ).replace(/###COL_POS###/,rowParsedId.id);
+
+               typo3pageModule.showSpinner();
+
+               Ext.Ajax.request({
+                  url: url,
+                  success: function(response, opts) {
+                               typo3pageModule.hideSpinner();
+                               window.location.reload();
+                       },
+                  failure: function(response, opts) { alert('server-side failure with status code ' + response.status); }
+               });
+
+               // Remove the drag invitation
+               this.onDragOut(evtObj, targetElId);
+
+               // Clear the styles
+               this.el.dom.style.position ='';
+               this.el.dom.style.top = '';
+               this.el.dom.style.left = '';
+           }
+           else {
+               // This was an invalid drop, initiate a repair
+               this.onInvalidDrop();
+           }
+       },
+
+       /**
+        * This method is called when an element has been drag over a valid drop zone.
+        * It highlights the drop zone to indicate to the user, that he can drop an item here.
+        *
+        * @param event
+        * @param string idString of the target element.
+        */
+       enableDropZone: function(evtObj, targetElId) {
+               if (targetElId != this.el.dom.parentNode.id) {
+                       var dropEl = Ext.get(targetElId);
+                       dropEl.addClass('validDrop');
+               }
+       },
+       /**
+        * This method is called when an element is removed from a dropZone.
+        *
+        * @param event
+        * @param string idString of the target element.
+        */
+       disableDropZone: function(evtObj, targetElId) {
+               if (targetElId != this.el.dom.parentNode.id) {
+
+                       var dropEl = Ext.get(targetElId);
+                       dropEl.removeClass('validDrop');
+               }
+       }
+}
+
+Event.observe(window, 'load', function() {
+       typo3pageModule.init();
+});
diff --git a/typo3/sysext/cms/layout/wizard_be_layout.php b/typo3/sysext/cms/layout/wizard_be_layout.php
new file mode 100644 (file)
index 0000000..44ca0c2
--- /dev/null
@@ -0,0 +1,568 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 1999-2009 Kasper Sk?rh?j (kasperYYYY@typo3.com)
+ *  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!
+ ***************************************************************/
+/**
+ * Grid wizard
+ *
+ * $Id $
+ */
+
+require_once('conf.php');
+require($BACK_PATH . 'init.php');
+require($BACK_PATH . 'template.php');
+$LANG->includeLLFile('EXT:lang/locallang_wizards.xml');
+
+/**
+ * Script Class for grid wizard
+ *
+ * @author     T3UXW09 Team1 <modernbe@cybercraft.de>
+ * @package TYPO3
+ * @subpackage core
+ */
+class SC_wizard_be_layout {
+
+       // GET vars:
+       var $P; // Wizard parameters, coming from TCEforms linking to the wizard.
+
+       /**
+        * document template object
+        *
+        * @var smallDoc
+        */
+       var $doc;
+       var $content; // Accumulated content.
+
+
+       /**
+        * Initialises the Class
+        *
+        * @return      void
+        */
+       function init() {
+
+
+               // Setting GET vars (used in frameset script):
+               $this->P = t3lib_div::_GP('P', 1);
+
+               //data[layouts][2][config]
+               $this->formName = $this->P['formName'];
+               $this->fieldName = $this->P['itemName'];
+               $this->md5ID = $this->P['md5ID'];
+               $uid = intval($this->P['uid']);
+
+               // Initialize document object:
+               $this->doc = t3lib_div::makeInstance('noDoc');
+               $this->doc->backPath = $GLOBALS['BACK_PATH'];
+
+               $pageRenderer = $this->doc->getPageRenderer();
+               $pageRenderer->addJsFile($GLOBALS['BACK_PATH'] . TYPO3_MOD_PATH . 'res/grideditor.js');
+               $pageRenderer->addJsInlineCode('storeData', '
+                       function storeData(data)        {
+                               if (parent.opener && parent.opener.document && parent.opener.document.' . $this->formName . ' && parent.opener.document.' . $this->formName . '["' . $this->fieldName . '"])    {
+                                       parent.opener.document.' . $this->formName . '["' . $this->fieldName . '"].value = data;
+                                       parent.opener.TBE_EDITOR.fieldChanged("be_layouts","' . $uid . '","config","data[be_layouts][' . $uid . '][config]");
+                               }
+                       }
+               ');
+
+               $languageLabels = array(
+                       'save' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_wizards.xml:grid_labelSave', 1),
+                       'title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_wizards.xml:grid_windowTitle', 1),
+                       'name' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_wizards.xml:grid_labelName', 1),
+                       'column' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_wizards.xml:grid_labelColumn', 1)
+               );
+               $pageRenderer->addInlineLanguageLabelArray($languageLabels);
+
+               // select record
+               $record = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows($this->P['field'], $this->P['table'], 'uid=' . intval($this->P['uid']));
+               if (trim($record[0][$this->P['field']]) == '') {
+                       $t3GridData = "[[{colspan:1,rowspan:1,spanned:false,name:''}]]";
+                       $colCount = 1;
+                       $rowCount = 1;
+               } else {
+
+                       // load TS parser
+                       $parser = t3lib_div::makeInstance('t3lib_TSparser');
+                       $parser->parse($record[0][$this->P['field']]);
+                       $data = $parser->setup['be_layout.'];
+                       $t3GridData = '[';
+                       $colCount = $data['colCount'];
+                       $rowCount = $data['rowCount'];
+                       $dataRows = $data['rows.'];
+                       $spannedMatrix = array();
+
+                       for ($i = 1; $i <= $rowCount; $i++) {
+                               $rowString = '';
+                               for ($j = 1; $j <= $colCount; $j++) {
+                                       if ($j == 1) {
+                                               $row = array_shift($dataRows);
+                                               $columns = $row['columns.'];
+                                               $rowString = '[';
+                                               $cells = array();
+                                       }
+                                       if (!$spannedMatrix[$i][$j]) {
+                                               if (is_array($columns) && count($columns)) {
+                                                       $column = array_shift($columns);
+                                                       $cellString = '{';
+                                                       $cellData = array();
+                                                       if (isset($column['colspan'])) {
+                                                               $cellData[] = 'colspan:' . intval($column['colspan']);
+                                                               if (isset($column['rowspan'])) {
+                                                                       for ($spanRow = 0; $spanRow < intval($column['rowspan']); $spanRow++) {
+                                                                               for ($spanColumn = 0; $spanColumn < intval($column['colspan']); $spanColumn++) {
+                                                                                       $spannedMatrix[$i + $spanRow][$j + $spanColumn] = 1;
+                                                                               }
+                                                                       }
+                                                               } else {
+                                                                       for ($spanColumn = 0; $spanColumn < intval($column['colspan']); $spanColumn++) {
+                                                                               $spannedMatrix[$i][$j + $spanColumn] = 1;
+                                                                       }
+                                                               }
+                                                       } else {
+                                                               $cellData[] = 'colspan:1';
+                                                               if (isset($column['rowspan'])) {
+                                                                       for ($spanRow = 0; $spanRow < intval($column['rowspan']); $spanRow++) {
+                                                                               $spannedMatrix[$i + $spanRow][$j] = 1;
+                                                                       }
+                                                               }
+                                                       }
+                                                       if (isset($column['rowspan'])) {
+                                                               $cellData[] = 'rowspan:' . intval($column['rowspan']);
+                                                       } else {
+                                                               $cellData[] = 'rowspan:1';
+                                                       }
+                                                       if (isset($column['name'])) {
+                                                               $cellData[] = 'name:\'' . $column['name'] . '\'';
+                                                       }
+                                                       if (isset($column['colPos'])) {
+                                                               $cellData[] = 'column:' . $column['colPos'];
+                                                       }
+
+                                                       $cellString .= implode(',', $cellData) . '}';
+                                                       $cells[] = $cellString;
+
+                                               }
+                                       } else {
+                                               $cells[] = '{colspan:1,rowspan:1,spanned:1}';
+                                       }
+                               }
+                               $rowString .= implode(',', $cells);
+                               if ($rowString) {
+                                       $rowString .= ']';
+                               }
+                               $rows[] = $rowString;
+                               ksort($spannedMatrix[$i]);
+                       }
+
+                       $t3GridData .= implode(',', $rows) . ']';
+
+
+               }
+
+               $this->doc->JScode .= '
+                       <script type="text/javascript">
+                       Ext.onReady(function() {
+                               t3Grid = new TYPO3.Backend.t3Grid({
+                                       data: ' . $t3GridData . ',
+                                       colCount: ' . $colCount . ',
+                                       rowCount: ' . $rowCount . ',
+                                       targetElement: \'editor\'
+                               });
+
+                               t3Grid.drawTable();
+                       });
+                       </script>
+               ';
+
+
+               $this->doc->styleSheetFile_post = TYPO3_MOD_PATH . 'res/grideditor.css';
+               $this->doc->styleSheetFile2 = 'sysext/t3skin/stylesheets/extjs/xtheme-t3skin.css';
+       }
+
+       /**
+        * Main Method, rendering either colorpicker or frameset depending on ->showPicker
+        *
+        * @return      void
+        */
+       function main() {
+
+               $content .= '<a href="#" title="' .
+                       $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:rm.saveDoc', TRUE) . '" onclick="storeData(t3Grid.export2LayoutRecord());return true;">' .
+                        t3lib_iconWorks::getSpriteIcon('actions-document-save') . '</a>';
+
+               $content .= '<a href="#" title="' .
+                       $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:rm.saveCloseDoc', TRUE) . '" onclick="storeData(t3Grid.export2LayoutRecord());window.close();return true;">' .
+                       t3lib_iconWorks::getSpriteIcon('actions-document-save-close') . '</a>';
+
+               $content .= '<a href="#" title="'.
+                       $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:rm.closeDoc', TRUE) . '" onclick="window.close();return true;">' .
+                        t3lib_iconWorks::getSpriteIcon('actions-document-close') . '</a>';
+
+
+               $content .= $this->doc->spacer(10);
+
+               $content .= '
+               <table border="0" width="100%" height="100%" id="outer_container">
+                       <tr>
+                               <td class="editor_cell">
+                                       <div id="editor">
+                                       </div>
+                               </td>
+                               <td width="20" valign="center">
+                                       <a id="addCol" href="#" title="' . $GLOBALS['LANG']->getLL('grid_addColumn') . '" onclick="t3Grid.addColumn(); t3Grid.drawTable(\'editor\');">
+                                               <img src="res/t3grid-tableright.png" border="0" />
+                                       </a><br />
+                                       <a id="addCol" href="#" title="' . $GLOBALS['LANG']->getLL('grid_removeColumn') . '" onclick="t3Grid.removeColumn(); t3Grid.drawTable(\'editor\');">
+                                               <img src="res/t3grid-tableleft.png" border="0" />
+                                       </a>
+                               </td>
+                       </tr>
+                       <tr>
+                               <td colspan="2" height="20" align="center">
+                                       <a id="addCol" href="#" title="' . $GLOBALS['LANG']->getLL('grid_addRow') . '" onclick="t3Grid.addRow(); t3Grid.drawTable(\'editor\');">
+                                               <img src="res/t3grid-tabledown.png" border="0" />
+                                       </a>
+                                       <a id="addCol" href="#" title="' . $GLOBALS['LANG']->getLL('grid_removeRow') . '" onclick="t3Grid.removeRow(); t3Grid.drawTable(\'editor\');">
+                                               <img src="res/t3grid-tableup.png" border="0" />
+                                       </a>
+                               </td>
+                       </tr>
+               </table>
+               ';
+
+               $this->content = $content;
+       }
+
+       /**
+        * Returnes the sourcecode to the browser
+        *
+        * @return      void
+        */
+       function printContent() {
+               echo $this->doc->render(
+                       'Grid wizard',
+                       $this->content
+               );
+       }
+
+}
+
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/wizard_be_layout.php']) {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/wizard_be_layout.php']);
+}
+
+
+// Make instance:
+$SOBE = t3lib_div::makeInstance('SC_wizard_be_layout');
+$SOBE->init();
+$SOBE->main();
+$SOBE->printContent();
+
+?>
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 1999-2009 Kasper Sk?rh?j (kasperYYYY@typo3.com)
+ *  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!
+ ***************************************************************/
+/**
+ * Grid wizard
+ *
+ * $Id $
+ */
+
+require_once('conf.php');
+require($BACK_PATH . 'init.php');
+require($BACK_PATH . 'template.php');
+$LANG->includeLLFile('EXT:lang/locallang_wizards.xml');
+
+/**
+ * Script Class for grid wizard
+ *
+ * @author     T3UXW09 Team1 <modernbe@cybercraft.de>
+ * @package TYPO3
+ * @subpackage core
+ */
+class SC_wizard_be_layout {
+
+       // GET vars:
+       var $P; // Wizard parameters, coming from TCEforms linking to the wizard.
+
+       /**
+        * document template object
+        *
+        * @var smallDoc
+        */
+       var $doc;
+       var $content; // Accumulated content.
+
+
+       /**
+        * Initialises the Class
+        *
+        * @return      void
+        */
+       function init() {
+
+
+               // Setting GET vars (used in frameset script):
+               $this->P = t3lib_div::_GP('P', 1);
+
+               //data[layouts][2][config]
+               $this->formName = $this->P['formName'];
+               $this->fieldName = $this->P['itemName'];
+               $this->md5ID = $this->P['md5ID'];
+
+               // Initialize document object:
+               $this->doc = t3lib_div::makeInstance('noDoc');
+               $this->doc->backPath = $GLOBALS['BACK_PATH'];
+
+               $pageRenderer = $this->doc->getPageRenderer();
+               $pageRenderer->addJsFile($GLOBALS['BACK_PATH'] . TYPO3_MOD_PATH . 'res/grideditor.js');
+               $pageRenderer->addJsInlineCode('storeData', '
+                       function storeData(data)        {
+                               if (parent.opener && parent.opener.document && parent.opener.document.' . $this->formName . ' && parent.opener.document.' . $this->formName . '["' . $this->fieldName . '"])    {
+                                       parent.opener.document.' . $this->formName . '["' . $this->fieldName . '"].value = data;
+                               }
+                       }
+               ');
+
+               $languageLabels = array(
+                       'save' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_wizards.xml:grid_labelSave', 1),
+                       'title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_wizards.xml:grid_windowTitle', 1),
+                       'name' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_wizards.xml:grid_labelName', 1),
+                       'column' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_wizards.xml:grid_labelColumn', 1)
+               );
+               $pageRenderer->addInlineLanguageLabelArray($languageLabels);
+
+               // select record
+               $record = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows($this->P['field'], $this->P['table'], 'uid=' . intval($this->P['uid']));
+               if (trim($record[0][$this->P['field']]) == '') {
+                       $t3GridData = "[[{colspan:1,rowspan:1,spanned:false,name:''}]]";
+                       $colCount = 1;
+                       $rowCount = 1;
+               } else {
+
+                       // load TS parser
+                       $parser = t3lib_div::makeInstance('t3lib_TSparser');
+                       $parser->parse($record[0][$this->P['field']]);
+                       $data = $parser->setup['be_layout.'];
+                       $t3GridData = '[';
+                       $colCount = $data['colCount'];
+                       $rowCount = $data['rowCount'];
+                       $dataRows = $data['rows.'];
+                       $spannedMatrix = array();
+
+                       for ($i = 1; $i <= $rowCount; $i++) {
+                               $rowString = '';
+                               for ($j = 1; $j <= $colCount; $j++) {
+                                       if ($j == 1) {
+                                               $row = array_shift($dataRows);
+                                               $columns = $row['columns.'];
+                                               $rowString = '[';
+                                               $cells = array();
+                                       }
+                                       if (!$spannedMatrix[$i][$j]) {
+                                               if (is_array($columns) && count($columns)) {
+                                                       $column = array_shift($columns);
+                                                       $cellString = '{';
+                                                       $cellData = array();
+                                                       if (isset($column['colspan'])) {
+                                                               $cellData[] = 'colspan:' . intval($column['colspan']);
+                                                               if (isset($column['rowspan'])) {
+                                                                       for ($spanRow = 0; $spanRow < intval($column['rowspan']); $spanRow++) {
+                                                                               for ($spanColumn = 0; $spanColumn < intval($column['colspan']); $spanColumn++) {
+                                                                                       $spannedMatrix[$i + $spanRow][$j + $spanColumn] = 1;
+                                                                               }
+                                                                       }
+                                                               } else {
+                                                                       for ($spanColumn = 0; $spanColumn < intval($column['colspan']); $spanColumn++) {
+                                                                               $spannedMatrix[$i][$j + $spanColumn] = 1;
+                                                                       }
+                                                               }
+                                                       } else {
+                                                               $cellData[] = 'colspan:1';
+                                                               if (isset($column['rowspan'])) {
+                                                                       for ($spanRow = 0; $spanRow < intval($column['rowspan']); $spanRow++) {
+                                                                               $spannedMatrix[$i + $spanRow][$j] = 1;
+                                                                       }
+                                                               }
+                                                       }
+                                                       if (isset($column['rowspan'])) {
+                                                               $cellData[] = 'rowspan:' . intval($column['rowspan']);
+                                                       } else {
+                                                               $cellData[] = 'rowspan:1';
+                                                       }
+                                                       if (isset($column['name'])) {
+                                                               $cellData[] = 'name:\'' . $column['name'] . '\'';
+                                                       }
+                                                       if (isset($column['colPos'])) {
+                                                               $cellData[] = 'column:' . $column['colPos'];
+                                                       }
+
+                                                       $cellString .= implode(',', $cellData) . '}';
+                                                       $cells[] = $cellString;
+
+                                               }
+                                       } else {
+                                               $cells[] = '{colspan:1,rowspan:1,spanned:1}';
+                                       }
+                               }
+                               $rowString .= implode(',', $cells);
+                               if ($rowString) {
+                                       $rowString .= ']';
+                               }
+                               $rows[] = $rowString;
+                               ksort($spannedMatrix[$i]);
+                       }
+
+                       $t3GridData .= implode(',', $rows) . ']';
+
+
+               }
+
+               $this->doc->JScode .= '
+                       <script type="text/javascript">
+                       Ext.onReady(function() {
+                               t3Grid = new TYPO3.Backend.t3Grid({
+                                       data: ' . $t3GridData . ',
+                                       colCount: ' . $colCount . ',
+                                       rowCount: ' . $rowCount . ',
+                                       targetElement: \'editor\'
+                               });
+
+                               t3Grid.drawTable();
+                       });
+                       </script>
+               ';
+
+
+               $this->doc->styleSheetFile_post = TYPO3_MOD_PATH . 'res/grideditor.css';
+               $this->doc->styleSheetFile2 = 'sysext/t3skin/stylesheets/extjs/xtheme-t3skin.css';
+       }
+
+       /**
+        * Main Method, rendering either colorpicker or frameset depending on ->showPicker
+        *
+        * @return      void
+        */
+       function main() {
+
+               $content .= '<a href="#" title="' .
+                       $GLOBALS['LANG']->mainLang['rm']['saveDoc'] . '" onclick="storeData(t3Grid.export2LayoutRecord());return true;">' .
+                        t3lib_iconWorks::getSpriteIcon('actions-document-save') . '</a>';
+
+               $content .= '<a href="#" title="' .
+                       $GLOBALS['LANG']->mainLang['rm']['saveCloseDoc'] . '" onclick="storeData(t3Grid.export2LayoutRecord());;return true;">' .
+                       t3lib_iconWorks::getSpriteIcon('actions-document-save-close') . '</a>';
+
+               $content .= '<a href="#"' .
+                       ' onclick="window.close();return true;">' .
+                        t3lib_iconWorks::getSpriteIcon('actions-document-close') . '</a>';
+
+
+               $content .= $this->doc->spacer(10);
+
+               $content .= '
+               <table border="0" width="100%" height="100%" id="outer_container">
+                       <tr>
+                               <td class="editor_cell">
+                                       <div id="editor">
+                                       </div>
+                               </td>
+                               <td width="20" valign="center">
+                                       <a id="addCol" href="#" title="' . $GLOBALS['LANG']->getLL('grid_addColumn') . '" onclick="t3Grid.addColumn(); t3Grid.drawTable(\'editor\');">
+                                               <img src="res/t3grid-tableright.png" border="0" />
+                                       </a><br />
+                                       <a id="addCol" href="#" title="' . $GLOBALS['LANG']->getLL('grid_removeColumn') . '" onclick="t3Grid.removeColumn(); t3Grid.drawTable(\'editor\');">
+                                               <img src="res/t3grid-tableleft.png" border="0" />
+                                       </a>
+                               </td>
+                       </tr>
+                       <tr>
+                               <td colspan="2" height="20" align="center">
+                                       <a id="addCol" href="#" title="' . $GLOBALS['LANG']->getLL('grid_addRow') . '" onclick="t3Grid.addRow(); t3Grid.drawTable(\'editor\');">
+                                               <img src="res/t3grid-tabledown.png" border="0" />
+                                       </a>
+                                       <a id="addCol" href="#" title="' . $GLOBALS['LANG']->getLL('grid_removeRow') . '" onclick="t3Grid.removeRow(); t3Grid.drawTable(\'editor\');">
+                                               <img src="res/t3grid-tableup.png" border="0" />
+                                       </a>
+                               </td>
+                       </tr>
+               </table>
+               ';
+
+               $this->content = $content;
+       }
+
+       /**
+        * Returnes the sourcecode to the browser
+        *
+        * @return      void
+        */
+       function printContent() {
+               echo $this->doc->render(
+                       'Grid wizard',
+                       $this->content
+               );
+       }
+
+}
+
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/wizard_be_layout.php']) {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/wizard_be_layout.php']);
+}
+
+
+// Make instance:
+$SOBE = t3lib_div::makeInstance('SC_wizard_be_layout');
+$SOBE->init();
+$SOBE->main();
+$SOBE->printContent();
+
+?>
index 3bdd6b4..b87d6c1 100755 (executable)
                        <label index="pages.fe_login_mode.enableAgain">Enable logins again</label>
                        <label index="pages.storage_pid_formlabel">On selected page</label>
                        <label index="pages.TSconfig_formlabel">TSconfig</label>
+                       <label index="pages.be_layout_formlabel">Backend Layout</label>
+                       <label index="pages.be_layout_next_level_formlabel">Backend Layout (on next level)</label>
                        <label index="tt_content">Pagecontent</label>
                        <label index="fe_users">Website user</label>
                        <label index="fe_users.username">Username:</label>
                        <label index="sys_template.tabs.options">Options</label>
                        <label index="sys_template.tabs.access">Access</label>
                        <label index="pages_language_overlay">Alternative Page Language</label>
+                       <label index="be_layouts">Backend Layouts</label>
+                       <label index="be_layouts.title">Title</label>
+                       <label index="be_layouts.description">Description</label>
+                       <label index="be_layouts.config">Config</label>
+                       <label index="be_layouts.wizard">Wizard</label>
+                       <label index="be_layouts.icon">Icon</label>
                </languageKey>
        </data>
 </T3locallang>
index fe0ce14..4832d07 100755 (executable)
@@ -996,5 +996,81 @@ $TCA['sys_template'] = array(
        )
 );
 
+// ******************************************************************
+// be_layouts
+// ******************************************************************
+/**
+ * @todo add lll
+ */
+$TCA['be_layouts'] = array(
+       'ctrl' => $TCA['be_layouts']['ctrl'],
+       'interface' => array(
+               'showRecordFieldList' => 'title,config,description,hidden,icon'
+       ),
+       'columns' => array(
+               'title' => array(
+                       'label' => 'LLL:EXT:cms/locallang_tca.xml:be_layouts.title',
+                       'config' => array(
+                               'type' => 'input',
+                               'size' => '25',
+                               'max' => '256',
+                               'eval' => 'required'
+                       )
+               ),
+               'description' => array(
+                       'label' => 'LLL:EXT:cms/locallang_tca.xml:be_layouts.description',
+                       'config' => array(
+                               'type' => 'text',
+                               'rows' => '5',
+                               'cols' => '25',
+                       )
+               ),
+               'config' => array(
+                       'label' => 'LLL:EXT:cms/locallang_tca.xml:be_layouts.config',
+                       'config' => array(
+                               'type' => 'text',
+                               'rows' => '5',
+                               'cols' => '25',
+                               'wizards' => Array(
+                                       '_PADDING' => 4,
+                                       0 => Array(
+                                               'title' => 'LLL:EXT:cms/locallang_tca.xml:be_layouts.wizard',
+                                               'type' => 'popup',
+                                               'icon' => t3lib_extMgm::extRelPath('cms').'layout/wizard_be_layout.png',
+                                               'script' => t3lib_extMgm::extRelPath('cms').'layout/wizard_be_layout.php',
+                                               'JSopenParams' => 'height=800,width=800,status=0,menubar=0,scrollbars=0',
+                                       ),
+                               ),
+                       )
+               ),
+               'hidden' => array(
+                       'label' => 'LLL:EXT:lang/locallang_general.php:LGL.disable',
+                       'exclude' => 1,
+                       'config' => array(
+                               'type' => 'check',
+                               'default' => '0'
+                       )
+               ),
+               'icon' => array(
+                       'label' => 'LLL:EXT:cms/locallang_tca.xml:be_layouts.icon',
+                       'exclude' => 1,
+                       'config' => array(
+                               'type' => 'group',
+                               'internal_type' => 'file',
+                               'allowed' => 'jpg,gif,png',
+                               'uploadfolder' => 'uploads/media',
+                               'show_thumbs' => 1,
+                               'size' => 1,
+                               'maxitems' => 1
+                       )
+               ),
+       ),
+       'types' => array(
+               '1' => array('showitem' => '
+                       hidden,title;;1;;2-2-2, icon, description, config'
+               )
+       )
+);
+
 
 ?>
\ No newline at end of file
index 5de2bb3..ba03973 100755 (executable)
@@ -297,6 +297,7 @@ $TCA['tt_content'] = array(
                        'label' => 'LLL:EXT:cms/locallang_ttc.xml:colPos',
                        'config' => array(
                                'type' => 'select',
+                               'itemsProcFunc' => 'EXT:cms/class.tx_cms_be_layout.php:tx_cms_be_layout->colPosListItemProcFunc',
                                'items' => array(
                                        array(
                                                'LLL:EXT:cms/locallang_ttc.xml:colPos.I.0',
@@ -1174,7 +1175,7 @@ $TCA['tt_content'] = array(
                                        array(
                                                '8',
                                                '8',
-                                       ),                                      
+                                       ),
                                        array(
                                                '9',
                                                '9',
@@ -1658,10 +1659,10 @@ $TCA['tt_content'] = array(
                        'showitem' => 'CType',
                ),
                'header' =>     array(
-                       'showitem' => 
+                       'showitem' =>
                                        '--palette--;LLL:EXT:cms/locallang_ttc.xml:palette.general;general,
-                                       --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.headers;headers, 
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                                       --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.headers;headers,
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
@@ -1669,12 +1670,12 @@ $TCA['tt_content'] = array(
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.extended',
                ),
                'text' =>               array(
-                       'showitem' => 
+                       'showitem' =>
                                        '--palette--;LLL:EXT:cms/locallang_ttc.xml:palette.general;general,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.header;header,
                                        bodytext;LLL:EXT:cms/locallang_ttc.xml:bodytext_formlabel;;richtext:rte_transform[flag=rte_enabled|mode=ts_css],
                                        rte_enabled;LLL:EXT:cms/locallang_ttc.xml:rte_enabled_formlabel,
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
@@ -1683,7 +1684,7 @@ $TCA['tt_content'] = array(
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.extended',
                ),
                'textpic' =>    array(
-                       'showitem' => 
+                       'showitem' =>
                                        '--palette--;LLL:EXT:cms/locallang_ttc.xml:palette.general;general,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.header;header,
                                        bodytext;Text;;richtext:rte_transform[flag=rte_enabled|mode=ts_css],
@@ -1691,8 +1692,8 @@ $TCA['tt_content'] = array(
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.images,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.imagefiles;imagefiles,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.imagelinks;imagelinks,
-                                       --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.image_accessibility;image_accessibility, 
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                                       --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.image_accessibility;image_accessibility,
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
@@ -1709,7 +1710,7 @@ $TCA['tt_content'] = array(
                                        --palette--;LLL:EXT:cms/locallang.xml:palette.imagefiles;imagefiles,
                                        --palette--;LLL:EXT:cms/locallang.xml:palette.imagelinks;imagelinks,
                                        --palette--;LLL:EXT:cms/locallang.xml:palette.image_accessibility;image_accessibility,
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
@@ -1719,11 +1720,11 @@ $TCA['tt_content'] = array(
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.extended',
                ),
                'bullets' =>    array(
-                       'showitem' => 
+                       'showitem' =>
                                        '--palette--;LLL:EXT:cms/locallang_ttc.xml:palette.general;general,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.header;header,
                                        bodytext;LLL:EXT:cms/locallang_ttc.xml:bodytext.ALT.bulletlist_formlabel;;nowrap,
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
@@ -1732,11 +1733,11 @@ $TCA['tt_content'] = array(
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.extended',
                ),
                'table' =>              array(
-                       'showitem' => 
+                       'showitem' =>
                                        '--palette--;LLL:EXT:cms/locallang_ttc.xml:palette.general;general,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.header;header,
                                        bodytext;LLL:EXT:cms/locallang_ttc.xml:bodytext.ALT.table_formlabel;;nowrap:wizards[table],
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
@@ -1746,11 +1747,11 @@ $TCA['tt_content'] = array(
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.extended',
                ),
                'splash' =>     array(
-                       'showitem' => 
+                       'showitem' =>
                                        '--palette--;LLL:EXT:cms/locallang_ttc.xml:palette.general;general,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.header;header,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.textbox;textbox,
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
@@ -1758,11 +1759,11 @@ $TCA['tt_content'] = array(
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.extended',
                ),
                'uploads' =>    array(
-                       'showitem' => 
+                       'showitem' =>
                                        '--palette--;LLL:EXT:cms/locallang_ttc.xml:palette.general;general,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.header;header,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:media;uploads,
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
@@ -1775,7 +1776,7 @@ $TCA['tt_content'] = array(
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.header;header,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.media,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.multimediafiles;multimediafiles,
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
@@ -1787,7 +1788,7 @@ $TCA['tt_content'] = array(
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.header;header,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.media,
                                        pi_flexform; ;,
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
@@ -1797,15 +1798,15 @@ $TCA['tt_content'] = array(
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.extended',
                ),
                'script' =>             array(
-                       'showitem' => 
+                       'showitem' =>
                                        '--palette--;LLL:EXT:cms/locallang_ttc.xml:palette.general;general,
                                        header;LLL:EXT:cms/locallang_ttc.xml:header.ALT.script_formlabel,
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.script, 
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.script,
                                        select_key;LLL:EXT:cms/locallang_ttc.xml:select_key.ALT.script_formlabel,
                                        pages;LLL:EXT:cms/locallang_ttc.xml:pages.ALT.script_formlabel,
                                        bodytext;LLL:EXT:cms/locallang_ttc.xml:bodytext.ALT.script_formlabel;;nowrap,
                                        imagecaption;LLL:EXT:cms/locallang_ttc.xml:imagecaption.ALT.script_formlabel,
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
@@ -1813,11 +1814,11 @@ $TCA['tt_content'] = array(
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.extended',
                ),
                'menu' =>               array(
-                       'showitem' => 
+                       'showitem' =>
                                        '--palette--;LLL:EXT:cms/locallang_ttc.xml:palette.general;general,
-                                       --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.header;header, 
-                                       --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.menu;menu, 
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                                       --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.header;header,
+                                       --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.menu;menu,
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
@@ -1825,24 +1826,24 @@ $TCA['tt_content'] = array(
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.extended',
                ),
                'mailform' =>   array(
-                       'showitem' => 
+                       'showitem' =>
                                        '--palette--;LLL:EXT:cms/locallang_ttc.xml:palette.general;general,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.header;header,
                                        bodytext;LLL:EXT:cms/locallang_ttc.xml:bodytext.ALT.mailform_formlabel;;nowrap:wizards[forms],
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.frames;frames,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.behaviour,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.mailform;mailform,
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.extended',           
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.extended',
                ),
                'search' =>     array(
-                       'showitem' => 
+                       'showitem' =>
                                        '--palette--;LLL:EXT:cms/locallang_ttc.xml:palette.general;general,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.header;header,
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
@@ -1852,10 +1853,10 @@ $TCA['tt_content'] = array(
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.extended',
                ),
                'login' =>              array(
-                       'showitem' => 
+                       'showitem' =>
                                        '--palette--;LLL:EXT:cms/locallang_ttc.xml:palette.general;general,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.header;header,
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
@@ -1865,11 +1866,11 @@ $TCA['tt_content'] = array(
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.extended',
                ),
                'shortcut' =>   array(
-                       'showitem' => 
+                       'showitem' =>
                                        '--palette--;LLL:EXT:cms/locallang_ttc.xml:palette.general;general,
                                        header;LLL:EXT:cms/locallang_ttc.xml:header.ALT.shortcut_formlabel,
                                        records;LLL:EXT:cms/locallang_ttc.xml:records_formlabel,
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
@@ -1877,19 +1878,19 @@ $TCA['tt_content'] = array(
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.extended',
                ),
                'list' =>               array(
-                       'showitem' => 
+                       'showitem' =>
                                        '--palette--;LLL:EXT:cms/locallang_ttc.xml:palette.general;general,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.header;header,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.plugin,
-                                       list_type;LLL:EXT:cms/locallang_ttc.xml:list_type_formlabel, 
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                                       list_type;LLL:EXT:cms/locallang_ttc.xml:list_type_formlabel,
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.frames;frames,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.behaviour,
                                        select_key;LLL:EXT:cms/locallang_ttc.xml:select_key_formlabel,
-                                       pages;LLL:EXT:cms/locallang_ttc.xml:pages.ALT.list_formlabel,           
+                                       pages;LLL:EXT:cms/locallang_ttc.xml:pages.ALT.list_formlabel,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.extended',
                        'subtype_value_field' => 'list_type',
                        'subtypes_excludelist' => array(
@@ -1910,10 +1911,10 @@ $TCA['tt_content'] = array(
                        ),
                ),
                'div' =>                array(
-                       'showitem' => 
+                       'showitem' =>
                                        '--palette--;LLL:EXT:cms/locallang_ttc.xml:palette.general;general,
                                        header;LLL:EXT:cms/locallang_ttc.xml:header.ALT.div_formlabel,
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
@@ -1921,11 +1922,11 @@ $TCA['tt_content'] = array(
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.extended',
                ),
                'html' =>               array(
-                       'showitem' => 
+                       'showitem' =>
                                        '--palette--;LLL:EXT:cms/locallang_ttc.xml:palette.general;general,
                                        header;LLL:EXT:cms/locallang_ttc.xml:header.ALT.html_formlabel,
                                        bodytext;LLL:EXT:cms/locallang_ttc.xml:bodytext.ALT.html_formlabel;;nowrap,
-                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access, 
+                               --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
                                        --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
                                --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
@@ -2012,11 +2013,11 @@ $TCA['tt_content'] = array(
                'image_settings' => array(
                        'showitem' => 'imagewidth;LLL:EXT:cms/locallang_ttc.xml:imagewidth_formlabel, imageheight;LLL:EXT:cms/locallang_ttc.xml:imageheight_formlabel, imageborder;LLL:EXT:cms/locallang_ttc.xml:imageborder_formlabel, --linebreak--, image_compression;LLL:EXT:cms/locallang_ttc.xml:image_compression_formlabel, image_effects;LLL:EXT:cms/locallang_ttc.xml:image_effects_formlabel, image_frames;LLL:EXT:cms/locallang_ttc.xml:image_frames_formlabel',
                        'canNotCollapse' => 1,
-               ),      
+               ),
                'imageblock' => array(
                        'showitem' => 'imageorient;LLL:EXT:cms/locallang_ttc.xml:imageorient_formlabel, imagecols;LLL:EXT:cms/locallang_ttc.xml:imagecols_formlabel, --linebreak--, image_noRows;LLL:EXT:cms/locallang_ttc.xml:image_noRows_formlabel, imagecaption_position;LLL:EXT:cms/locallang_ttc.xml:imagecaption_position_formlabel',
                        'canNotCollapse' => 1,
-               ),                                      
+               ),
                'uploads' => array(
                        'showitem' => 'select_key;LLL:EXT:cms/locallang_ttc.xml:select_key.ALT.uploads_formlabel, --linebreak--, media;LLL:EXT:cms/locallang_ttc.xml:media.ALT.uploads_formlabel, imagecaption;LLL:EXT:cms/locallang_ttc.xml:imagecaption.ALT.uploads_formlabel;;nowrap',
                        'canNotCollapse' => 1,
@@ -2024,19 +2025,19 @@ $TCA['tt_content'] = array(
                'mailform' => array(
                        'showitem' => 'pages;LLL:EXT:cms/locallang_ttc.xml:pages.ALT.forms, --linebreak--, subheader;LLL:EXT:cms/locallang_ttc.xml:subheader.ALT.mailform_formlabel',
                        'canNotCollapse' => 1,
-               ),              
+               ),
                'searchform' => array(
                        'showitem' => 'pages;LLL:EXT:cms/locallang_ttc.xml:pages.ALT.searchform',
                        'canNotCollapse' => 1,
-               ),              
+               ),
                'loginform' => array(
                        'showitem' => 'pages;LLL:EXT:cms/locallang_ttc.xml:pages.ALT.loginform',
                        'canNotCollapse' => 1,
-               ),                              
+               ),
                'menu' => array(
                        'showitem' => 'menu_type;LLL:EXT:cms/locallang_ttc.xml:menu_type_formlabel, --linebreak--, pages;LLL:EXT:cms/locallang_ttc.xml:pages.ALT.menu_formlabel',
                        'canNotCollapse' => 1,
-               ),                              
+               ),
                'visibility' => array(
                        'showitem' => 'hidden;LLL:EXT:cms/locallang_ttc.xml:hidden_formlabel, sectionIndex;LLL:EXT:cms/locallang_ttc.xml:sectionIndex_formlabel, linkToTop;LLL:EXT:cms/locallang_ttc.xml:linkToTop_formlabel',
                        'canNotCollapse' => 1,
@@ -2056,7 +2057,7 @@ $TCA['tt_content'] = array(
                'tablelayout' => array (
                        'showitem' => 'table_bgColor;LLL:EXT:cms/locallang_ttc.xml:table_bgColor_formlabel, table_border;LLL:EXT:cms/locallang_ttc.xml:table_border_formlabel, table_cellspacing;LLL:EXT:cms/locallang_ttc.xml:table_cellspacing_formlabel, table_cellpadding;LLL:EXT:cms/locallang_ttc.xml:table_cellpadding_formlabel',
                        'canNotCollapse' => 1,
-               ),              
+               ),
                'uploadslayout' => array (
                        'showitem' => 'filelink_size;LLL:EXT:cms/locallang_ttc.xml:filelink_size_formlabel',
                        'canNotCollapse' => 1,
index dac04a3..aa1f7c5 100755 (executable)
                        <label index="colorpicker_fromList">Select HTML color name:</label>
                        <label index="colorpicker_black">BLACK</label>
                        <label index="colorpicker_white">WHITE</label>
+                       <label index="grid_windowTitle">Set cell name and column number</label>
+                       <label index="grid_labelName">Name</label>
+                       <label index="grid_labelColumn">Column Number</label>
+                       <label index="grid_labelSave">Save to cell</label>
                </languageKey>
        </data>
 </T3locallang>
\ No newline at end of file
diff --git a/typo3/sysext/t3skin/icons/gfx/i/be_layout.gif b/typo3/sysext/t3skin/icons/gfx/i/be_layout.gif
new file mode 100644 (file)
index 0000000..a8729f4
Binary files /dev/null and b/typo3/sysext/t3skin/icons/gfx/i/be_layout.gif differ
diff --git a/typo3/sysext/t3skin/icons/gfx/i/be_layout__f.gif b/typo3/sysext/t3skin/icons/gfx/i/be_layout__f.gif
new file mode 100644 (file)
index 0000000..d40ee08
Binary files /dev/null and b/typo3/sysext/t3skin/icons/gfx/i/be_layout__f.gif differ
diff --git a/typo3/sysext/t3skin/icons/gfx/i/be_layout__h.gif b/typo3/sysext/t3skin/icons/gfx/i/be_layout__h.gif
new file mode 100644 (file)
index 0000000..d3f4905
Binary files /dev/null and b/typo3/sysext/t3skin/icons/gfx/i/be_layout__h.gif differ
diff --git a/typo3/sysext/t3skin/icons/gfx/i/be_layout__hf.gif b/typo3/sysext/t3skin/icons/gfx/i/be_layout__hf.gif
new file mode 100644 (file)
index 0000000..1ead842
Binary files /dev/null and b/typo3/sysext/t3skin/icons/gfx/i/be_layout__hf.gif differ
diff --git a/typo3/sysext/t3skin/icons/gfx/i/be_layout__hfu.gif b/typo3/sysext/t3skin/icons/gfx/i/be_layout__hfu.gif
new file mode 100644 (file)
index 0000000..b845a42
Binary files /dev/null and b/typo3/sysext/t3skin/icons/gfx/i/be_layout__hfu.gif differ
diff --git a/typo3/sysext/t3skin/icons/gfx/i/be_layout__ht.gif b/typo3/sysext/t3skin/icons/gfx/i/be_layout__ht.gif
new file mode 100644 (file)
index 0000000..13c414a
Binary files /dev/null and b/typo3/sysext/t3skin/icons/gfx/i/be_layout__ht.gif differ
diff --git a/typo3/sysext/t3skin/icons/gfx/i/be_layout__htu.gif b/typo3/sysext/t3skin/icons/gfx/i/be_layout__htu.gif
new file mode 100644 (file)
index 0000000..1dac536
Binary files /dev/null and b/typo3/sysext/t3skin/icons/gfx/i/be_layout__htu.gif differ
diff --git a/typo3/sysext/t3skin/icons/gfx/i/be_layout__hu.gif b/typo3/sysext/t3skin/icons/gfx/i/be_layout__hu.gif
new file mode 100644 (file)
index 0000000..ba00bf2
Binary files /dev/null and b/typo3/sysext/t3skin/icons/gfx/i/be_layout__hu.gif differ
diff --git a/typo3/sysext/t3skin/icons/gfx/i/be_layout__t.gif b/typo3/sysext/t3skin/icons/gfx/i/be_layout__t.gif
new file mode 100644 (file)
index 0000000..3580650
Binary files /dev/null and b/typo3/sysext/t3skin/icons/gfx/i/be_layout__t.gif differ
diff --git a/typo3/sysext/t3skin/icons/gfx/i/be_layout__u.gif b/typo3/sysext/t3skin/icons/gfx/i/be_layout__u.gif
new file mode 100644 (file)
index 0000000..5b44587
Binary files /dev/null and b/typo3/sysext/t3skin/icons/gfx/i/be_layout__u.gif differ
diff --git a/typo3/sysext/t3skin/icons/gfx/i/be_layout__x.gif b/typo3/sysext/t3skin/icons/gfx/i/be_layout__x.gif
new file mode 100644 (file)
index 0000000..c367122
Binary files /dev/null and b/typo3/sysext/t3skin/icons/gfx/i/be_layout__x.gif differ
diff --git a/typo3/sysext/t3skin/images/icons/mimetypes/x_belayout.png b/typo3/sysext/t3skin/images/icons/mimetypes/x_belayout.png
new file mode 100644 (file)
index 0000000..abcd936
Binary files /dev/null and b/typo3/sysext/t3skin/images/icons/mimetypes/x_belayout.png differ