diff --git a/Build/Resources/Public/Less/TYPO3/_main_backend_layout_wizard.less b/Build/Resources/Public/Less/TYPO3/_main_backend_layout_wizard.less new file mode 100644 index 0000000000000000000000000000000000000000..830d5aa65ca86980d3e5865a6a19750bbcc64ff9 --- /dev/null +++ b/Build/Resources/Public/Less/TYPO3/_main_backend_layout_wizard.less @@ -0,0 +1,116 @@ + +.grideditor { + td { + vertical-align: middle; + &.editor_cell { + height: 100%; + } + } + + table.editor { + border-right: 1px gray dashed; + border-bottom: 1px gray dashed; + + td { + vertical-align: middle; + border-top: 1px gray dashed; + border-left: 1px gray dashed; + text-align: center; + background-color: white; + min-height: 100px; + } + } + + div#editor { + height: 100%; + } + + div.cell_container { + width: 80px; + height: 80px; + position: relative; + left: 50%; + margin-left: -30px; + opacity: 0.3; + } + + div.cell_container:hover { + opacity: 0.5; + } + + .link { + display: block; + position: absolute; + width: 20px; + height: 40px; + overflow: hidden; + opacity: 0.5; + &:hover { + text-decoration: none; + opacity: 1; + } + + &_expand_down, + &_shrink_up { + width: 40px; + height: 20px; + } + + &_expand_right { + left: 52px; + top: 0; + &:before { + font-family: FontAwesome; + content: "@{fa-var-caret-right}"; + font-size: 42px; + line-height: 42px; + } + } + + &_shrink_left { + left: -8px; + top: 0; + &:before { + font-family: FontAwesome; + content: "@{fa-var-caret-left}"; + font-size: 42px; + line-height: 42px; + } + } + + &_expand_down { + left: 12px; + top: 40px; + &:before { + font-family: FontAwesome; + content: "@{fa-var-caret-down}"; + font-size: 42px; + line-height: 19px; + } + } + + &_shrink_up { + left: 12px; + top: -20px; + &:before { + font-family: FontAwesome; + content: "@{fa-var-caret-up}"; + font-size: 42px; + line-height: 20px; + } + } + + &_editor { + width: 40px; + height: 40px; + left: 12px; + top: 0; + &:before { + font-family: FontAwesome; + content: "@{fa-var-pencil-square}"; + font-size: 42px; + line-height: 42px; + } + } + } +} diff --git a/Build/Resources/Public/Less/backend.less b/Build/Resources/Public/Less/backend.less index a8025ca8de675a8078e8293e1b2f4d9f3e822f16..f6000c8c1a1d6399e419459af33a39f598e66f39 100644 --- a/Build/Resources/Public/Less/backend.less +++ b/Build/Resources/Public/Less/backend.less @@ -60,6 +60,7 @@ @import "TYPO3/_main_body.less"; @import "TYPO3/_main_content.less"; @import "TYPO3/_main_elementbrowser.less"; +@import "TYPO3/_main_backend_layout_wizard"; @import "TYPO3/_main_form.less"; @import "TYPO3/_main_scaffolding.less"; @import "TYPO3/_module_menu.less"; diff --git a/typo3/sysext/backend/Classes/Controller/BackendLayoutWizardController.php b/typo3/sysext/backend/Classes/Controller/BackendLayoutWizardController.php index fea863f635644d955b085d3e095bb01be71bd016..c54cc03d2f5f4b4ca06be2185465b716d2927b14 100644 --- a/typo3/sysext/backend/Classes/Controller/BackendLayoutWizardController.php +++ b/typo3/sysext/backend/Classes/Controller/BackendLayoutWizardController.php @@ -22,7 +22,6 @@ use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\Page\PageRenderer; use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser; -use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -30,15 +29,15 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; */ class BackendLayoutWizardController extends AbstractModule { - // GET vars: - // Wizard parameters, coming from TCEforms linking to the wizard. /** + * GET vars: + * Wizard parameters, coming from TCEforms linking to the wizard. * @var array */ public $P; - // Accumulated content. /** + * Accumulated content. * @var string */ public $content; @@ -53,6 +52,21 @@ class BackendLayoutWizardController extends AbstractModule */ public $fieldName; + /** + * @var array + */ + protected $rows; + + /** + * @var int + */ + protected $colCount; + + /** + * @var int + */ + protected $rowCount; + /** * Constructor */ @@ -85,10 +99,7 @@ class BackendLayoutWizardController extends AbstractModule /** @var \TYPO3\CMS\Core\Page\PageRenderer $pageRenderer */ $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class); - $pageRenderer->loadExtJS(); - $pageRenderer->addJsFile(ExtensionManagementUtility::extRelPath('backend') - . 'Resources/Public/JavaScript/grideditor.js'); - $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Tooltip'); + $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/GridEditor'); $pageRenderer->addInlineSetting( 'ContextHelp', 'moduleUrl', @@ -103,24 +114,28 @@ class BackendLayoutWizardController extends AbstractModule ) ); $pageRenderer->addJsInlineCode('storeData', ' - function storeData(data) { - if (parent.opener && parent.opener.document && parent.opener.document.' . $this->formName . ' && parent.opener.document.' . $this->formName . '[' . GeneralUtility::quoteJSvalue($this->fieldName) . ']) { - parent.opener.document.' . $this->formName . '[' . GeneralUtility::quoteJSvalue($this->fieldName) . '].value = data; - parent.opener.TBE_EDITOR.fieldChanged("backend_layout","' . $uid . '","config","data[backend_layout][' . $uid . '][config]"); - } - } - ', false); + function storeData(data) { + if (parent.opener && parent.opener.document && parent.opener.document.' . $this->formName + . ' && parent.opener.document.' . $this->formName . '[' + . GeneralUtility::quoteJSvalue($this->fieldName) . ']) { + parent.opener.document.' . $this->formName . '[' + . GeneralUtility::quoteJSvalue($this->fieldName) . '].value = data; + parent.opener.TBE_EDITOR.fieldChanged("backend_layout","' . $uid . '","config",' + . '"data[backend_layout][' . $uid . '][config]"); + } + } + ', false); $languageLabels = array( - 'save' => $lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_labelSave', true), - 'title' => $lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_windowTitle', true), - 'editCell' => $lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_editCell', true), - 'mergeCell' => $lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_mergeCell', true), - 'splitCell' => $lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_splitCell', true), - 'name' => $lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_name', true), - 'column' => $lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_column', true), - 'notSet' => $lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_notSet', true), - 'nameHelp' => $lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_nameHelp', true), - 'columnHelp' => $lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_columnHelp', true) + 'save' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_labelSave')), + 'title' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_windowTitle')), + 'editCell' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_editCell')), + 'mergeCell' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_mergeCell')), + 'splitCell' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_splitCell')), + 'name' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_name')), + 'column' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_column')), + 'notSet' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_notSet')), + 'nameHelp' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_nameHelp')), + 'columnHelp' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_columnHelp')) ); $pageRenderer->addInlineLanguageLabelArray($languageLabels); // Select record @@ -199,18 +214,9 @@ class BackendLayoutWizardController extends AbstractModule } } } - $pageRenderer->addExtOnReadyCode(' - t3Grid = new TYPO3.Backend.t3Grid({ - data: ' . json_encode($rows, JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS) . ', - colCount: ' . (int)$colCount . ', - rowCount: ' . (int)$rowCount . ', - targetElement: \'editor\' - }); - t3Grid.drawTable(); - '); - - $this->moduleTemplate->getPageRenderer()->addCssFile(ExtensionManagementUtility::extRelPath('backend') - . 'Resources/Public/Css/grideditor.css'); + $this->rows = $rows; + $this->colCount = (int)$colCount; + $this->rowCount = (int)$rowCount; } /** @@ -265,21 +271,18 @@ class BackendLayoutWizardController extends AbstractModule $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar(); $lang = $this->getLanguageService(); - $resourcePath = ExtensionManagementUtility::extRelPath('backend') - . 'Resources/Public/Images/BackendLayoutWizard/'; - $saveButton = $buttonBar->makeInputButton() ->setName('_savedok') ->setValue('1') ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveDoc')) - ->setOnClick('storeData(t3Grid.export2LayoutRecord());return true;') + ->setClasses('t3js-grideditor-savedok') ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-document-save', Icon::SIZE_SMALL)); $saveAndCloseButton = $buttonBar->makeInputButton() ->setName('_savedokandclose') ->setValue('1') ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveCloseDoc')) - ->setOnClick('storeData(t3Grid.export2LayoutRecord());window.close();return true;') + ->setClasses('t3js-grideditor-savedokclose') ->setIcon( $this->moduleTemplate->getIconFactory()->getIcon('actions-document-save-close', Icon::SIZE_SMALL) ); @@ -296,34 +299,51 @@ class BackendLayoutWizardController extends AbstractModule ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-document-close', Icon::SIZE_SMALL)); $buttonBar->addButton($closeButton, ButtonBar::BUTTON_POSITION_LEFT, 30); - $this->content .= ' - <table border="0" width="90%" height="90%" id="outer_container"> - <tr> - <td class="editor_cell"> - <div id="editor"> - </div> - </td> - <td width="20" valign="center"> - <a class="addCol" href="#" title="' . $lang->getLL('grid_addColumn') . '" onclick="t3Grid.addColumn(); t3Grid.drawTable(\'editor\');"> - <img src="' . $resourcePath . 't3grid-tableright.png" border="0" /> - </a><br /> - <a class="removeCol" href="#" title="' . $lang->getLL('grid_removeColumn') . '" onclick="t3Grid.removeColumn(); t3Grid.drawTable(\'editor\');"> - <img src="' . $resourcePath . 't3grid-tableleft.png" border="0" /> - </a> - </td> - </tr> - <tr> - <td colspan="2" height="20" align="center"> - <a class="addCol" href="#" title="' . $lang->getLL('grid_addRow') . '" onclick="t3Grid.addRow(); t3Grid.drawTable(\'editor\');"> - <img src="' . $resourcePath . 't3grid-tabledown.png" border="0" /> - </a> - <a class="removeCol" href="#" title="' . $lang->getLL('grid_removeRow') . '" onclick="t3Grid.removeRow(); t3Grid.drawTable(\'editor\');"> - <img src="' . $resourcePath . 't3grid-tableup.png" border="0" /> - </a> - </td> - </tr> - </table> - '; + $markup = array(); + $markup[] = ''; + $markup[] = '<table class="grideditor table table-bordered"">'; + $markup[] = ' <tr>'; + $markup[] = ' <td class="editor_cell">'; + $markup[] = ' <div id="editor" class="t3js-grideditor" data-data="' . htmlspecialchars( + json_encode( + $this->rows, + JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS + ) + ) . '" ' + . 'data-rowcount="' . (int)$this->rowCount . '" ' + . 'data-colcount="' . (int)$this->colCount . '">'; + $markup[] = ' </div>'; + $markup[] = ' </td>'; + $markup[] = ' <td>'; + $markup[] = ' <div class="btn-group-vertical">'; + $markup[] = ' <a class="btn btn-default btn-sm t3js-grideditor-addcolumn" href="#" title="' + . htmlspecialchars($lang->getLL('grid_addColumn')) . '">'; + $markup[] = ' <i class="fa fa-fw fa-arrow-right"></i>'; + $markup[] = ' </a>'; + $markup[] = ' <a class="btn btn-default btn-sm t3js-grideditor-removecolumn" href="#" title="' + . htmlspecialchars($lang->getLL('grid_removeColumn')) . '">'; + $markup[] = ' <i class="fa fa-fw fa-arrow-left"></i>'; + $markup[] = ' </a>'; + $markup[] = ' </div>'; + $markup[] = ' </td>'; + $markup[] = ' </tr>'; + $markup[] = ' <tr>'; + $markup[] = ' <td colspan="2" align="center">'; + $markup[] = ' <div class="btn-group">'; + $markup[] = ' <a class="btn btn-default btn-sm t3js-grideditor-addrow" href="#" title="' + . htmlspecialchars($lang->getLL('grid_addRow')) . '">'; + $markup[] = ' <i class="fa fa-fw fa-arrow-down"></i>'; + $markup[] = ' </a>'; + $markup[] = ' <a class="btn btn-default btn-sm t3js-grideditor-removerow" href="#" title="' + . htmlspecialchars($lang->getLL('grid_removeRow')) . '">'; + $markup[] = ' <i class="fa fa-fw fa-arrow-up"></i>'; + $markup[] = ' </a>'; + $markup[] = ' </div>'; + $markup[] = ' </td>'; + $markup[] = ' </tr>'; + $markup[] = '</table>'; + + $this->content .= implode(LF, $markup); } /** diff --git a/typo3/sysext/backend/Resources/Public/Css/grideditor.css b/typo3/sysext/backend/Resources/Public/Css/grideditor.css deleted file mode 100644 index ce087003a4c8ca4d24e94e6760b45da98d22af7e..0000000000000000000000000000000000000000 --- a/typo3/sysext/backend/Resources/Public/Css/grideditor.css +++ /dev/null @@ -1,241 +0,0 @@ -* { - padding: 0; - margin: 0; - position: relative; -} - -body { padding: 10px; } - -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(../Images/BackendLayoutWizard/t3grid-editor-right-inactive.png); - left: 46px; - top: 14px; -} - -.link_expand_right:hover { - background-image: url(../Images/BackendLayoutWizard/t3grid-editor-right.png); -} - - -.link_shrink_left { - background-image: url(../Images/BackendLayoutWizard/t3grid-editor-left-inactive.png); - left: 0px; - top: 14px; -} - -.link_shrink_left:hover { - background-image: url(../Images/BackendLayoutWizard/t3grid-editor-left.png); -} - -.link_expand_down { - background-image: url(../Images/BackendLayoutWizard/t3grid-editor-down-inactive.png); - left: 14px; - top: 46px; -} - -.link_expand_down:hover { - background-image: url(../Images/BackendLayoutWizard/t3grid-editor-down.png); -} - -.link_shrink_up { - background-image: url(../Images/BackendLayoutWizard/t3grid-editor-up-inactive.png); - left: 14px; - top: 0px; -} - -.link_shrink_up:hover { - background-image: url(../Images/BackendLayoutWizard/t3grid-editor-up.png); -} - -.link_editor { - background-image: url(../Images/BackendLayoutWizard/t3grid-edit-inactive.png); - width: 32px; - height: 32px; - left: 14px; - top: 14px; -} - -.link_editor:hover { - background-image: url(../Images/BackendLayoutWizard/t3grid-edit.png); -} - -.question { - background-image: url(../Images/BackendLayoutWizard/t3grid-layer-icon-help.png) !important; -} - -.save { - background-image: url(../Images/BackendLayoutWizard/t3grid-layer-icon-save.png) !important; -} - -.cancel { - background-image: url(../Images/BackendLayoutWizard/t3grid-layer-icon-close.png) !important; -} - -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(../Images/BackendLayoutWizard/t3grid-editor-right-inactive.png); - left: 46px; - top: 14px; -} - -.link_expand_right:hover { - background-image: url(../Images/BackendLayoutWizard/t3grid-editor-right.png); -} - - -.link_shrink_left { - background-image: url(../Images/BackendLayoutWizard/t3grid-editor-left-inactive.png); - left: 0px; - top: 14px; -} - -.link_shrink_left:hover { - background-image: url(../Images/BackendLayoutWizard/t3grid-editor-left.png); -} - -.link_expand_down { - background-image: url(../Images/BackendLayoutWizard/t3grid-editor-down-inactive.png); - left: 14px; - top: 46px; -} - -.link_expand_down:hover { - background-image: url(../Images/BackendLayoutWizard/t3grid-editor-down.png); -} - -.link_shrink_up { - background-image: url(../Images/BackendLayoutWizard/t3grid-editor-up-inactive.png); - left: 14px; - top: 0px; -} - -.link_shrink_up:hover { - background-image: url(../Images/BackendLayoutWizard/t3grid-editor-up.png); -} - -.link_editor { - background-image: url(../Images/BackendLayoutWizard/t3grid-edit-inactive.png); - width: 32px; - height: 32px; - left: 14px; - top: 14px; -} - -.link_editor:hover { - background-image: url(../Images/BackendLayoutWizard/t3grid-edit.png); -} - -.question { - background-image: url(../Images/BackendLayoutWizard/t3grid-layer-icon-help.png) !important; -} - -.save { - background-image: url(../Images/BackendLayoutWizard/t3grid-layer-icon-save.png) !important; -} - -.cancel { - background-image: url(../Images/BackendLayoutWizard/t3grid-layer-icon-close.png) !important; -} diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-edit-inactive-1.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-edit-inactive-1.png deleted file mode 100644 index 077cd7718777ac5aa1ac49d481a447516dc7cf9a..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-edit-inactive-1.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-edit-inactive.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-edit-inactive.png deleted file mode 100644 index 077cd7718777ac5aa1ac49d481a447516dc7cf9a..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-edit-inactive.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-edit.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-edit.png deleted file mode 100644 index 98a0ab12a3437ae884a3f88c690e1d7384a49ad2..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-edit.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-down-inactive.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-down-inactive.png deleted file mode 100644 index 72a6782a0179f42e349738521ad4dec32fe2be07..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-down-inactive.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-down.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-down.png deleted file mode 100644 index 13b5e706365085d3ea2ea48d600d891378420a6e..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-down.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-left-inactive.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-left-inactive.png deleted file mode 100644 index 64e32a2e6877cd798ce380eac638685cd67a6475..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-left-inactive.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-left.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-left.png deleted file mode 100644 index b68f4d5944affd7e2695777668f76dad7ee2b6ab..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-left.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-right-inactive.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-right-inactive.png deleted file mode 100644 index c67ec41db010f139e392425211751424baf822e1..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-right-inactive.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-right.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-right.png deleted file mode 100644 index 6bb63b25d53c4daf0accac146da035bcf3a5bfe3..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-right.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-up-inactive.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-up-inactive.png deleted file mode 100644 index b9438a7cde2262599573ba932e6bd696c2dd39d8..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-up-inactive.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-up.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-up.png deleted file mode 100644 index 24022ca2737de22d40d08d7e098e0b2ca569f3ac..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-editor-up.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-layer-icon-close.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-layer-icon-close.png deleted file mode 100644 index 6c52209da40c99c38e52e968d2d4f93a84a53ebb..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-layer-icon-close.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-layer-icon-help.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-layer-icon-help.png deleted file mode 100644 index b5b79e078af7c7d12ecdf61b0806675c23f6627d..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-layer-icon-help.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-layer-icon-save.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-layer-icon-save.png deleted file mode 100644 index af37bcda998fc3d9782fcc69c83ee68d00a807f2..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-layer-icon-save.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-tabledown.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-tabledown.png deleted file mode 100644 index 674e479fba7d440d6b1aff3d51515ca16441be78..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-tabledown.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-tableleft.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-tableleft.png deleted file mode 100644 index 763d37023f93bf93285e3185369cd8d57080d117..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-tableleft.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-tableright.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-tableright.png deleted file mode 100644 index e425e73921f961b8a6ce7a1780c741c684c933f1..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-tableright.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-tableup.png b/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-tableup.png deleted file mode 100644 index 056cf582669b4ddceeb926fe4b76e03d978a1d37..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/backend/Resources/Public/Images/BackendLayoutWizard/t3grid-tableup.png and /dev/null differ diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/GridEditor.js b/typo3/sysext/backend/Resources/Public/JavaScript/GridEditor.js new file mode 100644 index 0000000000000000000000000000000000000000..37783910f3e2a62c3d9b7d735f00e7e599724931 --- /dev/null +++ b/typo3/sysext/backend/Resources/Public/JavaScript/GridEditor.js @@ -0,0 +1,640 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Module: TYPO3/CMS/Backend/GridEditor + */ +define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity', 'bootstrap'], function($, Modal, Severity) { + 'use strict'; + + /** + * The main ContextHelp object + * + * @type {{colCount: number, rowCount: number, data: {}, nameLabel: string, columnLabel: string, targetElement: null}} + * @exports TYPO3/CMS/Backend/GridEditor + */ + var GridEditor = { + selectorEditor: '.t3js-grideditor', + selectorAddColumn: '.t3js-grideditor-addcolumn', + selectorRemoveColumn: '.t3js-grideditor-removecolumn', + selectorAddRow: '.t3js-grideditor-addrow', + selectorRemoveRow: '.t3js-grideditor-removerow', + selectorLinkEditor: '.t3js-grideditor-link-editor', + selectorLinkExpandRight: '.t3js-grideditor-link-expand-right', + selectorLinkShrinkLeft: '.t3js-grideditor-link-shrink-left', + selectorLinkExpandDown: '.t3js-grideditor-link-expand-down', + selectorLinkShrinkUp: '.t3js-grideditor-link-shrink-up', + selectorDocHeaderSave: '.t3js-grideditor-savedok', + selectorDocHeaderSaveClose: '.t3js-grideditor-savedokclose', + colCount: 1, + rowCount: 1, + data: [], + nameLabel: 'name', + columnLabel: 'columen label', + targetElement: null + }; + + /** + * + * @param {Object} config + */ + GridEditor.initialize = function(config) { + config = config || {}; + var $element = $(GridEditor.selectorEditor); + GridEditor.colCount = $element.data('colcount'); + GridEditor.rowCount = $element.data('rowcount'); + GridEditor.data = $element.data('data'); + GridEditor.nameLabel = config.nameLabel || 'Name'; + GridEditor.columnLabel = config.columnLabel || 'Column'; + GridEditor.targetElement = $(GridEditor.selectorEditor); + + $(document).on('click', GridEditor.selectorDocHeaderSave, function(e) { + e.preventDefault(); + storeData(GridEditor.export2LayoutRecord()); + }); + $(document).on('click', GridEditor.selectorDocHeaderSaveClose, function(e) { + e.preventDefault(); + storeData(GridEditor.export2LayoutRecord()); + window.close(); + }); + $(document).on('click', GridEditor.selectorAddColumn, function(e) { + e.preventDefault(); + GridEditor.addColumn(); + GridEditor.drawTable(); + }); + $(document).on('click', GridEditor.selectorRemoveColumn, function(e) { + e.preventDefault(); + GridEditor.removeColumn(); + GridEditor.drawTable(); + }); + $(document).on('click', GridEditor.selectorAddRow, function(e) { + e.preventDefault(); + GridEditor.addRow(); + GridEditor.drawTable(); + }); + $(document).on('click', GridEditor.selectorRemoveRow, function(e) { + e.preventDefault(); + GridEditor.removeRow(); + GridEditor.drawTable(); + }); + $(document).on('click', GridEditor.selectorLinkEditor, function(e) { + e.preventDefault(); + var $element = $(this); + var col = $element.data('col'); + var row = $element.data('row'); + GridEditor.showOptions(col, row); + }); + $(document).on('click', GridEditor.selectorLinkExpandRight, function(e) { + e.preventDefault(); + var $element = $(this); + var col = $element.data('col'); + var row = $element.data('row'); + GridEditor.addColspan(col, row); + GridEditor.drawTable(); + }); + $(document).on('click', GridEditor.selectorLinkShrinkLeft, function(e) { + e.preventDefault(); + var $element = $(this); + var col = $element.data('col'); + var row = $element.data('row'); + GridEditor.removeColspan(col, row); + GridEditor.drawTable(); + }); + $(document).on('click', GridEditor.selectorLinkExpandDown, function(e) { + e.preventDefault(); + var $element = $(this); + var col = $element.data('col'); + var row = $element.data('row'); + GridEditor.addRowspan(col, row); + GridEditor.drawTable(); + }); + $(document).on('click', GridEditor.selectorLinkShrinkUp, function(e) { + e.preventDefault(); + var $element = $(this); + var col = $element.data('col'); + var row = $element.data('row'); + GridEditor.removeRowspan(col, row); + GridEditor.drawTable(); + }); + + GridEditor.drawTable(); + }; + + /** + * Add a new row + */ + GridEditor.addRow = function() { + var newRow = []; + for (var i = 0; i < GridEditor.colCount; i++) { + newRow[i] = {spanned: false, rowspan: 1, colspan: 1}; + } + GridEditor.data.push(newRow); + GridEditor.rowCount++; + }; + + /** + * Removes the last row of the grid and adjusts all cells that might be effected + * by that change. (Removing colspans) + */ + GridEditor.removeRow = function() { + if (GridEditor.rowCount <= 1) { + return false; + } + var newData = []; + for (var rowIndex = 0; rowIndex < GridEditor.rowCount - 1; rowIndex++) { + newData.push(GridEditor.data[rowIndex]); + } + + // fix rowspan in former last row + for (var colIndex = 0; colIndex < GridEditor.colCount; colIndex++) { + if (GridEditor.data[GridEditor.rowCount - 1][colIndex].spanned == true) { + GridEditor.findUpperCellWidthRowspanAndDecreaseByOne(colIndex, GridEditor.rowCount - 1); + } + } + + GridEditor.data = newData; + GridEditor.rowCount--; + }; + + /** + * Takes a cell and looks above it if there are any cells that have colspans that + * spans 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 {Integer} col + * @param {Integer} row integer + */ + GridEditor.findUpperCellWidthRowspanAndDecreaseByOne = function(col, row) { + var upperCell = GridEditor.getCell(col, row - 1); + if (!upperCell) { + return false; + } + + if (upperCell.spanned == true) { + GridEditor.findUpperCellWidthRowspanAndDecreaseByOne(col, row - 1); + } else { + if (upperCell.rowspan > 1) { + GridEditor.removeRowspan(col, row - 1); + } + } + }; + + /** + * Removes the outermost right column from the grid. + */ + GridEditor.removeColumn = function() { + if (GridEditor.colCount <= 1) { + return false; + } + var newData = []; + + for (var rowIndex = 0; rowIndex < GridEditor.rowCount; rowIndex++) { + var newRow = []; + for (var colIndex = 0; colIndex < GridEditor.colCount - 1; colIndex++) { + newRow.push(GridEditor.data[rowIndex][colIndex]); + } + if (GridEditor.data[rowIndex][GridEditor.colCount - 1].spanned == true) { + GridEditor.findLeftCellWidthColspanAndDecreaseByOne(GridEditor.colCount - 1, rowIndex); + } + newData.push(newRow); + } + + GridEditor.data = newData; + GridEditor.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 {Integer} col + * @param {Integer} row + */ + GridEditor.findLeftCellWidthColspanAndDecreaseByOne = function(col, row) { + var leftCell = GridEditor.getCell(col - 1, row); + if (!leftCell) { + return false; + } + + if (leftCell.spanned == true) { + GridEditor.findLeftCellWidthColspanAndDecreaseByOne(col - 1, row); + } else { + if (leftCell.colspan > 1) { + GridEditor.removeColspan(col - 1, row); + } + } + }; + + /** + * Adds a column at the right side of the grid. + */ + GridEditor.addColumn = function() { + for (var rowIndex = 0; rowIndex < GridEditor.rowCount; rowIndex++) { + GridEditor.data[rowIndex].push({ + spanned: false, + rowspan: 1, + colspan: 1, + name: GridEditor.colCount + 'x' + rowIndex + }); + } + GridEditor.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. + */ + GridEditor.drawTable = function() { + var col; + var $colgroup = $('<colgroup>'); + for (col = 0; col < GridEditor.colCount; col++) { + $colgroup.append($('<col>').css({ + width: parseInt(100 / GridEditor.colCount, 10) + '%' + })); + } + var $table = $('<table id="base" class="table editor">'); + $table.append($colgroup); + + for (var row = 0; row < GridEditor.rowCount; row++) { + var rowData = GridEditor.data[row]; + if (rowData.length == 0) { + continue; + } + + var $row = $('<tr>'); + + for (col = 0; col < GridEditor.colCount; col++) { + var cell = GridEditor.data[row][col]; + if (cell.spanned == true) { + continue; + } + var $cell = $('<td>').css({ + height: parseInt(100 / GridEditor.rowCount, 10) * cell.rowspan + '%', + width: parseInt(100 / GridEditor.colCount, 10) * cell.colspan + '%' + }); + var $container = $('<div class="cell_container">'); + $cell.append($container); + var dataString = ' data-col="' + col + '" data-row="' + row + '"'; + $container.append($('<a class="t3js-grideditor-link-editor link link_editor" title="' + TYPO3.lang['editCell'] + '" ' + dataString + ' href="#"><!-- --></a>')); + if (GridEditor.cellCanSpanRight(col, row)) { + $container.append($('<a class="t3js-grideditor-link-expand-right link link_expand_right" href="#" title="' + TYPO3.lang['mergeCell'] + '" ' + dataString + '><!-- --></a>')); + } + if (GridEditor.cellCanShrinkLeft(col, row)) { + $container.append('<a class="t3js-grideditor-link-shrink-left link link_shrink_left" href="#" title="' + TYPO3.lang['splitCell'] + '" ' + dataString + '><!-- --></a>'); + } + if (GridEditor.cellCanSpanDown(col, row)) { + $container.append('<a class="t3js-grideditor-link-expand-down link link_expand_down" href="#" title="' + TYPO3.lang['mergeCell'] + '" ' + dataString + '><!-- --></a>'); + } + if (GridEditor.cellCanShrinkUp(col, row)) { + $container.append('<a class="t3js-grideditor-link-shrink-up link link_shrink_up" href="#" title="' + TYPO3.lang['splitCell'] + '" ' + dataString + '><!-- --></a>'); + } + $cell.append('<div class="cell_data">' + TYPO3.lang['name'] + ': ' + (cell.name ? GridEditor.stripMarkup(cell.name) : TYPO3.lang['notSet']) + + '<br />' + TYPO3.lang['column'] + ': ' + + (cell.column === undefined ? TYPO3.lang['notSet'] : parseInt(cell.column, 10)) + '</div>'); + + if (cell.colspan > 1) { + $cell.attr('colspan', cell.colspan); + } + if (cell.rowspan > 1) { + $cell.attr('rowspan', cell.rowspan); + } + $row.append($cell); + } + $table.append($row); + } + $(GridEditor.targetElement).empty().append($table); + }; + + /** + * Sets the name of a certain grid element. + * + * @param {String} newName + * @param {Integer} col + * @param {Integer} row + * + * @returns {Boolean} + */ + GridEditor.setName = function(newName, col, row) { + var cell = GridEditor.getCell(col, row); + if (!cell) return false; + cell.name = GridEditor.stripMarkup(newName); + return true; + }; + + /** + * Sets the column field for a certain grid element. This is NOT the column of the + * element itself. + * + * @param {Integer} newColumn + * @param {Integer} col + * @param {Integer} row + * + * @returns {Boolean} + */ + GridEditor.setColumn = function(newColumn, col, row) { + var cell = GridEditor.getCell(col, row); + if (!cell) { + return false; + } + cell.column = GridEditor.stripMarkup(newColumn); + return true; + }; + + /** + * Creates an ExtJs Window with two input fields and shows it. On save, the data + * is written into the grid element. + * + * @param {Integer} col + * @param {Integer} row + * + * @returns {Boolean} + */ + GridEditor.showOptions = function(col, row) { + var cell = GridEditor.getCell(col, row); + if (!cell) { + return false; + } + + var $markup = $('<div>'); + $markup.append( + '<div>' + + '<div class="form-group">' + + '<label>' + TYPO3.lang['nameHelp'] + '</label>' + + '<input type="text" class="t3js-grideditor-field-name form-control" name="name" value="' + (GridEditor.stripMarkup(cell.name) || '') + '">' + + '</div>' + + '<div class="form-group">' + + '<label>' + TYPO3.lang['columnHelp'] + '</label>' + + '<input type="text" class="t3js-grideditor-field-colpos form-control" name="name" value="' + (parseInt(cell.column, 10) || '') + '">' + + '</div>' + + '</div>' + ); + var $modal = Modal.show(TYPO3.lang['title'], $markup, Severity.notice, [ + { + text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel', + active: true, + btnClass: 'btn-default', + name: 'cancel' + }, + { + text: $(this).data('button-ok-text') || TYPO3.lang['button.ok'] || 'OK', + btnClass: 'btn-' + Modal.getSeverityClass(Severity.notice), + name: 'ok' + } + ]); + $modal.data('col', col); + $modal.data('row', row); + $modal.on('button.clicked', function(e) { + if (e.target.name === 'cancel') { + $(this).trigger('modal-dismiss'); + } else if (e.target.name === 'ok') { + GridEditor.setName($modal.find('.t3js-grideditor-field-name').val(), $modal.data('col'), $modal.data('row')); + GridEditor.setColumn($modal.find('.t3js-grideditor-field-colpos').val(), $modal.data('col'), $modal.data('row')); + GridEditor.drawTable(); + $(this).trigger('modal-dismiss'); + } + }); + }; + + /** + * Returns a cell element from the grid. + * + * @param {Integer} col + * @param {Integer} row + * @returns {Object} + */ + GridEditor.getCell = function(col, row) { + if (col > GridEditor.colCount - 1) { + return false; + } + if (row > GridEditor.rowCount - 1) { + return false; + } + return GridEditor.data[row][col]; + }; + + /** + * Checks whether 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 {Integer} col + * @param {Integer} row + * @returns {Boolean} + */ + GridEditor.cellCanSpanRight = function(col, row) { + if (col == GridEditor.colCount - 1) { + return false; + } + + var cell = GridEditor.getCell(col, row); + var checkCell; + if (cell.rowspan > 1) { + for (var rowIndex = row; rowIndex < row + cell.rowspan; rowIndex++) { + checkCell = GridEditor.getCell(col + cell.colspan, rowIndex); + if (!checkCell || checkCell.spanned == true || checkCell.colspan > 1 || checkCell.rowspan > 1) { + return false; + } + } + } else { + checkCell = GridEditor.getCell(col + cell.colspan, row); + if (!checkCell || cell.spanned == true || checkCell.spanned == true || checkCell.colspan > 1 || checkCell.rowspan > 1) { + return false; + } + } + + return true; + }; + + /** + * Checks whether a cell can span down or not. + * + * @param {Integer} col + * @param {Integer} row + * @returns {Boolean} + */ + GridEditor.cellCanSpanDown = function(col, row) { + if (row == GridEditor.rowCount - 1) { + return false; + } + + var cell = GridEditor.getCell(col, row); + var checkCell; + 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++) { + checkCell = GridEditor.getCell(colIndex, row + cell.rowspan); + if (!checkCell || checkCell.spanned == true || checkCell.colspan > 1 || checkCell.rowspan > 1) { + return false; + } + } + } else { + checkCell = GridEditor.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 {Integer} col + * @param {Integer} row + * @returns {Boolean} + */ + GridEditor.cellCanShrinkLeft = function(col, row) { + return (GridEditor.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 {Integer} col + * @param {Integer} row + * @returns {Boolean} + */ + GridEditor.cellCanShrinkUp = function(col, row) { + return (GridEditor.data[row][col].rowspan > 1); + }; + + /** + * Adds a colspan to a grid element. + * + * @param {Integer} col + * @param {Integer} row + * @returns {Boolean} + */ + GridEditor.addColspan = function(col, row) { + var cell = GridEditor.getCell(col, row); + if (!cell || !GridEditor.cellCanSpanRight(col, row)) { + return false; + } + + for (var rowIndex = row; rowIndex < row + cell.rowspan; rowIndex++) { + GridEditor.data[rowIndex][col + cell.colspan].spanned = true; + } + cell.colspan += 1; + }; + + /** + * Adds a rowspan to grid element. + * + * @param {Integer} col + * @param {Integer} row + * @returns {Boolean} + */ + GridEditor.addRowspan = function(col, row) { + var cell = GridEditor.getCell(col, row); + if (!cell || !GridEditor.cellCanSpanDown(col, row)) { + return false; + } + + for (var colIndex = col; colIndex < col + cell.colspan; colIndex++) { + GridEditor.data[row + cell.rowspan][colIndex].spanned = true; + } + cell.rowspan += 1; + }; + + /** + * Removes a colspan from a grid element. + * + * @param {Integer} col + * @param {Integer} row + * @returns {Boolean} + */ + GridEditor.removeColspan = function(col, row) { + var cell = GridEditor.getCell(col, row); + if (!cell || !GridEditor.cellCanShrinkLeft(col, row)) { + return false; + } + + cell.colspan -= 1; + for (var rowIndex = row; rowIndex < row + cell.rowspan; rowIndex++) { + GridEditor.data[rowIndex][col + cell.colspan].spanned = false; + } + }; + + /** + * Removes a rowspan from a grid element. + * + * @param {Integer} col + * @param {Integer} row + * @returns {Boolean} + */ + GridEditor.removeRowspan = function(col, row) { + var cell = GridEditor.getCell(col, row); + if (!cell || !GridEditor.cellCanShrinkUp(col, row)) { + return false; + } + + cell.rowspan -= 1; + for (var colIndex = col; colIndex < col + cell.colspan; colIndex++) { + GridEditor.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. + * + * @returns {String} + */ + GridEditor.export2LayoutRecord = function() { + var result = "backend_layout {\n\tcolCount = " + GridEditor.colCount + "\n\trowCount = " + GridEditor.rowCount + "\n\trows {\n"; + for (var row = 0; row < GridEditor.rowCount; row++) { + result += "\t\t" + (row + 1) + " {\n"; + result += "\t\t\tcolumns {\n"; + var colIndex = 0; + for (var col = 0; col < GridEditor.colCount; col++) { + var cell = GridEditor.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; + }; + + /** + * + * @param {String} input + * @returns {*|jQuery} + */ + GridEditor.stripMarkup = function(input) { + return $('<p>' + input + '</p>').text(); + }; + + GridEditor.initialize(); + return GridEditor; +}); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/grideditor.js b/typo3/sysext/backend/Resources/Public/JavaScript/grideditor.js deleted file mode 100644 index 79c8c3d2d715b10e2669cf198760f385cc7fdfb7..0000000000000000000000000000000000000000 --- a/typo3/sysext/backend/Resources/Public/JavaScript/grideditor.js +++ /dev/null @@ -1,635 +0,0 @@ -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * 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. - */ -Ext.namespace('TYPO3.Backend.t3Grid'); - -TYPO3.Backend.t3Grid = Ext.extend(Ext.Component, { - - 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 - * spans 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%', - cls: '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, 10) + '%' - }); - } - 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 + '" title="' + TYPO3.l10n.localize('editCell') + '" href="#"><!-- --></a>'; - if (this.cellCanSpanRight(col, row)) { - cellHtml += '<a href="#" id="r_' - + col + '_' + row + '" title="' + TYPO3.l10n.localize('mergeCell') + '" class="link_expand_right"><!-- --></a>'; - } - if (this.cellCanShrinkLeft(col, row)) { - cellHtml += '<a href="#" id="l_' - + col + '_' + row + '" title="' + TYPO3.l10n.localize('splitCell') + '" class="link_shrink_left"><!-- --></a>'; - } - if (this.cellCanSpanDown(col, row)) { - cellHtml += '<a href="#" id="d_' - + col + '_' + row + '" title="' + TYPO3.l10n.localize('mergeCell') + '" class="link_expand_down"><!-- --></a>'; - } - if (this.cellCanShrinkUp(col, row)) { - cellHtml += '<a href="#" id="u_' - + col + '_' + row + '" title="' + TYPO3.l10n.localize('splitCell') + '" class="link_shrink_up"><!-- --></a>'; - } - cellHtml += '</div>'; - - cellHtml += '<div class="cell_data">' + TYPO3.l10n.localize('name') + ': ' + (cell.name ? Ext.util.Format.htmlEncode(cell.name) : TYPO3.l10n.localize('notSet')) - + '<br />' + TYPO3.l10n.localize('column') + ': ' - + (cell.column === undefined ? TYPO3.l10n.localize('notSet') : parseInt(cell.column, 10)) + '</div>'; - - // create cells - var child = { - tag: 'td', - height: parseInt(100 / this.rowCount, 10) * cell.rowspan + '%', - width: parseInt(100 / this.colCount, 10) * 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.l10n.localize('name'), - name: 'name', - width: 270, - value: cell.name, - tabIndex: 1, - listeners: { - render: function(c) { - c.getEl().set({ - 'data-toggle': 'tooltip', - 'data-placement': 'bottom', - 'data-title': TYPO3.l10n.localize('nameHelp') - }); - }, - afterrender: function(cmp) { - TYPO3.Tooltip.initialize('[data-toggle="tooltip"]'); - } - } - }); - - var fieldColumn = new Ext.form.NumberField({ - fieldLabel: TYPO3.l10n.localize('column'), - name: 'column', - width: 50, - value: cell.column, - tabIndex: 2, - listeners: { - render: function(c) { - c.getEl().set({ - 'data-toggle': 'tooltip', - 'data-placement': 'bottom', - 'data-title': TYPO3.l10n.localize('columnHelp') - }); - }, - afterrender: function(cmp) { - TYPO3.Tooltip.initialize('[data-toggle="tooltip"]'); - } - } - }); - - win = new Ext.Window({ - layout: 'fit', - title: TYPO3.l10n.localize('title'), - width: 400, - 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.l10n.localize('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 whether 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 whether 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 = "backend_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/t3skin/Resources/Public/Css/backend.css b/typo3/sysext/t3skin/Resources/Public/Css/backend.css index 5b3277582134a1bb8e1f8d5a0269adbcfc1f9bed..0c7b2666d5ac6787226c276fd10b42bbf139520a 100644 --- a/typo3/sysext/t3skin/Resources/Public/Css/backend.css +++ b/typo3/sysext/t3skin/Resources/Public/Css/backend.css @@ -12029,6 +12029,107 @@ span.warningboxheader { padding-bottom: 30px; margin: 0 15px 30px 15px; } +.grideditor td { + vertical-align: middle; +} +.grideditor td.editor_cell { + height: 100%; +} +.grideditor table.editor { + border-right: 1px gray dashed; + border-bottom: 1px gray dashed; +} +.grideditor table.editor td { + vertical-align: middle; + border-top: 1px gray dashed; + border-left: 1px gray dashed; + text-align: center; + background-color: white; + min-height: 100px; +} +.grideditor div#editor { + height: 100%; +} +.grideditor div.cell_container { + width: 80px; + height: 80px; + position: relative; + left: 50%; + margin-left: -30px; + opacity: 0.3; +} +.grideditor div.cell_container:hover { + opacity: 0.5; +} +.grideditor .link { + display: block; + position: absolute; + width: 20px; + height: 40px; + overflow: hidden; + opacity: 0.5; +} +.grideditor .link:hover { + text-decoration: none; + opacity: 1; +} +.grideditor .link_expand_down, +.grideditor .link_shrink_up { + width: 40px; + height: 20px; +} +.grideditor .link_expand_right { + left: 52px; + top: 0; +} +.grideditor .link_expand_right:before { + font-family: FontAwesome; + content: "\f0da"; + font-size: 42px; + line-height: 42px; +} +.grideditor .link_shrink_left { + left: -8px; + top: 0; +} +.grideditor .link_shrink_left:before { + font-family: FontAwesome; + content: "\f0d9"; + font-size: 42px; + line-height: 42px; +} +.grideditor .link_expand_down { + left: 12px; + top: 40px; +} +.grideditor .link_expand_down:before { + font-family: FontAwesome; + content: "\f0d7"; + font-size: 42px; + line-height: 19px; +} +.grideditor .link_shrink_up { + left: 12px; + top: -20px; +} +.grideditor .link_shrink_up:before { + font-family: FontAwesome; + content: "\f0d8"; + font-size: 42px; + line-height: 20px; +} +.grideditor .link_editor { + width: 40px; + height: 40px; + left: 12px; + top: 0; +} +.grideditor .link_editor:before { + font-family: FontAwesome; + content: "\f14b"; + font-size: 42px; + line-height: 42px; +} *::-ms-clear { display: none; }