From 8483eb2330396f550951d80eaab8636b77d6b6a5 Mon Sep 17 00:00:00 2001 From: zauberfisch Date: Tue, 15 Nov 2016 05:37:57 +0000 Subject: [PATCH] init --- .editorconfig | 17 + .gitattributes | 1 + .htaccess | 3 + LICENSE | 17 + README.md | 97 ++++ _config.php | 4 + _config/config.yml | 7 + code/HtmlEditorField.php | 29 ++ code/PageBuilder_CompositeField.php | 8 + code/PageBuilder_DBField.php | 7 + code/PageBuilder_Field/PageBuilder_Field.php | 187 ++++++++ .../PageBuilder_Field_Handler.php | 17 + .../PageBuilder_Field_Handler_Block.php | 67 +++ ...geBuilder_Field_Handler_ContentElement.php | 82 ++++ code/PageBuilder_LeftAndMainExtension.php | 16 + .../PageBuilder_ContentElement.php | 23 + .../PageBuilder_Value_Block.php | 160 +++++++ .../PageBuilder_Value_Block_BlockGroup.php | 99 ++++ ...ageBuilder_Value_Block_BlockGroup_Base.php | 22 + ...PageBuilder_Value_Block_ContentElement.php | 70 +++ composer.json | 21 + css/PageBuilder.scss.css | 418 ++++++++++++++++ docs/example.md | 447 ++++++++++++++++++ images/reorder.png | Bin 0 -> 306 bytes javascript/PageBuilder.js | 264 +++++++++++ javascript/PageBuilderDialog.js | 94 ++++ lang/de.yml | 21 + lang/en.yml | 21 + scss/PageBuilder.scss | 191 ++++++++ templates/PageBuilder_CompositeField.ss | 6 + .../PageBuilder_CompositeField_holder.ss | 6 + templates/PageBuilder_Field_holder.ss | 16 + .../PageBuilder_Value_Block.ss | 5 + .../PageBuilder_Value_Block_BlockGroup.ss | 7 + .../PageBuilder_Value_Block_ContentElement.ss | 5 + 35 files changed, 2455 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .htaccess create mode 100644 LICENSE create mode 100644 README.md create mode 100644 _config.php create mode 100644 _config/config.yml create mode 100644 code/HtmlEditorField.php create mode 100644 code/PageBuilder_CompositeField.php create mode 100644 code/PageBuilder_DBField.php create mode 100644 code/PageBuilder_Field/PageBuilder_Field.php create mode 100644 code/PageBuilder_Field/PageBuilder_Field_Handler.php create mode 100644 code/PageBuilder_Field/PageBuilder_Field_Handler_Block.php create mode 100644 code/PageBuilder_Field/PageBuilder_Field_Handler_ContentElement.php create mode 100644 code/PageBuilder_LeftAndMainExtension.php create mode 100644 code/PageBuilder_Value/PageBuilder_ContentElement.php create mode 100644 code/PageBuilder_Value/PageBuilder_Value_Block.php create mode 100644 code/PageBuilder_Value/PageBuilder_Value_Block_BlockGroup.php create mode 100644 code/PageBuilder_Value/PageBuilder_Value_Block_BlockGroup_Base.php create mode 100644 code/PageBuilder_Value/PageBuilder_Value_Block_ContentElement.php create mode 100644 composer.json create mode 100644 css/PageBuilder.scss.css create mode 100644 docs/example.md create mode 100644 images/reorder.png create mode 100644 javascript/PageBuilder.js create mode 100644 javascript/PageBuilderDialog.js create mode 100644 lang/de.yml create mode 100644 lang/en.yml create mode 100644 scss/PageBuilder.scss create mode 100644 templates/PageBuilder_CompositeField.ss create mode 100644 templates/PageBuilder_CompositeField_holder.ss create mode 100644 templates/PageBuilder_Field_holder.ss create mode 100644 templates/PageBuilder_Value_Block/PageBuilder_Value_Block.ss create mode 100644 templates/PageBuilder_Value_Block/PageBuilder_Value_Block_BlockGroup.ss create mode 100644 templates/PageBuilder_Value_Block/PageBuilder_Value_Block_ContentElement.ss diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..9857e47 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,17 @@ +# For more information about the properties used in this file, +# please see the EditorConfig documentation: +# http://editorconfig.org + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = tab +insert_final_newline = true +trim_trailing_whitespace = true + +[{*.yml,package.json}] +indent_size = 2 + +# The indent size used in the package.json file cannot be changed: +# https://github.com/npm/npm/pull/3180#issuecomment-16336516 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..587fe77 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +/docs export-ignore diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..fad44cc --- /dev/null +++ b/.htaccess @@ -0,0 +1,3 @@ + + Deny from all + \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0b99800 --- /dev/null +++ b/LICENSE @@ -0,0 +1,17 @@ +Copyright (c) 2016, Zauberfisch - www.zauberfisch.at +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of SilverStripe nor the names of its contributors may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..39bd2cf --- /dev/null +++ b/README.md @@ -0,0 +1,97 @@ +# SilverStripe PageBuilder module + +SilverStripe module to allow for modular, block based, content in SilverStripe + +**WARNING: this module is still work in progress and may not be suitable for production yet.** + +**Major API changes are more than likely** + +## Maintainer Contact + +* Zauberfisch + +## Requirements + +* silverstripe/framework >=3.5 +* zauberfisch/silverstripe-serialized-dataobject >=1.0 + +## Installation + +* `composer require "zauberfisch/silverstripe-page-builder"` +* Optional: install suggested packages + + composer require "zauberfisch/silverstripe-page-builder-basic-blocks" + +* rebuild manifest (flush) +* Unfortunately a bug in SilverStripe current breaks the HTMLEditorField file management + inside a sub controller within the CMS, to work around this bug the following work around is required: + + In your project `.htaccess` replace `RewriteRule .* framework/main.php?url=%1 [QSA]` with + `RewriteRule .* index.php?url=%1 [QSA]` and create an `index.php` file (you can replace the default + SilverStripe file if your server supports mod_rewrite) with the following content: + + is mistaken for a Page ID by LeftAndMain + # lets replace ID with FileID which is then converted back in PageBuilder + $match = true; + $url = $_GET['url']; + foreach(['PageBuilder', 'EditorToolbar', 'viewfile'] as $str) { + if (strpos($url, $str) === FALSE) { + $match = false; + break; + } + } + if ($match) { + $id = $_GET['ID']; + $_GET['url'] = str_replace(['?ID=','&ID='],['?FileID=','&FileID='], $url); + $_REQUEST['FileID'] = $id; + $_GET['FileID'] = $id; + unset($_REQUEST['ID']); + unset($_GET['ID']); + } + } + + chdir('framework'); + require 'framework/main.php'; + +## Documentation + +Add the PageBuilder DB Field and FormField to any DataObject, for example Page: + + class Page extends SiteTree { + private static $db = [ + 'PageBuilder' => 'PageBuilder_DBField', + ]; + + public function getCMSFields() { + $fields = parent::getCMSFields(); + $fields->addFieldsToTab('Root.Main', [ + new PageBuilder_Field('PageBuilder', $this->fieldLabel('PageBuilder')), + ]); + return $fields; + } + } + +Now, in your template, you can access $PageBuilder and output the content: + + <% if $PageBuilder %> +
+ $PageBuilder.Value +
+ <% end_if %> + +See [docs/example.md](docs/example.md) for example project files with some basic frontend. + +However, in the bare installation this module does not provide any content types. +It just provides the abstract classes and form fields. +Just like with SilverStripe DataObjects it is up to the individual developer and +other modules to define the desired data types. +A good starting point with some basic block types can be found in the +[basic blocks module](https://packagist.org/packages/zauberfisch/silverstripe-page-builder-basic-blocks). + +Documentation for creating custom blocks has not been written yet, please refer +to the [basic blocks module](https://packagist.org/packages/zauberfisch/silverstripe-page-builder-basic-blocks), +they should serve as good examples. diff --git a/_config.php b/_config.php new file mode 100644 index 0000000..53dae80 --- /dev/null +++ b/_config.php @@ -0,0 +1,4 @@ +getVars(), + $request->postVars(), + ]; + foreach($data as &$arr) { + if (isset($arr['FileID'])) { + $arr['ID'] = $arr['FileID']; + unset($arr['FileID']); + } + } + $request = new SS_HTTPRequest($request->httpMethod(), $request->getURL(), $data[0], $data[1], $request->getBody()); + return parent::viewfile($request); + } + +} diff --git a/code/PageBuilder_CompositeField.php b/code/PageBuilder_CompositeField.php new file mode 100644 index 0000000..a0e87be --- /dev/null +++ b/code/PageBuilder_CompositeField.php @@ -0,0 +1,8 @@ +setAttribute() values + * @author zauberfisch + */ +class PageBuilder_CompositeField extends CompositeField { +} \ No newline at end of file diff --git a/code/PageBuilder_DBField.php b/code/PageBuilder_DBField.php new file mode 100644 index 0000000..06f9747 --- /dev/null +++ b/code/PageBuilder_DBField.php @@ -0,0 +1,7 @@ +addExtraClass('stacked'); + } + + public function setValue($val) { + if (is_a($val, 'PageBuilder_DBField')) { + $this->value = $val; + } else { + $this->value = new PageBuilder_DBField(); + $this->value->setValue('', null, true); + if ($val) { + // value is an array after form submission, lets turn it into an object + if (is_array($val)) { + $this->value->setValue($this->createValueFromArray($val)); + } elseif (is_string($val)) { + $this->value->setValue($val); + } else { + throw new Exception('unexpected value'); + } + } + } + return $this; + } + + public function Value() { + $return = parent::Value(); + if (!$return) { + $this->setValue(null); + $return = parent::Value(); + } + return $return; + } + + public function createValueFromArray($array) { + $baseUID = ''; + $base = null; + $blocksByParent = []; + foreach ($array as $uid => $blockArray) { + if (isset($blockArray['ClassName'])) { + if (!in_array($blockArray['ClassName'], ClassInfo::subclassesFor('PageBuilder_Value_Block'))) { + throw new Exception(sprintf('Invalid class name "%s"', $blockArray['ClassName'])); + } + /** @var PageBuilder_Value_Block $block */ + $block = new $blockArray['ClassName'](); + $block->update($blockArray); + //$blocks[$uid] = $block; + $parentUID = $blockArray['BlockParent']; + if (!$parentUID) { + $baseUID = $uid; + $base = $block; + } else { + if (!isset($blocksByParent[$parentUID])) { + $blocksByParent[$parentUID] = []; + } + $blocksByParent[$parentUID][$blockArray['BlockPosition']] = [ + 'UID' => $uid, + 'Block' => $block, + ]; + } + } + } + if (!$base) { + throw new Exception('PageBuilder is missing the base block'); + } + /** + * @param PageBuilder_Value_Block_BlockGroup $parent + * @param array $blocks + * @return PageBuilder_Value_Block_BlockGroup + */ + $nestBlock = function ($parent, $blocks) use ($blocksByParent, &$nestBlock) { + ksort($blocks); + $_blocks = []; + foreach ($blocks as $childBlock) { + //$childBlock['Block']->setMaxWidthDesktop($parent->getWidthDesktop()); + //$childBlock['Block']->setMaxWidthTablet($parent->getWidthTablet()); + $childBlock['Block']->setWidthDesktop(min( + $childBlock['Block']->getWidthDesktop(), + $parent->getWidthDesktop() + )); + $childBlock['Block']->setWidthTablet(min( + $childBlock['Block']->getWidthTablet(), + $parent->getWidthTablet() + )); + if (isset($blocksByParent[$childBlock['UID']])) { + $_blocks[] = $nestBlock($childBlock['Block'], $blocksByParent[$childBlock['UID']]); + } else { + $_blocks[] = $childBlock['Block']; + } + } + $parent->setBlocks(new SerializedDataList($_blocks)); + return $parent; + }; + if (isset($blocksByParent[$baseUID])) { + $base = $nestBlock($base, $blocksByParent[$baseUID]); + } + return $base; + } + + public function getAttributes() { + return $this->attributes; + } + + public function FieldHolder($properties = []) { + $this->addExtraClass('PageBuilder_Field'); + $this->setAttribute('data-name', $this->getName()); + $this->setAttribute('data-grid-mode', 'desktop'); + $this->setAttribute('data-config', json_encode([ + 'urls' => [ + 'add' => $this->Link('handleBlock/add'), + 'edit-content-element' => $this->Link('handleContentElement'), + //'group' => [ + // 'create' => $this->Link('handleGroup/createNew'), + // 'createFromTemplate' => $this->Link('handleGroup/createFromTemplate'), + ////'createFromTemplate' => $this->Link('newFromTemplate'), + //], + //'block' => [ + // 'create' => $this->Link('handleBlock'), + // 'edit' => $this->Link('handleBlock/edit'), + //], + ], + ])); + return parent::FieldHolder($properties); + } + + public function Field($properties = []) { + $val = $this->Value(); + if ($val && is_a($val->getValue(), 'PageBuilder_Value_Block_BlockGroup_Base')) { + /** @var PageBuilder_Value_Block_BlockGroup_Base $baseBlock */ + $baseBlock = $val->getValue(); + return $baseBlock->getPageBuilderFields($this->getName()); + //foreach ($val->getValue() as $i => $group) { + // /** @var PageBuilder_Value_BlockGroup_Grid $group */ + // $groupsFields[] = $group->getPageBuilderGridFields($this->getName(), $i); + //} + } + throw new Exception('PageBuilder_Field does not have a base block'); + //return new LiteralField($this->getName(), ''); + + //return (new PageBuilder_CompositeField([ + // (new PageBuilder_CompositeField($groupsFields)) + // ->addExtraClass('PageBuilder_Field-BlockGroups'), + // (new FormAction(sprintf('%s[groups][%s]', $this->getName(), 'add'), _t('PageBuilder_Field.BlockGroup-Add', 'add new block group'))) + // ->setUseButtonTag(true) + // ->addExtraClass('PageBuilder_Field-BlockGroup-Add') + // ->addExtraClass('font-icon-plus'), + //])) + // ->addExtraClass('PageBuilder_Field') + // ->addExtraClass('PageBuilder_Field_HasMany') + // ->setAttribute('data-config', json_encode([ + // 'urls' => [ + // 'group' => [ + // 'create' => $this->Link('handleGroup/createNew'), + // 'createFromTemplate' => $this->Link('handleGroup/createFromTemplate'), + // //'createFromTemplate' => $this->Link('newFromTemplate'), + // ], + // 'block' => [ + // 'create' => $this->Link('handleBlock'), + // 'edit' => $this->Link('handleBlock/edit'), + // ], + // ], + // ])); + } + + public function saveInto(DataObjectInterface $record) { + $record->{$this->name} = $this->Value(); + } + + private static $allowed_actions = [ + 'handleBlock', + 'handleContentElement', + ]; + + public function handleBlock(SS_HTTPRequest $r) { + return new PageBuilder_Field_Handler_Block($this); + } + + public function handleContentElement(SS_HTTPRequest $r) { + return new PageBuilder_Field_Handler_ContentElement($this); + } +} diff --git a/code/PageBuilder_Field/PageBuilder_Field_Handler.php b/code/PageBuilder_Field/PageBuilder_Field_Handler.php new file mode 100644 index 0000000..bfb39a3 --- /dev/null +++ b/code/PageBuilder_Field/PageBuilder_Field_Handler.php @@ -0,0 +1,17 @@ +parent; + } + + public function __construct($parent) { + $this->parent = $parent; + parent::__construct(); + } +} diff --git a/code/PageBuilder_Field/PageBuilder_Field_Handler_Block.php b/code/PageBuilder_Field/PageBuilder_Field_Handler_Block.php new file mode 100644 index 0000000..0178745 --- /dev/null +++ b/code/PageBuilder_Field/PageBuilder_Field_Handler_Block.php @@ -0,0 +1,67 @@ +parent->Link(), '/handleBlock/', $action); + } + + public function Add(SS_HTTPRequest $r) { + return json_encode([ + 'html' => $this->AddForm()->loadDataFrom([ + 'BlockPosition' => $r->requestVar('BlockPosition'), + 'BlockParent' => $r->requestVar('BlockParent'), + ])->forTemplate()->forTemplate(), + ]); + } + + /** + * @return Form + */ + public function AddForm() { + $classes = []; + foreach (ClassInfo::subclassesFor('PageBuilder_Value_Block') as $class) { + if (!in_array($class, ['PageBuilder_Value_Block', 'PageBuilder_Value_Block_BlockGroup_Base', 'PageBuilder_Value_Block_ContentElement'])) { + $classes[$class] = singleton($class)->i18n_singular_name(); + } + } + return (new Form( + $this, + __FUNCTION__, + new FieldList([ + new HiddenField('BlockPosition', ''), + new HiddenField('BlockParent', ''), + new OptionsetField('ClassName', _t('PageBuilder_Field_Handler_Block.AddFormClassName', 'Class name'), $classes), + ]), + new FieldList([ + new FormAction('AddFormSubmit', _t('PageBuilder_Field_Handler_Block.AddFormSubmit', 'add')), + ]), + new RequiredFields(['AddClassName']) + ))->disableSecurityToken()->addExtraClass('PageBuilderDialog-Form'); + } + + public function AddFormSubmit($data) { + $class = $data['ClassName']; + /** @var PageBuilder_Value_Block $obj */ + $obj = new $class(); + if ($obj->hasMethod('onAfterCreate')) { + $obj->onAfterCreate(); + } + return json_encode([ + 'DialogEnd' => [ + 'html' => (string)$obj->getPageBuilderFields($this->getParent()->getName(), $data['BlockPosition'], $data['BlockParent'])->FieldHolder(), + ], + ]); + } +} diff --git a/code/PageBuilder_Field/PageBuilder_Field_Handler_ContentElement.php b/code/PageBuilder_Field/PageBuilder_Field_Handler_ContentElement.php new file mode 100644 index 0000000..3d0bf33 --- /dev/null +++ b/code/PageBuilder_Field/PageBuilder_Field_Handler_ContentElement.php @@ -0,0 +1,82 @@ + '$Action', + ]; + private static $allowed_actions = [ + 'Form', + 'PageBuilderPreview', + 'EditorToolbar', + ]; + protected $_contentElement; + + public function getContentElementID() { + return $this->getRequest()->param('ContentElementID'); + } + + /** + * @return PageBuilder_ContentElement + */ + public function getContentElement() { + if (!$this->_contentElement && $this->getContentElementID()) { + $obj = PageBuilder_ContentElement::get()->byID($this->getContentElementID()); + if ($obj && $obj->exists()) { + $this->_contentElement = $obj; + } + } + return $this->_contentElement; + } + + /** + * @param string $action + * @return string + */ + public function Link($action = null) { + return Controller::join_links($this->getParent()->Link('handleContentElement'), $this->getContentElementID(), $action); + } + + public function index(SS_HTTPRequest $r) { + $dummy = new LeftAndMain(); + $dummy->response = new SS_HTTPResponse(); + $dummy->init(); + HtmlEditorConfig::require_js(); + // not using json because editing uses an iframe + return $this->customise([ + 'Content' => $this->EditorToolbar()->forTemplate(), + ])->renderWith('CMSDialog'); + } + + public function Form() { + $obj = $this->getContentElement(); + $fields = $obj->getPageBuilderPopupFields(); + return (new Form( + $this, + __FUNCTION__, + $fields, + new FieldList([ + (new FormAction('EditContentElementSubmit', _t('PageBuilder_Field_Handler_ContentElement.Submit', 'save'))) + ->addExtraClass('ss-ui-action-constructive icon-accept'), + ]) + ))->disableSecurityToken()->loadDataFrom($obj)->setAttribute('style', 'padding: 20px;'); + } + + public function EditContentElementSubmit($data, Form $f) { + $obj = $this->getContentElement(); + $f->saveInto($obj); + $obj->write(); + $f->sessionMessage(_t('PageBuilder_Field_Handler_ContentElement.SubmitSuccess', 'saved'), 'good'); + return Controller::curr()->redirectBack(); + } + + public function PageBuilderPreview() { + return $this->getContentElement()->PageBuilderPreview(); + } + + /** + * @return PageBuilderHtmlEditorField_Toolbar + */ + public function EditorToolbar() { + return PageBuilderHtmlEditorField_Toolbar::create($this, "EditorToolbar"); + } +} diff --git a/code/PageBuilder_LeftAndMainExtension.php b/code/PageBuilder_LeftAndMainExtension.php new file mode 100644 index 0000000..030fd25 --- /dev/null +++ b/code/PageBuilder_LeftAndMainExtension.php @@ -0,0 +1,16 @@ +class, '', __CLASS__); + if (!$templates) { + throw new Exception("No template found for {$this->class}"); + } + return $this->renderWith($templates); + } + + public function PageBuilderPreview() { + return $this->getTitle(); + } +} diff --git a/code/PageBuilder_Value/PageBuilder_Value_Block.php b/code/PageBuilder_Value/PageBuilder_Value_Block.php new file mode 100644 index 0000000..d6a030d --- /dev/null +++ b/code/PageBuilder_Value/PageBuilder_Value_Block.php @@ -0,0 +1,160 @@ +name) { + $this->name = uniqid(); + } + return $this->name; + } + + public function getNamePrefixed($prefix) { + return sprintf('%s[%s]', $prefix, $this->getName()); + } + + public function getNameForField($prefix, $fieldName) { + return sprintf('%s[%s]', $this->getNamePrefixed($prefix), $fieldName); + } + + public function i18n_singular_name() { + return _t("{$this->class}.SINGULARNAME", FormField::name_to_label(str_replace('PageBuilder_Value_Block_', '', $this->class))); + } + + public function i18n_plural_name() { + $name = FormField::name_to_label(str_replace('PageBuilder_Value_Block_', '', $this->class)); + //if the penultimate character is not a vowel, replace "y" with "ies" + if (preg_match('/[^aeiou]y$/i', $name)) { + $name = substr($name, 0, -1) . 'ie'; + } + return _t("{$this->class}.PLURALNAME", $name . 's'); + } + + /** + * @param string $prefix + * @param int $blockPosition + * @param string $parent + * @return PageBuilder_CompositeField + */ + public function getPageBuilderFields($prefix, $blockPosition = 0, $parent = null) { + $classes = []; + foreach (array_reverse(ClassInfo::ancestry($this->class)) as $class) { + $classes[] = $class; + if ($class == __CLASS__) { + break; + } + } + return (new PageBuilder_CompositeField([ + (new LabelField($this->getNameForField($prefix, 'ClassNameInfo'), $this->i18n_singular_name())) + ->addExtraClass('PageBuilder_Value_Block-ClassNameInfo'), + (new PageBuilder_CompositeField([ + (new FormAction($this->getNameForField($prefix, 'EditColumns'), '')) + ->setUseButtonTag(true) + ->addExtraClass('PageBuilder_Value_Block-EditColumns') + ->addExtraClass('font-icon-columns'), + (new FormAction($this->getNameForField($prefix, 'Delete'), '')) + ->setUseButtonTag(true) + ->addExtraClass('PageBuilder_Value_Block-Delete') + ->addExtraClass('font-icon-cancel-circled') + ->setAttribute('data-confirm', _t('PageBuilder_Value_Block.ConfirmDelete', 'Are you sure you want to delete this block?')), + //(new FormAction($this->getNameForField($prefix, 'Edit'), '')) + // ->setUseButtonTag(true) + // ->addExtraClass('PageBuilder_Value_Block-Edit') + // ->addExtraClass('font-icon-edit-write'), + new LiteralField($this->getNameForField($prefix, 'Reorder'), '
'), + //new InlineFormAction($this->getNameForField($prefix, 'Edit')), + ]))->addExtraClass('PageBuilder_Value_Block-Controls')->setName($this->getNameForField($prefix, 'Controls')), + new HiddenField($this->getNameForField($prefix, 'ClassName'), '', $this->class), + new HiddenField($this->getNameForField($prefix, 'BlockPosition'), '', $blockPosition), + new HiddenField($this->getNameForField($prefix, 'BlockParent'), '', $parent), + (new PageBuilder_CompositeField([ + (new TextField($this->getNameForField($prefix, 'WidthDesktop'), $this->fieldLabel('WidthDesktop'), $this->getWidthDesktop())) + ->setAttribute('type', 'number') + ->setAttribute('min', '1') + ->setAttribute('max', '12') + ->addExtraClass('PageBuilder_Value_Block-Width PageBuilder_Value_Block-WidthDesktop'), + (new TextField($this->getNameForField($prefix, 'WidthTablet'), $this->fieldLabel('WidthTablet'), $this->getWidthTablet())) + ->setAttribute('type', 'number') + ->setAttribute('min', '1') + ->setAttribute('max', '12') + ->addExtraClass('PageBuilder_Value_Block-Width PageBuilder_Value_Block-WidthTablet'), + ]))->addExtraClass('PageBuilder_Value_Block-Widths')->setName($this->getNameForField($prefix, 'Widths')), + ])) + ->addExtraClass(implode(' ', $classes)) + ->setAttribute('data-width-desktop', $this->getWidthDesktop()) + //->setAttribute('data-width-desktop-context', 12) + //->setAttribute('data-width-desktop-context', $this->getMaxWidthDesktop()) + ->setAttribute('data-width-tablet', $this->getWidthTablet()) + //->setAttribute('data-width-tablet-context', 12) + //->setAttribute('data-width-tablet-context', $this->getMaxWidthTablet()) + ->setAttribute('data-name', $this->getName()); + } + + public static function getPageBuilderEditPopupFields() { + return new FieldList([]); + } + + public function onAfterCreate() { + $this->setWidthDesktop(12); + $this->setWidthTablet(12); + //$this->setField('WidthDesktop', 12); + //$this->setField('WidthTablet', 12); + } + + public function forTemplate() { + $templates = SSViewer::get_templates_by_class($this->class, '', __CLASS__); + if (!$templates) { + throw new Exception("No template found for {$this->class}"); + } + return $this->renderWith($templates); + } + + /** + * Compiles all CSS-classes + * @return string + */ + public function extraClass() { + return implode(' ', $this->extraClasses); + } + + /** + * Add one or more CSS-classes + * Multiple class names should be space delimited + * @param string $class + * @return $this + */ + public function addExtraClass($class) { + $classes = preg_split('/\s+/', $class); + foreach ($classes as $class) { + $this->extraClasses[$class] = $class; + } + return $this; + } + + /** + * Remove one or more CSS-classes + * @param string $class + * @return $this + */ + public function removeExtraClass($class) { + $classes = preg_split('/\s+/', $class); + foreach ($classes as $class) { + unset($this->extraClasses[$class]); + } + return $this; + } +} diff --git a/code/PageBuilder_Value/PageBuilder_Value_Block_BlockGroup.php b/code/PageBuilder_Value/PageBuilder_Value_Block_BlockGroup.php new file mode 100644 index 0000000..97cf5c9 --- /dev/null +++ b/code/PageBuilder_Value/PageBuilder_Value_Block_BlockGroup.php @@ -0,0 +1,99 @@ +getName(); + $i = 0; + $fields->push( + (new PageBuilder_CompositeField( + array_map(function (PageBuilder_Value_Block $block) use ($prefix, &$i, $name) { + return $block->getPageBuilderFields($prefix, $i++, $name); + }, $this->getBlocks()->toArray()) + ))->addExtraClass('PageBuilder_Value_Block_BlockGroup-Blocks') + ); + $fields->push( + (new FormAction( + $this->getNameForField($prefix, 'AddButton'), + _t('PageBuilder_Value_Block_BlockGroup.AddButton', 'add block') + )) + ->setUseButtonTag(true) + ->addExtraClass('PageBuilder_Value_Block_BlockGroup-AddButton') + ->addExtraClass('font-icon-plus') + ); + return $fields; + } + + public function BlocksForTemplate() { + $rowDesktop = 0; + $rowTablet = 0; + $blocks = []; + foreach (array_values($this->getBlocks()->toArray()) as $i => $_block) { + /** @var PageBuilder_Value_Block $block */ + $block = clone $_block; + //$block->setMaxWidthDesktop($this->getWidthDesktop()); + //$block->setMaxWidthTablet($this->getWidthTablet()); + foreach (array_reverse(ClassInfo::ancestry($block->class)) as $class) { + $baseClass = 'PageBuilder_Value_Block'; + if ($class == $baseClass) { + break; + } + $block->addExtraClass(str_replace($baseClass . '_', '', $class)); + } + $desktop = (int)$block->getWidthDesktop(); + $tablet = (int)$block->getWidthTablet(); + $desktopMax = (int)$this->getWidthDesktop(); + $tabletMax = (int)$this->getWidthTablet(); + $block->addExtraClass('grid-column'); + $block->addExtraClass("grid-column-desktop-$desktop"); + $block->addExtraClass("grid-column-desktop-context-$desktopMax"); + //$block->addExtraClass("grid-column-desktop-n-of-$desktopMax"); + //$block->addExtraClass("grid-column-desktop-$desktop-of-$desktopMax"); + $block->addExtraClass("grid-column-tablet-$tablet"); + $block->addExtraClass("grid-column-tablet-context-$tabletMax"); + //$block->addExtraClass("grid-column-tablet-$tablet-of-$tabletMax"); + //$block->addExtraClass("grid-column-tablet-$tablet-of-n"); + if ($block->is_a(__CLASS__)) { + $block->addExtraClass('grid-column-container'); + } + $rowDesktop += $desktop; + if ($i == 0 || $rowDesktop > $desktopMax) { + // item can't fit into current row, place it on next row + $block->addExtraClass('grid-desktop-clear'); + $rowDesktop = $desktop; + if ($i) { + $blocks[$i - 1]->addExtraClass('grid-desktop-last'); + } + } + $rowTablet += $tablet; + if ($i == 0 || $rowTablet > $tabletMax) { + // item can't fit into current row, place it on next row + $block->addExtraClass('grid-tablet-clear'); + $rowTablet = $tablet; + if ($i) { + $blocks[$i - 1]->addExtraClass('grid-tablet-last'); + } + } + $blocks[] = $block; + } + $count = count($blocks); + if ($count > 0 && $rowDesktop == (int)$this->getWidthDesktop()) { + //if ($rowDesktop == 12) { + $blocks[$count - 1]->addExtraClass('grid-desktop-last'); + } + if ($count > 0 && $rowTablet == (int)$this->getWidthTablet()) { + //if ($rowTablet == 12) { + $blocks[$count - 1]->addExtraClass('grid-tablet-last'); + } + return new ArrayList($blocks); + } +} diff --git a/code/PageBuilder_Value/PageBuilder_Value_Block_BlockGroup_Base.php b/code/PageBuilder_Value/PageBuilder_Value_Block_BlockGroup_Base.php new file mode 100644 index 0000000..37bc7ea --- /dev/null +++ b/code/PageBuilder_Value/PageBuilder_Value_Block_BlockGroup_Base.php @@ -0,0 +1,22 @@ +removeByName($this->getNameForField($prefix, 'Widths')); + $fields->removeByName($this->getNameForField($prefix, 'Controls')); + $fields->removeByName($this->getNameForField($prefix, 'ClassNameInfo')); + return $fields; + } + + public function extraClass() { + return 'grid-base' . parent::extraClass(); + } +} diff --git a/code/PageBuilder_Value/PageBuilder_Value_Block_ContentElement.php b/code/PageBuilder_Value/PageBuilder_Value_Block_ContentElement.php new file mode 100644 index 0000000..d6d3feb --- /dev/null +++ b/code/PageBuilder_Value/PageBuilder_Value_Block_ContentElement.php @@ -0,0 +1,70 @@ +_contentElement && $this->getContentElementID()) { + /** @var PageBuilder_ContentElement $obj */ + $obj = PageBuilder_ContentElement::get()->byID($this->getContentElementID()); + if ($obj && $obj->exists()) { + $this->_contentElement = $obj; + } + } + return $this->_contentElement; + } + + public function getContentElementForTemplate() { + $obj = $this->getContentElement(); + if ($obj) { + return $obj->customise([ + 'MetaData' => $this, + ]); + } + return null; + } + + public function getPageBuilderFields($prefix, $blockPosition = 0, $parent = null) { + $return = parent::getPageBuilderFields($prefix, $blockPosition, $parent); + $obj = $this->getContentElement(); + $return->push(new HiddenField($this->getNameForField($prefix, 'ContentElementID'), '', $this->getContentElementID())); + $return->push((new CompositeField([ + new LiteralField( + $this->getNameForField($prefix, 'Preview'), + $obj ? $obj->PageBuilderPreview() : _t('PageBuilder_Value_Block_ContentElement.NoContentElement', 'Content not found') + ), + ]))->addExtraClass('PageBuilder_Value_Block-Preview')); + $return->push( + (new FormAction( + $this->getNameForField($prefix, 'Edit'), + _t('PageBuilder_Value_Block_ContentElement.Edit', 'edit block content') + )) + ->setUseButtonTag(true) + ->addExtraClass('PageBuilder_Value_Block-Edit') + ->addExtraClass('font-icon-edit-write') + ->setAttribute('data-id', $this->getContentElementID()) + ->setAttribute('data-edit-type', 'edit-content-element') + ); + return $return; + } + + public function onAfterCreate() { + parent::onAfterCreate(); + $class = "{$this->class}_ContentElement"; + /** @var PageBuilder_ContentElement $obj */ + $obj = new $class(); + $obj->write(); + $this->setContentElementID($obj->ID); + } +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..0e5ba59 --- /dev/null +++ b/composer.json @@ -0,0 +1,21 @@ +{ + "name": "zauberfisch/silverstripe-page-builder", + "description": "SilverStripe module to allow for modular, block based, content in SilverStripe", + "type": "silverstripe-module", + "keywords": ["silverstripe", "content", "elements", "blocks", "contentblock", "pagebuilder"], + "license": "BSD-3-Clause", + "authors": [{ + "name": "Zauberfisch", + "email": "code@zauberfisch.at" + }], + "require": { + "silverstripe/framework": "~3.5", + "zauberfisch/silverstripe-serialized-dataobject": "~1.0" + }, + "suggest": { + "zauberfisch/silverstripe-page-builder-basic-blocks": "*" + }, + "extra": { + "installer-name": "page-builder" + } +} diff --git a/css/PageBuilder.scss.css b/css/PageBuilder.scss.css new file mode 100644 index 0000000..00c842f --- /dev/null +++ b/css/PageBuilder.scss.css @@ -0,0 +1,418 @@ +.PageBuilder_Field { + min-width: 600px; } + .PageBuilder_Field .grid-controls { + float: right; } + .PageBuilder_Field .grid-controls .icon-button { + display: block; + float: left; + padding: 6px 8px; + height: 14px; } + .PageBuilder_Field > .middleColumn { + margin: 0 auto !important; } + .PageBuilder_Field > .middleColumn:after { + content: " "; + display: block; + clear: both; } + .PageBuilder_Field > .middleColumn *, .PageBuilder_Field > .middleColumn *:before, .PageBuilder_Field > .middleColumn *:after { + margin: 0; + padding: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + .PageBuilder_Field .clear { + clear: both; } + .PageBuilder_Field[data-grid-mode="desktop"] .grid-desktop-clear { + clear: both; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="1"][data-width-desktop-context="1"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="1"][data-width-desktop-context="2"] { + width: 48%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="1"][data-width-desktop-context="3"] { + width: 31.33333%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="1"][data-width-desktop-context="4"] { + width: 23%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="1"][data-width-desktop-context="5"] { + width: 18%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="1"][data-width-desktop-context="6"] { + width: 14.66667%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="1"][data-width-desktop-context="7"] { + width: 12.28571%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="1"][data-width-desktop-context="8"] { + width: 10.5%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="1"][data-width-desktop-context="9"] { + width: 9.11111%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="1"][data-width-desktop-context="10"] { + width: 8%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="1"][data-width-desktop-context="11"] { + width: 7.09091%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="1"][data-width-desktop-context="12"] { + width: 6.33333%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="2"][data-width-desktop-context="2"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="2"][data-width-desktop-context="3"] { + width: 64.66667%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="2"][data-width-desktop-context="4"] { + width: 48%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="2"][data-width-desktop-context="5"] { + width: 38%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="2"][data-width-desktop-context="6"] { + width: 31.33333%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="2"][data-width-desktop-context="7"] { + width: 26.57143%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="2"][data-width-desktop-context="8"] { + width: 23%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="2"][data-width-desktop-context="9"] { + width: 20.22222%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="2"][data-width-desktop-context="10"] { + width: 18%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="2"][data-width-desktop-context="11"] { + width: 16.18182%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="2"][data-width-desktop-context="12"] { + width: 14.66667%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="3"][data-width-desktop-context="3"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="3"][data-width-desktop-context="4"] { + width: 73%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="3"][data-width-desktop-context="5"] { + width: 58%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="3"][data-width-desktop-context="6"] { + width: 48%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="3"][data-width-desktop-context="7"] { + width: 40.85714%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="3"][data-width-desktop-context="8"] { + width: 35.5%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="3"][data-width-desktop-context="9"] { + width: 31.33333%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="3"][data-width-desktop-context="10"] { + width: 28%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="3"][data-width-desktop-context="11"] { + width: 25.27273%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="3"][data-width-desktop-context="12"] { + width: 23%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="4"][data-width-desktop-context="4"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="4"][data-width-desktop-context="5"] { + width: 78%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="4"][data-width-desktop-context="6"] { + width: 64.66667%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="4"][data-width-desktop-context="7"] { + width: 55.14286%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="4"][data-width-desktop-context="8"] { + width: 48%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="4"][data-width-desktop-context="9"] { + width: 42.44444%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="4"][data-width-desktop-context="10"] { + width: 38%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="4"][data-width-desktop-context="11"] { + width: 34.36364%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="4"][data-width-desktop-context="12"] { + width: 31.33333%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="5"][data-width-desktop-context="5"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="5"][data-width-desktop-context="6"] { + width: 81.33333%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="5"][data-width-desktop-context="7"] { + width: 69.42857%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="5"][data-width-desktop-context="8"] { + width: 60.5%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="5"][data-width-desktop-context="9"] { + width: 53.55556%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="5"][data-width-desktop-context="10"] { + width: 48%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="5"][data-width-desktop-context="11"] { + width: 43.45455%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="5"][data-width-desktop-context="12"] { + width: 39.66667%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="6"][data-width-desktop-context="6"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="6"][data-width-desktop-context="7"] { + width: 83.71429%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="6"][data-width-desktop-context="8"] { + width: 73%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="6"][data-width-desktop-context="9"] { + width: 64.66667%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="6"][data-width-desktop-context="10"] { + width: 58%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="6"][data-width-desktop-context="11"] { + width: 52.54545%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="6"][data-width-desktop-context="12"] { + width: 48%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="7"][data-width-desktop-context="7"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="7"][data-width-desktop-context="8"] { + width: 85.5%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="7"][data-width-desktop-context="9"] { + width: 75.77778%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="7"][data-width-desktop-context="10"] { + width: 68%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="7"][data-width-desktop-context="11"] { + width: 61.63636%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="7"][data-width-desktop-context="12"] { + width: 56.33333%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="8"][data-width-desktop-context="8"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="8"][data-width-desktop-context="9"] { + width: 86.88889%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="8"][data-width-desktop-context="10"] { + width: 78%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="8"][data-width-desktop-context="11"] { + width: 70.72727%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="8"][data-width-desktop-context="12"] { + width: 64.66667%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="9"][data-width-desktop-context="9"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="9"][data-width-desktop-context="10"] { + width: 88%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="9"][data-width-desktop-context="11"] { + width: 79.81818%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="9"][data-width-desktop-context="12"] { + width: 73%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="10"][data-width-desktop-context="10"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="10"][data-width-desktop-context="11"] { + width: 88.90909%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="10"][data-width-desktop-context="12"] { + width: 81.33333%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="11"][data-width-desktop-context="11"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="11"][data-width-desktop-context="12"] { + width: 89.66667%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="12"][data-width-desktop-context="12"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="1"] .PageBuilder_Value_Block-Widths div.PageBuilder_Value_Block-Width, .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="2"] .PageBuilder_Value_Block-Widths div.PageBuilder_Value_Block-Width, .PageBuilder_Field[data-grid-mode="desktop"] .PageBuilder_Value_Block[data-width-desktop="3"] .PageBuilder_Value_Block-Widths div.PageBuilder_Value_Block-Width { + width: auto; + float: none; } + .PageBuilder_Field[data-grid-mode="desktop"] input.PageBuilder_Value_Block-WidthDesktop { + background: #DBF8FF; } + .PageBuilder_Field[data-grid-mode="tablet"] > .middleColumn { + width: 600px; } + .PageBuilder_Field[data-grid-mode="tablet"] .grid-tablet-clear { + clear: both; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="1"][data-width-tablet-context="1"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="1"][data-width-tablet-context="2"] { + width: 48%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="1"][data-width-tablet-context="3"] { + width: 31.33333%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="1"][data-width-tablet-context="4"] { + width: 23%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="1"][data-width-tablet-context="5"] { + width: 18%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="1"][data-width-tablet-context="6"] { + width: 14.66667%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="1"][data-width-tablet-context="7"] { + width: 12.28571%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="1"][data-width-tablet-context="8"] { + width: 10.5%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="1"][data-width-tablet-context="9"] { + width: 9.11111%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="1"][data-width-tablet-context="10"] { + width: 8%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="1"][data-width-tablet-context="11"] { + width: 7.09091%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="1"][data-width-tablet-context="12"] { + width: 6.33333%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="2"][data-width-tablet-context="2"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="2"][data-width-tablet-context="3"] { + width: 64.66667%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="2"][data-width-tablet-context="4"] { + width: 48%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="2"][data-width-tablet-context="5"] { + width: 38%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="2"][data-width-tablet-context="6"] { + width: 31.33333%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="2"][data-width-tablet-context="7"] { + width: 26.57143%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="2"][data-width-tablet-context="8"] { + width: 23%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="2"][data-width-tablet-context="9"] { + width: 20.22222%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="2"][data-width-tablet-context="10"] { + width: 18%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="2"][data-width-tablet-context="11"] { + width: 16.18182%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="2"][data-width-tablet-context="12"] { + width: 14.66667%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="3"][data-width-tablet-context="3"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="3"][data-width-tablet-context="4"] { + width: 73%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="3"][data-width-tablet-context="5"] { + width: 58%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="3"][data-width-tablet-context="6"] { + width: 48%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="3"][data-width-tablet-context="7"] { + width: 40.85714%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="3"][data-width-tablet-context="8"] { + width: 35.5%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="3"][data-width-tablet-context="9"] { + width: 31.33333%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="3"][data-width-tablet-context="10"] { + width: 28%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="3"][data-width-tablet-context="11"] { + width: 25.27273%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="3"][data-width-tablet-context="12"] { + width: 23%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="4"][data-width-tablet-context="4"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="4"][data-width-tablet-context="5"] { + width: 78%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="4"][data-width-tablet-context="6"] { + width: 64.66667%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="4"][data-width-tablet-context="7"] { + width: 55.14286%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="4"][data-width-tablet-context="8"] { + width: 48%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="4"][data-width-tablet-context="9"] { + width: 42.44444%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="4"][data-width-tablet-context="10"] { + width: 38%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="4"][data-width-tablet-context="11"] { + width: 34.36364%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="4"][data-width-tablet-context="12"] { + width: 31.33333%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="5"][data-width-tablet-context="5"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="5"][data-width-tablet-context="6"] { + width: 81.33333%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="5"][data-width-tablet-context="7"] { + width: 69.42857%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="5"][data-width-tablet-context="8"] { + width: 60.5%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="5"][data-width-tablet-context="9"] { + width: 53.55556%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="5"][data-width-tablet-context="10"] { + width: 48%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="5"][data-width-tablet-context="11"] { + width: 43.45455%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="5"][data-width-tablet-context="12"] { + width: 39.66667%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="6"][data-width-tablet-context="6"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="6"][data-width-tablet-context="7"] { + width: 83.71429%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="6"][data-width-tablet-context="8"] { + width: 73%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="6"][data-width-tablet-context="9"] { + width: 64.66667%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="6"][data-width-tablet-context="10"] { + width: 58%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="6"][data-width-tablet-context="11"] { + width: 52.54545%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="6"][data-width-tablet-context="12"] { + width: 48%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="7"][data-width-tablet-context="7"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="7"][data-width-tablet-context="8"] { + width: 85.5%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="7"][data-width-tablet-context="9"] { + width: 75.77778%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="7"][data-width-tablet-context="10"] { + width: 68%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="7"][data-width-tablet-context="11"] { + width: 61.63636%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="7"][data-width-tablet-context="12"] { + width: 56.33333%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="8"][data-width-tablet-context="8"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="8"][data-width-tablet-context="9"] { + width: 86.88889%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="8"][data-width-tablet-context="10"] { + width: 78%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="8"][data-width-tablet-context="11"] { + width: 70.72727%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="8"][data-width-tablet-context="12"] { + width: 64.66667%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="9"][data-width-tablet-context="9"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="9"][data-width-tablet-context="10"] { + width: 88%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="9"][data-width-tablet-context="11"] { + width: 79.81818%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="9"][data-width-tablet-context="12"] { + width: 73%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="10"][data-width-tablet-context="10"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="10"][data-width-tablet-context="11"] { + width: 88.90909%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="10"][data-width-tablet-context="12"] { + width: 81.33333%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="11"][data-width-tablet-context="11"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="11"][data-width-tablet-context="12"] { + width: 89.66667%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="12"][data-width-tablet-context="12"] { + width: 98%; } + .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="1"] .PageBuilder_Value_Block-Widths div.PageBuilder_Value_Block-Width, .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="2"] .PageBuilder_Value_Block-Widths div.PageBuilder_Value_Block-Width, .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="3"] .PageBuilder_Value_Block-Widths div.PageBuilder_Value_Block-Width, .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="4"] .PageBuilder_Value_Block-Widths div.PageBuilder_Value_Block-Width, .PageBuilder_Field[data-grid-mode="tablet"] .PageBuilder_Value_Block[data-width-tablet="5"] .PageBuilder_Value_Block-Widths div.PageBuilder_Value_Block-Width { + width: auto; + float: none; } + .PageBuilder_Field[data-grid-mode="tablet"] input.PageBuilder_Value_Block-WidthTablet { + background: #DBF8FF; } + .PageBuilder_Field .PageBuilder_Value_Block { + border-radius: 3px; + background: rgba(0, 0, 0, 0.05); + border: 1px solid #CDCCD0; + padding: 8px 15px 3px !important; + float: left; + margin: 10px 1% 0 !important; + position: relative; } + .PageBuilder_Field .PageBuilder_Value_Block.pre-delete { + border-color: red; } + .PageBuilder_Field .PageBuilder_Value_Block label { + width: auto; + padding: 0 0 8px; + margin: 0; } + .PageBuilder_Field .PageBuilder_Value_Block div.field { + padding: 0 0 8px; + margin: 0; + border: 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; } + .PageBuilder_Field .PageBuilder_Value_Block .PageBuilder_Value_Block-ClassNameInfo { + opacity: .5; + padding: 0; + font-size: small; + margin: 0 0 10px; } + .PageBuilder_Field .PageBuilder_Value_Block .PageBuilder_Value_Block-Controls { + transition: opacity 300ms ease; + position: absolute; + right: 5px; + top: 5px; + opacity: 0; + white-space: nowrap; } + .PageBuilder_Field .PageBuilder_Value_Block .PageBuilder_Value_Block-Controls > * { + display: block; + float: left; + margin: 0 4px; + padding: 2px; } + .PageBuilder_Field .PageBuilder_Value_Block .PageBuilder_Value_Block-Controls .PageBuilder_Value_Block-Reorder { + height: 22px; + width: 16px; + cursor: move; + background: center center no-repeat url("../images/reorder.png"); } + .PageBuilder_Field .PageBuilder_Value_Block .PageBuilder_Value_Block-Controls button:before { + margin: 0; } + .PageBuilder_Field .PageBuilder_Value_Block .PageBuilder_Value_Block-Widths { + display: none; } + .PageBuilder_Field .PageBuilder_Value_Block .PageBuilder_Value_Block-Widths:after { + content: " "; + display: block; + clear: both; } + .PageBuilder_Field .PageBuilder_Value_Block .PageBuilder_Value_Block-Widths div.PageBuilder_Value_Block-Width { + width: 49%; + float: left; + margin: 0; } + .PageBuilder_Field .PageBuilder_Value_Block .PageBuilder_Value_Block-Widths div.PageBuilder_Value_Block-Width.PageBuilder_Value_Block-WidthDesktop { + margin: 0 2% 0 0; } + .PageBuilder_Field .PageBuilder_Value_Block.PageBuilder_Value_Block_BlockGroup .PageBuilder_Value_Block_BlockGroup-Blocks { + padding: 0 0 30px; } + .PageBuilder_Field .PageBuilder_Value_Block.PageBuilder_Value_Block_BlockGroup .PageBuilder_Value_Block_BlockGroup-Blocks:after { + content: " "; + display: block; + clear: both; } + .PageBuilder_Field .PageBuilder_Value_Block.PageBuilder_Value_Block_BlockGroup .PageBuilder_Value_Block_BlockGroup-AddButton { + clear: both; } + .PageBuilder_Field .PageBuilder_Value_Block:hover > .PageBuilder_Value_Block-Controls { + opacity: 1; } diff --git a/docs/example.md b/docs/example.md new file mode 100644 index 0000000..be02eb3 --- /dev/null +++ b/docs/example.md @@ -0,0 +1,447 @@ +# PageBuilder project example + +composer.json + + { + "require": { + "php": ">=5.4", + "silverstripe/cms": "^3.5", + "silverstripe/framework": "^3.5", + "zauberfisch/silverstripe-page-builder": "^1.0", + "zauberfisch/silverstripe-page-builder-basic-blocks": "^1.0" + }, + "minimum-stability": "dev", + "prefer-stable": true + } + +mysite/code/Page.php + + 'PageBuilder_DBField', + ]; + + public function getCMSFields() { + $fields = parent::getCMSFields(); + $fields->addFieldsToTab('Root.Main', [ + new PageBuilder_Field('PageBuilder', $this->fieldLabel('PageBuilder')), + ]); + return $fields; + } + } + + class Page_Controller extends Controller {} + +mysite/templates/Layout/Page.ss + +
+

$Title

+ $Content + $Form +
+ <% if $PageBuilder %> +
+ $PageBuilder.Value +
+ <% end_if %> + +mysite/scss/grid.scss (optional, alternatively just use plain css below) + + // mixin to generate the css for each possible nesting of blocks + @mixin grid-element($type: desktop) { + @for $i from 1 through 12 { + @for $j from $i through 12 { + .grid-column.grid-column-#{$type}-#{$i}.grid-column-#{$type}-context-#{$j} { + width: 100% * $i / $j; + } + } + } + } + + .grid-base { + .grid-column { + // on mobile display all columns full width + padding: 10px; + margin: 0 0 10px; + + // add some border colors to make the grid visible + border: 1px solid red; + + .grid-column { + border-color: blue; + + .grid-column { + border-color: green; + + .grid-column { + border-color: yellow; + } + } + } + } + + @include breakpoint(500px) { + // on tablets use the tablet column widths from the PageBuilder + @include grid-element(tablet); + + .grid-tablet-clear { + clear: both; + } + .grid-column { + float: left; + } + } + @include breakpoint(700px) { + // on desktop use the desktop column widths from the PageBuilder + .grid-tablet-clear { + clear: none; + } + .grid-desktop-clear { + clear: both; + } + @include grid-element(desktop); + } + } + +mysite/css/grid.css (generated from grid.scss) + + .grid-base .grid-column { + /** on mobile display all columns full width **/ + padding: 10px; + margin: 0 0 10px; + border: 1px solid red; } + /** add some border colors to make the grid visible **/ + .grid-base .grid-column .grid-column { + border-color: blue; } + .grid-base .grid-column .grid-column .grid-column { + border-color: green; } + .grid-base .grid-column .grid-column .grid-column .grid-column { + border-color: yellow; } + + @media (min-width: 500px) { + /** on tablets use the tablet column widths from the PageBuilder **/ + .grid-base .grid-column.grid-column-tablet-1.grid-column-tablet-context-1 { + width: 100%; } + .grid-base .grid-column.grid-column-tablet-1.grid-column-tablet-context-2 { + width: 50%; } + .grid-base .grid-column.grid-column-tablet-1.grid-column-tablet-context-3 { + width: 33.33333%; } + .grid-base .grid-column.grid-column-tablet-1.grid-column-tablet-context-4 { + width: 25%; } + .grid-base .grid-column.grid-column-tablet-1.grid-column-tablet-context-5 { + width: 20%; } + .grid-base .grid-column.grid-column-tablet-1.grid-column-tablet-context-6 { + width: 16.66667%; } + .grid-base .grid-column.grid-column-tablet-1.grid-column-tablet-context-7 { + width: 14.28571%; } + .grid-base .grid-column.grid-column-tablet-1.grid-column-tablet-context-8 { + width: 12.5%; } + .grid-base .grid-column.grid-column-tablet-1.grid-column-tablet-context-9 { + width: 11.11111%; } + .grid-base .grid-column.grid-column-tablet-1.grid-column-tablet-context-10 { + width: 10%; } + .grid-base .grid-column.grid-column-tablet-1.grid-column-tablet-context-11 { + width: 9.09091%; } + .grid-base .grid-column.grid-column-tablet-1.grid-column-tablet-context-12 { + width: 8.33333%; } + .grid-base .grid-column.grid-column-tablet-2.grid-column-tablet-context-2 { + width: 100%; } + .grid-base .grid-column.grid-column-tablet-2.grid-column-tablet-context-3 { + width: 66.66667%; } + .grid-base .grid-column.grid-column-tablet-2.grid-column-tablet-context-4 { + width: 50%; } + .grid-base .grid-column.grid-column-tablet-2.grid-column-tablet-context-5 { + width: 40%; } + .grid-base .grid-column.grid-column-tablet-2.grid-column-tablet-context-6 { + width: 33.33333%; } + .grid-base .grid-column.grid-column-tablet-2.grid-column-tablet-context-7 { + width: 28.57143%; } + .grid-base .grid-column.grid-column-tablet-2.grid-column-tablet-context-8 { + width: 25%; } + .grid-base .grid-column.grid-column-tablet-2.grid-column-tablet-context-9 { + width: 22.22222%; } + .grid-base .grid-column.grid-column-tablet-2.grid-column-tablet-context-10 { + width: 20%; } + .grid-base .grid-column.grid-column-tablet-2.grid-column-tablet-context-11 { + width: 18.18182%; } + .grid-base .grid-column.grid-column-tablet-2.grid-column-tablet-context-12 { + width: 16.66667%; } + .grid-base .grid-column.grid-column-tablet-3.grid-column-tablet-context-3 { + width: 100%; } + .grid-base .grid-column.grid-column-tablet-3.grid-column-tablet-context-4 { + width: 75%; } + .grid-base .grid-column.grid-column-tablet-3.grid-column-tablet-context-5 { + width: 60%; } + .grid-base .grid-column.grid-column-tablet-3.grid-column-tablet-context-6 { + width: 50%; } + .grid-base .grid-column.grid-column-tablet-3.grid-column-tablet-context-7 { + width: 42.85714%; } + .grid-base .grid-column.grid-column-tablet-3.grid-column-tablet-context-8 { + width: 37.5%; } + .grid-base .grid-column.grid-column-tablet-3.grid-column-tablet-context-9 { + width: 33.33333%; } + .grid-base .grid-column.grid-column-tablet-3.grid-column-tablet-context-10 { + width: 30%; } + .grid-base .grid-column.grid-column-tablet-3.grid-column-tablet-context-11 { + width: 27.27273%; } + .grid-base .grid-column.grid-column-tablet-3.grid-column-tablet-context-12 { + width: 25%; } + .grid-base .grid-column.grid-column-tablet-4.grid-column-tablet-context-4 { + width: 100%; } + .grid-base .grid-column.grid-column-tablet-4.grid-column-tablet-context-5 { + width: 80%; } + .grid-base .grid-column.grid-column-tablet-4.grid-column-tablet-context-6 { + width: 66.66667%; } + .grid-base .grid-column.grid-column-tablet-4.grid-column-tablet-context-7 { + width: 57.14286%; } + .grid-base .grid-column.grid-column-tablet-4.grid-column-tablet-context-8 { + width: 50%; } + .grid-base .grid-column.grid-column-tablet-4.grid-column-tablet-context-9 { + width: 44.44444%; } + .grid-base .grid-column.grid-column-tablet-4.grid-column-tablet-context-10 { + width: 40%; } + .grid-base .grid-column.grid-column-tablet-4.grid-column-tablet-context-11 { + width: 36.36364%; } + .grid-base .grid-column.grid-column-tablet-4.grid-column-tablet-context-12 { + width: 33.33333%; } + .grid-base .grid-column.grid-column-tablet-5.grid-column-tablet-context-5 { + width: 100%; } + .grid-base .grid-column.grid-column-tablet-5.grid-column-tablet-context-6 { + width: 83.33333%; } + .grid-base .grid-column.grid-column-tablet-5.grid-column-tablet-context-7 { + width: 71.42857%; } + .grid-base .grid-column.grid-column-tablet-5.grid-column-tablet-context-8 { + width: 62.5%; } + .grid-base .grid-column.grid-column-tablet-5.grid-column-tablet-context-9 { + width: 55.55556%; } + .grid-base .grid-column.grid-column-tablet-5.grid-column-tablet-context-10 { + width: 50%; } + .grid-base .grid-column.grid-column-tablet-5.grid-column-tablet-context-11 { + width: 45.45455%; } + .grid-base .grid-column.grid-column-tablet-5.grid-column-tablet-context-12 { + width: 41.66667%; } + .grid-base .grid-column.grid-column-tablet-6.grid-column-tablet-context-6 { + width: 100%; } + .grid-base .grid-column.grid-column-tablet-6.grid-column-tablet-context-7 { + width: 85.71429%; } + .grid-base .grid-column.grid-column-tablet-6.grid-column-tablet-context-8 { + width: 75%; } + .grid-base .grid-column.grid-column-tablet-6.grid-column-tablet-context-9 { + width: 66.66667%; } + .grid-base .grid-column.grid-column-tablet-6.grid-column-tablet-context-10 { + width: 60%; } + .grid-base .grid-column.grid-column-tablet-6.grid-column-tablet-context-11 { + width: 54.54545%; } + .grid-base .grid-column.grid-column-tablet-6.grid-column-tablet-context-12 { + width: 50%; } + .grid-base .grid-column.grid-column-tablet-7.grid-column-tablet-context-7 { + width: 100%; } + .grid-base .grid-column.grid-column-tablet-7.grid-column-tablet-context-8 { + width: 87.5%; } + .grid-base .grid-column.grid-column-tablet-7.grid-column-tablet-context-9 { + width: 77.77778%; } + .grid-base .grid-column.grid-column-tablet-7.grid-column-tablet-context-10 { + width: 70%; } + .grid-base .grid-column.grid-column-tablet-7.grid-column-tablet-context-11 { + width: 63.63636%; } + .grid-base .grid-column.grid-column-tablet-7.grid-column-tablet-context-12 { + width: 58.33333%; } + .grid-base .grid-column.grid-column-tablet-8.grid-column-tablet-context-8 { + width: 100%; } + .grid-base .grid-column.grid-column-tablet-8.grid-column-tablet-context-9 { + width: 88.88889%; } + .grid-base .grid-column.grid-column-tablet-8.grid-column-tablet-context-10 { + width: 80%; } + .grid-base .grid-column.grid-column-tablet-8.grid-column-tablet-context-11 { + width: 72.72727%; } + .grid-base .grid-column.grid-column-tablet-8.grid-column-tablet-context-12 { + width: 66.66667%; } + .grid-base .grid-column.grid-column-tablet-9.grid-column-tablet-context-9 { + width: 100%; } + .grid-base .grid-column.grid-column-tablet-9.grid-column-tablet-context-10 { + width: 90%; } + .grid-base .grid-column.grid-column-tablet-9.grid-column-tablet-context-11 { + width: 81.81818%; } + .grid-base .grid-column.grid-column-tablet-9.grid-column-tablet-context-12 { + width: 75%; } + .grid-base .grid-column.grid-column-tablet-10.grid-column-tablet-context-10 { + width: 100%; } + .grid-base .grid-column.grid-column-tablet-10.grid-column-tablet-context-11 { + width: 90.90909%; } + .grid-base .grid-column.grid-column-tablet-10.grid-column-tablet-context-12 { + width: 83.33333%; } + .grid-base .grid-column.grid-column-tablet-11.grid-column-tablet-context-11 { + width: 100%; } + .grid-base .grid-column.grid-column-tablet-11.grid-column-tablet-context-12 { + width: 91.66667%; } + .grid-base .grid-column.grid-column-tablet-12.grid-column-tablet-context-12 { + width: 100%; } + .grid-base .grid-tablet-clear { + clear: both; } + .grid-base .grid-column { + float: left; } } + + @media (min-width: 700px) { + /** on desktop use the desktop column widths from the PageBuilder **/ + .grid-base .grid-tablet-clear { + clear: none; } + .grid-base .grid-desktop-clear { + clear: both; } + .grid-base .grid-column.grid-column-desktop-1.grid-column-desktop-context-1 { + width: 100%; } + .grid-base .grid-column.grid-column-desktop-1.grid-column-desktop-context-2 { + width: 50%; } + .grid-base .grid-column.grid-column-desktop-1.grid-column-desktop-context-3 { + width: 33.33333%; } + .grid-base .grid-column.grid-column-desktop-1.grid-column-desktop-context-4 { + width: 25%; } + .grid-base .grid-column.grid-column-desktop-1.grid-column-desktop-context-5 { + width: 20%; } + .grid-base .grid-column.grid-column-desktop-1.grid-column-desktop-context-6 { + width: 16.66667%; } + .grid-base .grid-column.grid-column-desktop-1.grid-column-desktop-context-7 { + width: 14.28571%; } + .grid-base .grid-column.grid-column-desktop-1.grid-column-desktop-context-8 { + width: 12.5%; } + .grid-base .grid-column.grid-column-desktop-1.grid-column-desktop-context-9 { + width: 11.11111%; } + .grid-base .grid-column.grid-column-desktop-1.grid-column-desktop-context-10 { + width: 10%; } + .grid-base .grid-column.grid-column-desktop-1.grid-column-desktop-context-11 { + width: 9.09091%; } + .grid-base .grid-column.grid-column-desktop-1.grid-column-desktop-context-12 { + width: 8.33333%; } + .grid-base .grid-column.grid-column-desktop-2.grid-column-desktop-context-2 { + width: 100%; } + .grid-base .grid-column.grid-column-desktop-2.grid-column-desktop-context-3 { + width: 66.66667%; } + .grid-base .grid-column.grid-column-desktop-2.grid-column-desktop-context-4 { + width: 50%; } + .grid-base .grid-column.grid-column-desktop-2.grid-column-desktop-context-5 { + width: 40%; } + .grid-base .grid-column.grid-column-desktop-2.grid-column-desktop-context-6 { + width: 33.33333%; } + .grid-base .grid-column.grid-column-desktop-2.grid-column-desktop-context-7 { + width: 28.57143%; } + .grid-base .grid-column.grid-column-desktop-2.grid-column-desktop-context-8 { + width: 25%; } + .grid-base .grid-column.grid-column-desktop-2.grid-column-desktop-context-9 { + width: 22.22222%; } + .grid-base .grid-column.grid-column-desktop-2.grid-column-desktop-context-10 { + width: 20%; } + .grid-base .grid-column.grid-column-desktop-2.grid-column-desktop-context-11 { + width: 18.18182%; } + .grid-base .grid-column.grid-column-desktop-2.grid-column-desktop-context-12 { + width: 16.66667%; } + .grid-base .grid-column.grid-column-desktop-3.grid-column-desktop-context-3 { + width: 100%; } + .grid-base .grid-column.grid-column-desktop-3.grid-column-desktop-context-4 { + width: 75%; } + .grid-base .grid-column.grid-column-desktop-3.grid-column-desktop-context-5 { + width: 60%; } + .grid-base .grid-column.grid-column-desktop-3.grid-column-desktop-context-6 { + width: 50%; } + .grid-base .grid-column.grid-column-desktop-3.grid-column-desktop-context-7 { + width: 42.85714%; } + .grid-base .grid-column.grid-column-desktop-3.grid-column-desktop-context-8 { + width: 37.5%; } + .grid-base .grid-column.grid-column-desktop-3.grid-column-desktop-context-9 { + width: 33.33333%; } + .grid-base .grid-column.grid-column-desktop-3.grid-column-desktop-context-10 { + width: 30%; } + .grid-base .grid-column.grid-column-desktop-3.grid-column-desktop-context-11 { + width: 27.27273%; } + .grid-base .grid-column.grid-column-desktop-3.grid-column-desktop-context-12 { + width: 25%; } + .grid-base .grid-column.grid-column-desktop-4.grid-column-desktop-context-4 { + width: 100%; } + .grid-base .grid-column.grid-column-desktop-4.grid-column-desktop-context-5 { + width: 80%; } + .grid-base .grid-column.grid-column-desktop-4.grid-column-desktop-context-6 { + width: 66.66667%; } + .grid-base .grid-column.grid-column-desktop-4.grid-column-desktop-context-7 { + width: 57.14286%; } + .grid-base .grid-column.grid-column-desktop-4.grid-column-desktop-context-8 { + width: 50%; } + .grid-base .grid-column.grid-column-desktop-4.grid-column-desktop-context-9 { + width: 44.44444%; } + .grid-base .grid-column.grid-column-desktop-4.grid-column-desktop-context-10 { + width: 40%; } + .grid-base .grid-column.grid-column-desktop-4.grid-column-desktop-context-11 { + width: 36.36364%; } + .grid-base .grid-column.grid-column-desktop-4.grid-column-desktop-context-12 { + width: 33.33333%; } + .grid-base .grid-column.grid-column-desktop-5.grid-column-desktop-context-5 { + width: 100%; } + .grid-base .grid-column.grid-column-desktop-5.grid-column-desktop-context-6 { + width: 83.33333%; } + .grid-base .grid-column.grid-column-desktop-5.grid-column-desktop-context-7 { + width: 71.42857%; } + .grid-base .grid-column.grid-column-desktop-5.grid-column-desktop-context-8 { + width: 62.5%; } + .grid-base .grid-column.grid-column-desktop-5.grid-column-desktop-context-9 { + width: 55.55556%; } + .grid-base .grid-column.grid-column-desktop-5.grid-column-desktop-context-10 { + width: 50%; } + .grid-base .grid-column.grid-column-desktop-5.grid-column-desktop-context-11 { + width: 45.45455%; } + .grid-base .grid-column.grid-column-desktop-5.grid-column-desktop-context-12 { + width: 41.66667%; } + .grid-base .grid-column.grid-column-desktop-6.grid-column-desktop-context-6 { + width: 100%; } + .grid-base .grid-column.grid-column-desktop-6.grid-column-desktop-context-7 { + width: 85.71429%; } + .grid-base .grid-column.grid-column-desktop-6.grid-column-desktop-context-8 { + width: 75%; } + .grid-base .grid-column.grid-column-desktop-6.grid-column-desktop-context-9 { + width: 66.66667%; } + .grid-base .grid-column.grid-column-desktop-6.grid-column-desktop-context-10 { + width: 60%; } + .grid-base .grid-column.grid-column-desktop-6.grid-column-desktop-context-11 { + width: 54.54545%; } + .grid-base .grid-column.grid-column-desktop-6.grid-column-desktop-context-12 { + width: 50%; } + .grid-base .grid-column.grid-column-desktop-7.grid-column-desktop-context-7 { + width: 100%; } + .grid-base .grid-column.grid-column-desktop-7.grid-column-desktop-context-8 { + width: 87.5%; } + .grid-base .grid-column.grid-column-desktop-7.grid-column-desktop-context-9 { + width: 77.77778%; } + .grid-base .grid-column.grid-column-desktop-7.grid-column-desktop-context-10 { + width: 70%; } + .grid-base .grid-column.grid-column-desktop-7.grid-column-desktop-context-11 { + width: 63.63636%; } + .grid-base .grid-column.grid-column-desktop-7.grid-column-desktop-context-12 { + width: 58.33333%; } + .grid-base .grid-column.grid-column-desktop-8.grid-column-desktop-context-8 { + width: 100%; } + .grid-base .grid-column.grid-column-desktop-8.grid-column-desktop-context-9 { + width: 88.88889%; } + .grid-base .grid-column.grid-column-desktop-8.grid-column-desktop-context-10 { + width: 80%; } + .grid-base .grid-column.grid-column-desktop-8.grid-column-desktop-context-11 { + width: 72.72727%; } + .grid-base .grid-column.grid-column-desktop-8.grid-column-desktop-context-12 { + width: 66.66667%; } + .grid-base .grid-column.grid-column-desktop-9.grid-column-desktop-context-9 { + width: 100%; } + .grid-base .grid-column.grid-column-desktop-9.grid-column-desktop-context-10 { + width: 90%; } + .grid-base .grid-column.grid-column-desktop-9.grid-column-desktop-context-11 { + width: 81.81818%; } + .grid-base .grid-column.grid-column-desktop-9.grid-column-desktop-context-12 { + width: 75%; } + .grid-base .grid-column.grid-column-desktop-10.grid-column-desktop-context-10 { + width: 100%; } + .grid-base .grid-column.grid-column-desktop-10.grid-column-desktop-context-11 { + width: 90.90909%; } + .grid-base .grid-column.grid-column-desktop-10.grid-column-desktop-context-12 { + width: 83.33333%; } + .grid-base .grid-column.grid-column-desktop-11.grid-column-desktop-context-11 { + width: 100%; } + .grid-base .grid-column.grid-column-desktop-11.grid-column-desktop-context-12 { + width: 91.66667%; } + .grid-base .grid-column.grid-column-desktop-12.grid-column-desktop-context-12 { + width: 100%; } } diff --git a/images/reorder.png b/images/reorder.png new file mode 100644 index 0000000000000000000000000000000000000000..e65815e868c5fc3910649316edb601e44aa3ce75 GIT binary patch literal 306 zcmV-20nPr2P)k(SieY)XTA@p>O?Inx-#Z*KMOHIt75buAhD1e|4&=+HuZV z7=|YRFbu;%-}gI~W!cp(5 zS!>;*DEe_6Zwdbp5nGmpt?LSw=lKx;2f)|g9|PFaJkJ+e>uUgq0E98-(pr1QHk*y* zoUQIp=RuO5=In=(_IvFYRDg;jl4>X8-^I07*qoM6N<$ Eg5Obk>;M1& literal 0 HcmV?d00001 diff --git a/javascript/PageBuilder.js b/javascript/PageBuilder.js new file mode 100644 index 0000000..265c3fc --- /dev/null +++ b/javascript/PageBuilder.js @@ -0,0 +1,264 @@ +(function ($) { + if ($.ui.sortable) { + var sortable_mouseStart = $.ui.sortable.prototype._mouseStart; + $.ui.sortable.prototype._mouseStart = function (event, overrideHandle, noActivation) { + this._trigger('customBeforeStart', event, this._uiHash()); + sortable_mouseStart.apply(this, [event, overrideHandle, noActivation]); + }; + } + $('.PageBuilder_Field, .PageBuilder_Field *').entwine({ + getPageBuilderField: function () { + return this.closest('.PageBuilder_Field'); + }, + getRootForm: function () { + return this.closest('form'); + }, + getConfig: function () { + return this.getPageBuilderField().data('config'); + } + }); + $('.PageBuilder_Field .grid-controls .icon-button').entwine({ + onclick: function () { + var field = this.closest('.PageBuilder_Field'), + val = this.prop('href').split('#')[1]; + field.data('grid-mode', val); + field.attr('data-grid-mode', val); + this.addClass('active').siblings().removeClass('active'); + return false; + } + }); + $('.PageBuilder_Field .PageBuilder_Value_Block *').entwine({ + getBlockContainer: function () { + return this.closest('.PageBuilder_Value_Block'); + }, + getParentBlockContainer: function () { + return this.parent().closest('.PageBuilder_Value_Block_BlockGroup'); + } + }); + $('.PageBuilder_Field .PageBuilder_Value_Block').entwine({ + updateWidthDesktop: function (width) { + this.data('width-desktop', width); + this.attr('data-width-desktop', width); + this.getParentBlockContainer().updateGrid(); + if (this.hasClass('PageBuilder_Value_Block_BlockGroup')) { + this.updateWidthContext(); + } + }, + updateWidthTablet: function (width) { + this.data('width-tablet', width); + this.attr('data-width-tablet', width); + this.getParentBlockContainer().updateGrid(); + if (this.hasClass('PageBuilder_Value_Block_BlockGroup')) { + this.updateWidthContext(); + } + } + }); + $('.PageBuilder_Field input.PageBuilder_Value_Block-WidthDesktop').entwine({ + onchange: function () { + this.getBlockContainer().updateWidthDesktop(this.val()); + } + }); + $('.PageBuilder_Field input.PageBuilder_Value_Block-WidthTablet').entwine({ + onchange: function () { + this.getBlockContainer().updateWidthTablet(this.val()); + } + }); + $('.PageBuilder_Field .PageBuilder_Value_Block_BlockGroup').entwine({ + onmatch: function () { + this.updateGrid(); + }, + getDirectChildren: function () { + return this.find('> .PageBuilder_Value_Block_BlockGroup-Blocks > .PageBuilder_Value_Block'); + }, + updateWidthContext: function () { + var parentWidthDesktop = parseInt(this.data('width-desktop')), + parentWidthTablet = parseInt(this.data('width-tablet')); + this.getDirectChildren().each(function () { + var _this = $(this); + _this.data('width-desktop-context', parentWidthDesktop); + _this.attr('data-width-desktop-context', parentWidthDesktop); + _this.data('width-tablet-context', parentWidthTablet); + _this.attr('data-width-tablet-context', parentWidthTablet); + _this.find('> .PageBuilder_Value_Block-Widths input.PageBuilder_Value_Block-WidthDesktop').attr('max', parentWidthDesktop); + _this.find('> .PageBuilder_Value_Block-Widths input.PageBuilder_Value_Block-WidthTablet').attr('max', parentWidthTablet); + _this.updateWidthContext(); + }); + }, + updateGrid: function () { + var rowDesktop = 0, + rowTablet = 0, + parentWidthDesktop = parseInt(this.data('width-desktop')), + parentWidthTablet = parseInt(this.data('width-desktop')); + this.getDirectChildren().each(function (i) { + var _this = $(this), + desktop = parseInt(_this.data('width-desktop')), + tablet = parseInt(_this.data('width-tablet')); + rowDesktop += desktop; + if (i == 0 || rowDesktop > parentWidthDesktop) { + // item can't fit into current row, place it on next row + _this.addClass('grid-desktop-clear'); + rowDesktop = desktop; + } else { + // item fits + _this.removeClass('grid-desktop-clear'); + } + rowTablet += tablet; + if (i == 0 || rowTablet > parentWidthTablet) { + // item can't fit into current row, place it on next row + _this.addClass('grid-tablet-clear'); + rowTablet = tablet; + } else { + // item fits + _this.removeClass('grid-tablet-clear'); + } + }); + }, + updateBlocksMetadata: function () { + var prefix = this.closest('.PageBuilder_Field').data('name'), + groupName = this.data('name'); + this.updateGrid(); + this.find('> .PageBuilder_Value_Block_BlockGroup-Blocks > .PageBuilder_Value_Block').each(function (i) { + var _this = $(this), + name = _this.data('name'), + selector = '#' + prefix + '_' + name + '_'; + _this.find(selector + 'BlockPosition').val(i); + _this.find(selector + 'BlockParent').val(groupName); + if (_this.hasClass('PageBuilder_Value_Block_BlockGroup')) { + _this.updateBlocksMetadata(); + _this.updateGrid(); + } + }); + } + }); + $('.PageBuilder_Field .PageBuilder_Value_Block_BlockGroup.PageBuilder_Value_Block_BlockGroup_Base').entwine({ + onmatch: function () { + this.data('width-desktop-context', 12); + this.attr('data-width-desktop-context', 12); + this.data('width-tablet-context', 12); + this.attr('data-width-tablet-context', 12); + this.updateWidthContext(); + this._super(); + } + }); + $('.PageBuilder_Field .PageBuilder_Value_Block_BlockGroup-AddButton').entwine({ + onclick: function () { + var rootForm = this.getRootForm(), + //_this = this, + dialog = $('
'), + container = this.getBlockContainer(), + pageBuilder = this.getPageBuilderField(), + blocks = container.find('> .PageBuilder_Value_Block_BlockGroup-Blocks'); + dialog.PageBuilderDialog({ + contentURL: this.getConfig().urls.add, + data: $.param({ + BlockParent: container.data('name'), + BlockPosition: blocks.find('> .PageBuilder_Value_Block').length + }), + //, + //FormMergeData: { + // GroupIndex: container.data('unique-index'), + // BlockIndex: _this.getUniqueBlockIndex(), + // CreatedForClassName: rootForm.find('input[name=ClassName]').val(), + // CreatedForID: parseInt(rootForm.find('input[name=ID]').val()) + //}, + DialogEnd: function (event, data) { + var block = $(data.html); + blocks.append(block); + pageBuilder.sortableBind(); + rootForm.addClass('changed'); + if (!block.hasClass('PageBuilder_Value_Block_BlockGroup')) { + block.find('.PageBuilder_Value_Block-Edit').click(); + } + container.updateWidthContext(); + } + }); + dialog.PageBuilderDialog('open'); + } + }); + $('.PageBuilder_Value_Block-EditColumns').entwine({ + onclick: function () { + var container = this.getBlockContainer(); + container.find('> .PageBuilder_Value_Block-Widths').slideToggle(); + this.blur(); + return false; + } + }); + $('.PageBuilder_Value_Block-Delete').entwine({ + onclick: function () { + var container = this.getBlockContainer(); + container.addClass('pre-delete'); + if (confirm(this.data('confirm'))) { + var parent = this.getParentBlockContainer(); + container.remove(); + parent.updateBlocksMetadata(); + //var index = this.closest('.PageBuilder_Field-BlockGroup').index(); + //this.closest('.PageBuilder_Field-BlockGroups').removeGroup(index); + } + container.removeClass('pre-delete'); + this.blur(); + return false; + } + }); + $('.PageBuilder_Value_Block-Edit').entwine({ + onclick: function () { + var dialog = $('
'), + iframeURL = [ + this.getConfig().urls[this.data('edit-type')], + this.data('id') + ].join('/'), + updatePreviewURL = [ + this.getConfig().urls[this.data('edit-type')], + this.data('id'), + 'PageBuilderPreview' + ].join('/'), + previewElement = this.getBlockContainer().find('> .PageBuilder_Value_Block-Preview'); + dialog.ssdialog({ + iframeUrl: iframeURL, + height: 550, + beforeClose: function () { + $.get(updatePreviewURL, function (content) { + previewElement.html(content); + }); + } + }); + dialog.ssdialog('open'); + this.blur(); + return false; + } + }); + $('.PageBuilder_Field').entwine({ + onmatch: function () { + this.sortableBind(); + }, + sortableBind: function () { + var rootForm = this.getRootForm(), + base = this.find('.PageBuilder_Value_Block_BlockGroup_Base'), + groups = this.find('.PageBuilder_Value_Block_BlockGroup-Blocks'); + groups.each(function () { + if ($(this).hasClass('ui-sortable')) { + $(this).sortable('destroy'); + } + }); + groups.sortable({ + connectWith: '#' + this.prop('id') + " .PageBuilder_Value_Block_BlockGroup-Blocks", + handle: '> .PageBuilder_Value_Block-Controls > .PageBuilder_Value_Block-Reorder', + placeholder: 'PageBuilder_Value_Block', + //helper: 'clone', + //forceHelperSize: true, + forcePlaceholderSize: true, + update: function () { + base.updateBlocksMetadata(); + rootForm.addClass('changed'); + }, + customBeforeStart: function () { + //_this.find('.PageBuilder_Field-BlockGroup > *').hide() + // .filter('.PageBuilder_Field-BlockGroup-MetaFields, .PageBuilder_Field-BlockGroup-Reorder').show(); + }, + stop: function () { + //_this.find('.PageBuilder_Field-BlockGroup > *').show(); + } + }); + } + }); +}) +(jQuery); diff --git a/javascript/PageBuilderDialog.js b/javascript/PageBuilderDialog.js new file mode 100644 index 0000000..374f3d2 --- /dev/null +++ b/javascript/PageBuilderDialog.js @@ -0,0 +1,94 @@ +(function ($) { + $.widget("ssui.PageBuilderDialog", $.ui.dialog, { + DialogContentElement: null, + options: { + width: 700, + height: 600, + modal: true, + autoOpen: false, + autoPosition: true, + minWidth: 700, + maxWidth: 600, + resizable: false, + data: [] + }, + _loadContent: function (config) { + var _this = this; + this.uiDialog.addClass('loading'); + config = $.extend({ + type: 'GET', + dataType: 'json' + }, config, { + success: function (data) { + _this.uiDialog.removeClass('loading'); + if (typeof data != 'object' || !(data.html || data.DialogEnd)) { + data = { + html: data + }; + } + if (data.DialogEnd) { + _this._trigger('DialogEnd', null, data.DialogEnd); + _this.close(); + _this.DialogContentElement.remove(); + } else { + _this.DialogContentElement.html(data.html); + //var grid = _this.DialogContentElement.find('.ss-gridfield'); + //if (grid.length) { + // var input = grid.closest('form').find('[name=SelectedIDs]') + // var bindSelectHandler = function () { + // var gridItems = grid.find('.ss-gridfield-items.ui-selectable'); + // if (gridItems.length) { + // gridItems.on('selectableselected selectableunselected', function () { + // input.val($.map(gridItems.find('.ss-gridfield-item.ui-selected'), function (el) { + // return $(el).data('id'); + // }).join(',')); + // }); + // } + // }; + // bindSelectHandler(); + // grid.on('reload', bindSelectHandler); + //} + } + } + }); + $.ajax(config); + }, + _create: function () { + var _this = this; + //$.ssui.ssdialog.prototype._create.call(this); + $.ui.dialog.prototype._create.call(this); + + this.DialogContentElement = $('
'); + this.element.append(this.DialogContentElement); + //this.DialogContentElement.on('click', 'a.PageBuilderDialog-Link', function () { + // _this._loadContent({url: $(this).prop('href')}); + // return false; + //}); + // live bind submit event in case there is a form that needs to be ajax submitted + this.DialogContentElement.on('submit', 'form.PageBuilderDialog-Form', function () { + var data = $(this).serializeArray(); + //if (_this.options.FormMergeData) { + // for (var key in _this.options.FormMergeData) { + // data.push({name: key, value: _this.options.FormMergeData[key]}); + // } + //} + _this._loadContent({ + type: 'POST', + url: $(this).prop('action'), + data: $.param(data) + }); + return false; + }); + // load the initial content + this._loadContent({ + url: this.options.contentURL, + data: this.options.data + }); + }, + close: function () { + $.ui.dialog.prototype.close.call(this); + this.element.remove(); + } + }); + +}(jQuery)); diff --git a/lang/de.yml b/lang/de.yml new file mode 100644 index 0000000..1b87812 --- /dev/null +++ b/lang/de.yml @@ -0,0 +1,21 @@ +de: + PageBuilder_ContentElement: + __PLURALNAME: 'Page Builder Content Elements' + __SINGULARNAME: 'Page Builder Content Element' + PageBuilder_Field_Handler_Block: + AddFormClassName: Typ + AddFormSubmit: hinzufügen + PageBuilder_Field_Handler_ContentElement: + Submit: speichern + SubmitSuccess: 'Eintrag erfolgreich gespeichert' + PageBuilder_Value_Block: + ConfirmDelete: 'Ausgewählten Block löschen?' + field_WidthDesktop: 'Desktop Breite' + field_WidthTablet: 'Tablet Breite' + PageBuilder_Value_Block_BlockGroup: + AddButton: 'Block hinzufügen' + list_Blocks: Blöcke + PageBuilder_Value_Block_ContentElement: + Edit: 'Inhalt bearbeiten' + NoContentElement: 'Inhalt nicht gefunden' + __field_ContentElementID: 'Content Element ID' diff --git a/lang/en.yml b/lang/en.yml new file mode 100644 index 0000000..b028055 --- /dev/null +++ b/lang/en.yml @@ -0,0 +1,21 @@ +en: + PageBuilder_ContentElement: + __PLURALNAME: 'Page Builder Content Elements' + __SINGULARNAME: 'Page Builder Content Element' + PageBuilder_Field_Handler_Block: + AddFormClassName: Type + __AddFormSubmit: add + PageBuilder_Field_Handler_ContentElement: + __Submit: save + __SubmitSuccess: saved + PageBuilder_Value_Block: + __ConfirmDelete: 'Are you sure you want to delete this block?' + __field_WidthDesktop: 'Width Desktop' + __field_WidthTablet: 'Width Tablet' + PageBuilder_Value_Block_BlockGroup: + __AddButton: 'add block' + __list_Blocks: Blocks + PageBuilder_Value_Block_ContentElement: + __Edit: 'edit block content' + __NoContentElement: 'Content not found' + __field_ContentElementID: 'Content Element ID' diff --git a/scss/PageBuilder.scss b/scss/PageBuilder.scss new file mode 100644 index 0000000..4e52a40 --- /dev/null +++ b/scss/PageBuilder.scss @@ -0,0 +1,191 @@ +@mixin button-reset { + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + cursor: pointer; + background: transparent; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + -webkit-text-shadow: none; + -moz-text-shadow: none; + text-shadow: none; + border: 0; + display: block; + outline: none; + padding: 0; + margin: 0; +} + +@mixin clear-fix { + &:after { + content: " "; + display: block; + clear: both; + } +} + +@mixin grid-element($type: desktop) { + @for $i from 1 through 12 { + @for $j from $i through 12 { + .PageBuilder_Value_Block[data-width-#{$type}="#{$i}"][data-width-#{$type}-context="#{$j}"] { + width: 100% * $i / $j - 2%; + } + } + } +} + +.PageBuilder_Field { + min-width: 600px; + + .grid-controls { + float: right; + + .icon-button { + display: block; + float: left; + padding: 6px 8px; + height: 14px; + } + } + > .middleColumn { + @include clear-fix; + margin: 0 auto !important; + + *, *:before, *:after { + margin: 0; + padding: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + } + .clear { + clear: both; + } + &[data-grid-mode="desktop"] { + .grid-desktop-clear { + clear: both; + } + @include grid-element(); + .PageBuilder_Value_Block { + &[data-width-desktop="1"], &[data-width-desktop="2"], &[data-width-desktop="3"] { + .PageBuilder_Value_Block-Widths div.PageBuilder_Value_Block-Width { + width: auto; + float: none; + } + } + } + input.PageBuilder_Value_Block-WidthDesktop { + background: #DBF8FF; + } + } + &[data-grid-mode="tablet"] { + > .middleColumn { + width: 600px; + } + .grid-tablet-clear { + clear: both; + } + @include grid-element(tablet); + .PageBuilder_Value_Block { + &[data-width-tablet="1"], &[data-width-tablet="2"], &[data-width-tablet="3"], + &[data-width-tablet="4"], &[data-width-tablet="5"] { + .PageBuilder_Value_Block-Widths div.PageBuilder_Value_Block-Width { + width: auto; + float: none; + } + } + } + input.PageBuilder_Value_Block-WidthTablet { + background: #DBF8FF; + } + } + + .PageBuilder_Value_Block { + border-radius: 3px; + background: rgba(#000, .05); + border: 1px solid #CDCCD0; + padding: 8px 15px 3px !important; + float: left; + margin: 10px 1% 0 !important; + position: relative; + + &.pre-delete { + border-color: red; + } + label { + width: auto; + padding: 0 0 8px; + margin: 0; + } + div.field { + padding: 0 0 8px; + margin: 0; + border: 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + } + .PageBuilder_Value_Block-ClassNameInfo { + opacity: .5; + padding: 0; + font-size: small; + margin: 0 0 10px; + } + .PageBuilder_Value_Block-Controls { + transition: opacity 300ms ease; + position: absolute; + right: 5px; + top: 5px; + opacity: 0; + white-space: nowrap; + + > * { + display: block; + float: left; + margin: 0 4px; + padding: 2px; + + } + .PageBuilder_Value_Block-Reorder { + height: 22px; + width: 16px; + cursor: move; + background: center center no-repeat url('../images/reorder.png'); + } + button:before { + margin: 0; + } + } + .PageBuilder_Value_Block-Widths { + @include clear-fix; + display: none; + + div.PageBuilder_Value_Block-Width { + width: 49%; + float: left; + margin: 0; + + &.PageBuilder_Value_Block-WidthDesktop { + margin: 0 2% 0 0; + } + } + } + &.PageBuilder_Value_Block_BlockGroup { + .PageBuilder_Value_Block_BlockGroup-Blocks { + @include clear-fix; + padding: 0 0 30px; + } + .PageBuilder_Value_Block_BlockGroup-AddButton { + clear: both; + } + } + &:hover { + > .PageBuilder_Value_Block-Controls { + opacity: 1; + } + } + } +} diff --git a/templates/PageBuilder_CompositeField.ss b/templates/PageBuilder_CompositeField.ss new file mode 100644 index 0000000..9adc5e8 --- /dev/null +++ b/templates/PageBuilder_CompositeField.ss @@ -0,0 +1,6 @@ +<$Tag class="$extraClass" $AttributesHTML> +<% loop $FieldList %> + $FieldHolder +<% end_loop %> +<% if $Description %>$Description<% end_if %> + diff --git a/templates/PageBuilder_CompositeField_holder.ss b/templates/PageBuilder_CompositeField_holder.ss new file mode 100644 index 0000000..9adc5e8 --- /dev/null +++ b/templates/PageBuilder_CompositeField_holder.ss @@ -0,0 +1,6 @@ +<$Tag class="$extraClass" $AttributesHTML> +<% loop $FieldList %> + $FieldHolder +<% end_loop %> +<% if $Description %>$Description<% end_if %> + diff --git a/templates/PageBuilder_Field_holder.ss b/templates/PageBuilder_Field_holder.ss new file mode 100644 index 0000000..e1f6875 --- /dev/null +++ b/templates/PageBuilder_Field_holder.ss @@ -0,0 +1,16 @@ +
+
+
+ + + <%----%> +
+
+ <% if $Title %><% end_if %> +
+ $Field +
+ <% if $RightTitle %><% end_if %> + <% if $Message %>$Message<% end_if %> + <% if $Description %>$Description<% end_if %> +
diff --git a/templates/PageBuilder_Value_Block/PageBuilder_Value_Block.ss b/templates/PageBuilder_Value_Block/PageBuilder_Value_Block.ss new file mode 100644 index 0000000..93f9498 --- /dev/null +++ b/templates/PageBuilder_Value_Block/PageBuilder_Value_Block.ss @@ -0,0 +1,5 @@ +
+
+ missing {$class}.ss +
+
diff --git a/templates/PageBuilder_Value_Block/PageBuilder_Value_Block_BlockGroup.ss b/templates/PageBuilder_Value_Block/PageBuilder_Value_Block_BlockGroup.ss new file mode 100644 index 0000000..624a2e1 --- /dev/null +++ b/templates/PageBuilder_Value_Block/PageBuilder_Value_Block_BlockGroup.ss @@ -0,0 +1,7 @@ +
+
+ <% loop $BlocksForTemplate %> + $Me + <% end_loop %> +
+
diff --git a/templates/PageBuilder_Value_Block/PageBuilder_Value_Block_ContentElement.ss b/templates/PageBuilder_Value_Block/PageBuilder_Value_Block_ContentElement.ss new file mode 100644 index 0000000..00fcbf1 --- /dev/null +++ b/templates/PageBuilder_Value_Block/PageBuilder_Value_Block_ContentElement.ss @@ -0,0 +1,5 @@ +
+
+ $getContentElementForTemplate +
+