From ada42103edcd26103033d0bd8934494e2901fe25 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Tue, 6 Nov 2012 23:59:35 +0100 Subject: [PATCH] Tabs docs for CMS --- docs/en/reference/cms-architecture.md | 138 +++++++++++++++++++++++++- 1 file changed, 137 insertions(+), 1 deletion(-) diff --git a/docs/en/reference/cms-architecture.md b/docs/en/reference/cms-architecture.md index bc729cb20..519476380 100644 --- a/docs/en/reference/cms-architecture.md +++ b/docs/en/reference/cms-architecture.md @@ -110,7 +110,46 @@ before the form itself is layouted with its sibling panels to avoid incorrect di SilverStripe constructs forms and its fields within PHP, mainly through the `[getCMSFields()](api:DataObject->getCMSFields())` method. This in turn means that the CMS loads these forms as HTML via Ajax calls, -e.g. after saving a record (which requires a form refresh), or switching the section in the CMS> +e.g. after saving a record (which requires a form refresh), or switching the section in the CMS. + +Depending on where in the DOM hierarchy you want to use a form, +custom templates and additional CSS classes might be required for correct operation. +For example, the "EditForm" has specific view and logic JavaScript behaviour +which can be enabled via adding the "cms-edit-form" class. +In order to set the correct layout classes, we also need a custom template. +To obey the inheritance chain, we use `$this->getTemplatesWithSuffix('_EditForm')` for +selecting the most specific template (so `MyAdmin_EditForm.ss`, if it exists). + +Basic example form in a CMS controller subclass: + + :::php + class MyAdmin extends LeftAndMain { + function getEditForm() { + $form = new Form( + $this, + 'EditForm', + new FieldSet( + TabSet::create( + 'Root', + Tab::create('Main', + TextField::create('MyText') + ) + )->setTemplate('CMSTabset') + ), + new FieldSet( + FormAction::create('doSubmit') + ) + ); + // Required for correct CMS layout + $form->addExtraClass('cms-edit-form'); + $form->setTemplate($this->getTemplatesWithSuffix('_EditForm')); + return $form; + } + } + +Note: Usually you don't need to worry about these settings, +and will simply call `parent::getEditForm()` to modify an existing, +correctly configured form. ## JavaScript through jQuery.entwine @@ -351,6 +390,103 @@ Note that a similar tree logic is also used for the form fields to select one or more entries from those hierarchies (`[api:TreeDropdownField]` and `[api:TreeMultiselectField]`). +## Tabs + +We're using [jQuery UI tabs](http://jqueryui.com/), but in a customized fashion. +HTML with tabs can be created either directly through HTML templates in the CMS, +or indirectly through a `[api:TabSet]` form field. Since tabsets are useable +outside of the CMS as well, the baseline application of tabs happens via +a small wrapper around `jQuery.tabs()` stored in `TabSet.js`. + +In the CMS however, tabs need to do more: They memorize their active tab +in the user's browser, and lazy load content via ajax once they're activated. + +They also need to work across different "layout containers" (see above), +meaning a tab navigation might be in a layout header, while the tab +content is occupied by the main content area. jQuery assumes a common +parent in the DOM for both the tab navigation and its target DOM elements. +In order to achieve this level of flexibility, most tabsets in the CMS +use a custom template which leaves rendering the tab navigation to +a separate template: `CMSMain.ss`. See the "Forms" section above +for an example form. + +Here's how you would apply this template to your own tabsets used in the CMS. +Note that you usually only need to apply it to the outermost tabset, +since all others should render with their tab navigation inline. + +Form template with custom tab navigation (trimmed down): + + :::ss +
+ +
+ <% if Fields.hasTabset %> + <% with Fields.fieldByName('Root') %> +
+
    + <% loop Tabs %> +
  • $Title
  • + <% end_loop %> +
+
+ <% end_with %> + <% end_if %> +
+ +
+
+ <% loop Fields %>$FieldHolder<% end_loop %> +
+
+ +
+ +Tabset template without tab navigation (e.g. `CMSTabset.ss`) + + :::ss +
+ <% loop Tabs %> + <% if Tabs %> + $FieldHolder + <% else %> +
+ <% loop Fields %> + $FieldHolder + <% end_loop %> +
+ <% end_if %> + <% end_loop %> +
+ +Lazy loading works based on the `href` attribute of the tab navigation. +The base behaviour is applied through adding a class `.cms-tabset` to a container. +Assuming that each tab has its own URL which is tracked in the HTML5 history, +the current tab display also has to work when loaded directly without Ajax. +This is achieved by template conditionals (see "MyActiveCondition"). +The `.cms-panel-link` class will automatically trigger the ajax loading, +and load the HTML content into the main view. Example: + + :::ss +
+ +
+ +The URL endpoints `admin/mytabs/tab1` and `admin/mytabs/tab2` +should return HTML fragments suitable for inserting into the content area, +through the `PjaxResponseNegotiator` class (see above). + + ## Related * [Howto: Extend the CMS Interface](../howto/extend-cms-interface)